* [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
@ 2014-05-14 1:11 Thomas Abraham
2014-05-14 1:11 ` [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies Thomas Abraham
` (9 more replies)
0 siblings, 10 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
Changes since v3:
- Addressed comments from Tomasz Figa <t.figa@samsung.com>
[http://www.spinics.net/lists/cpufreq/msg09290.html]
- Rebased to v3.15-rc4
Changes since v2:
- Safe operating voltage is not required while switching APLL frequency
since the temporary parent's clock is divided down to keep armclk within
permissible limits. Thanks to Heiko Stübner <heiko@sntech.de> for this
suggesting this.
- Rob had suggested to use max frequency for each of the divider clock
outputs instead of divider values. But due to certain SoC specific
characteristics, the divider values corresponding to the input clock
frequency for the CMU_CPU clock blocks have to be used.
Changes since v1:
- Removes Exynos4x12 and Exynos5250 cpufreq driver also.
- Device tree based clock configuration lookup as suggested by Lukasz
Majewski and Tomasz Figa.
- safe operating point binding reworked as suggested by Shawn Guo.
The patch series removes the use of Exynos specific cpufreq driver and enables
the use of cpufreq-cpu0 driver for Exynos4210, Exynos4x12 and Exynos5250 based
platforms. This is being done for few reasons.
(a) The Exynos cpufreq driver reads/writes clock controller registers
bypassing the Exynos CCF driver which is sort of problematic.
(b) Removes the need for having clock controller register definitions
in the cpufreq driver and also removes the need for statically
io-remapping clock controller address space (helps in moving towards
multiplatform kernel).
Thomas Abraham (8):
cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
clk: samsung: change scope of samsung clock lock to global
clk: samsung: add infrastructure to register cpu clocks
Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
clk: exynos: use cpu-clock provider type to represent arm clock
ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data
ARM: Exynos: switch to using generic cpufreq-cpu0 driver
cpufreq: exynos: remove all exynos specific cpufreq driver support
.../devicetree/bindings/clock/exynos4-clock.txt | 37 ++
.../devicetree/bindings/clock/exynos5250-clock.txt | 36 ++
.../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 2 +
arch/arm/boot/dts/exynos4210-origen.dts | 6 +
arch/arm/boot/dts/exynos4210-trats.dts | 6 +
arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +
arch/arm/boot/dts/exynos4210.dtsi | 35 ++
arch/arm/boot/dts/exynos4212.dtsi | 18 +
arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +
arch/arm/boot/dts/exynos4412-origen.dts | 6 +
arch/arm/boot/dts/exynos4412-trats2.dts | 6 +
arch/arm/boot/dts/exynos4412.dtsi | 31 ++
arch/arm/boot/dts/exynos4x12.dtsi | 36 ++
arch/arm/boot/dts/exynos5250-arndale.dts | 6 +
arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +
arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +
arch/arm/boot/dts/exynos5250.dtsi | 41 ++
arch/arm/mach-exynos/exynos.c | 4 +-
drivers/clk/samsung/Makefile | 2 +-
drivers/clk/samsung/clk-cpu.c | 458 ++++++++++++++++++++
drivers/clk/samsung/clk-exynos4.c | 25 +-
drivers/clk/samsung/clk-exynos5250.c | 12 +-
drivers/clk/samsung/clk.c | 13 +-
drivers/clk/samsung/clk.h | 7 +
drivers/cpufreq/Kconfig | 11 +
drivers/cpufreq/Kconfig.arm | 52 ---
drivers/cpufreq/Makefile | 4 -
drivers/cpufreq/cpufreq-cpu0.c | 5 +
drivers/cpufreq/exynos-cpufreq.c | 209 ---------
drivers/cpufreq/exynos-cpufreq.h | 91 ----
drivers/cpufreq/exynos4210-cpufreq.c | 157 -------
drivers/cpufreq/exynos4x12-cpufreq.c | 211 ---------
drivers/cpufreq/exynos5250-cpufreq.c | 183 --------
include/dt-bindings/clock/exynos5250.h | 1 +
34 files changed, 799 insertions(+), 936 deletions(-)
create mode 100644 drivers/clk/samsung/clk-cpu.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.h
delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos4x12-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos5250-cpufreq.c
--
1.7.4.4
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-14 3:46 ` Viresh Kumar
2014-05-14 1:11 ` [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global Thomas Abraham
` (8 subsequent siblings)
9 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
Lookup for the optional boost-frequency property in cpu0 node and if
available, enable support for boost mode frequencies. The frequencies
usable in boost mode are determined while preparing the cpufreq table
from the list of operating points available.
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
.../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 2 ++
drivers/cpufreq/Kconfig | 11 +++++++++++
drivers/cpufreq/cpufreq-cpu0.c | 5 +++++
3 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index f055515..60f321a 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -19,6 +19,8 @@ Optional properties:
- cooling-min-level:
- cooling-max-level:
Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
+- boost-frequency:
+ Please refer to Documentation/devicetree/bindings/cpufreq/cpufreq-boost.txt
Examples:
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 1fbe11f..0ca4485 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -194,6 +194,17 @@ config GENERIC_CPUFREQ_CPU0
If in doubt, say N.
+config GENERIC_CPUFREQ_CPU0_BOOST
+ bool "Boost frequency support for generic CPU0 cpufreq driver"
+ depends on GENERIC_CPUFREQ_CPU0
+ select CPU_FREQ_BOOST_SW
+ help
+ This enables support for software managed overclocking (BOOST). It
+ allows usage of special frequencies (those beyond the normal operating
+ frequencies).
+
+ If in doubt, say N.
+
menu "x86 CPU frequency scaling drivers"
depends on X86
source "drivers/cpufreq/Kconfig.x86"
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 1bf6bba..e6c21a8 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -194,6 +194,11 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
transition_latency += ret * 1000;
}
+#ifdef CONFIG_GENERIC_CPUFREQ_CPU0_BOOST
+ if (of_find_property(cpu_dev->of_node, "boost-frequency", NULL))
+ cpu0_cpufreq_driver.boost_supported = true;
+#endif
+
ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
if (ret) {
pr_err("failed register driver: %d\n", ret);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
2014-05-14 1:11 ` [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-14 3:50 ` Viresh Kumar
2014-05-16 12:30 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks Thomas Abraham
` (7 subsequent siblings)
9 siblings, 2 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
Access to samsung clock lock is required to support newer samsung specific
clock types. So change the scope of the samsung clock lock to global. And
prefix 'samsung_clk_' to the existing name of the lock to prevent name space
pollution.
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/clk/samsung/clk.c | 13 ++++++++-----
drivers/clk/samsung/clk.h | 2 ++
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 91bec3e..c86c28c 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -14,7 +14,7 @@
#include <linux/syscore_ops.h>
#include "clk.h"
-static DEFINE_SPINLOCK(lock);
+DEFINE_SPINLOCK(samsung_clk_lock);
static struct clk **clk_table;
static void __iomem *reg_base;
#ifdef CONFIG_OF
@@ -173,7 +173,8 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_mux(NULL, list->name, list->parent_names,
list->num_parents, list->flags, reg_base + list->offset,
- list->shift, list->width, list->mux_flags, &lock);
+ list->shift, list->width, list->mux_flags,
+ &samsung_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
@@ -206,12 +207,13 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
list->parent_name, list->flags,
reg_base + list->offset, list->shift,
list->width, list->div_flags,
- list->table, &lock);
+ list->table, &samsung_clk_lock);
else
clk = clk_register_divider(NULL, list->name,
list->parent_name, list->flags,
reg_base + list->offset, list->shift,
- list->width, list->div_flags, &lock);
+ list->width, list->div_flags,
+ &samsung_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
@@ -241,7 +243,8 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_gate(NULL, list->name, list->parent_name,
list->flags, reg_base + list->offset,
- list->bit_idx, list->gate_flags, &lock);
+ list->bit_idx, list->gate_flags,
+ &samsung_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index c7141ba..951bc85 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -21,6 +21,8 @@
#include <linux/of_address.h>
#include "clk-pll.h"
+extern spinlock_t samsung_clk_lock;
+
/**
* struct samsung_clock_alias: information about mux clock
* @id: platform specific id of the clock.
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
2014-05-14 1:11 ` [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies Thomas Abraham
2014-05-14 1:11 ` [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-15 18:18 ` Doug Anderson
2014-05-16 17:17 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5 Thomas Abraham
` (6 subsequent siblings)
9 siblings, 2 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
The CPU clock provider supplies the clock to the CPU clock domain. The
composition and organization of the CPU clock provider could vary among
Exynos SoCs. A CPU clock provider can be composed of clock mux, dividers
and gates. This patch defines a new clock type for CPU clock provider and
adds infrastructure to register the CPU clock providers for Samsung
platforms.
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/clk/samsung/Makefile | 2 +-
drivers/clk/samsung/clk-cpu.c | 458 +++++++++++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk.h | 5 +
3 files changed, 464 insertions(+), 1 deletions(-)
create mode 100644 drivers/clk/samsung/clk-cpu.c
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 8eb4799..e2b453f 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -2,7 +2,7 @@
# Samsung Clock specific Makefile
#
-obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
+obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
new file mode 100644
index 0000000..6a40862
--- /dev/null
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * 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.
+ *
+ * This file contains the utility functions to register the cpu clocks
+ * for samsung platforms.
+*/
+
+#include <linux/errno.h>
+#include "clk.h"
+
+#define SRC_CPU 0x0
+#define STAT_CPU 0x200
+#define DIV_CPU0 0x300
+#define DIV_CPU1 0x304
+#define DIV_STAT_CPU0 0x400
+#define DIV_STAT_CPU1 0x404
+
+#define MAX_DIV 8
+
+#define EXYNOS4210_ARM_DIV1(div) ((div & 0x7) + 1)
+#define EXYNOS4210_ARM_DIV2(div) (((div >> 28) & 0x7) + 1)
+
+#define EXYNOS4210_DIV_CPU0(d5, d4, d3, d2, d1, d0) \
+ ((d5 << 24) | (d4 << 20) | (d3 << 16) | (d2 << 12) | \
+ (d1 << 8) | (d0 << 4))
+#define EXYNOS4210_DIV_CPU1(d2, d1, d0) \
+ ((d2 << 8) | (d1 << 4) | (d0 << 0))
+
+#define EXYNOS4210_DIV1_HPM_MASK ((0x7 << 0) | (0x7 << 4))
+#define EXYNOS4210_MUX_HPM_MASK (1 << 20)
+
+/**
+ * struct exynos4210_armclk_data: config data to setup exynos4210 cpu clocks.
+ * @prate: frequency of the parent clock.
+ * @div0: value to be programmed in the div_cpu0 register.
+ * @div1: value to be programmed in the div_cpu1 register.
+ *
+ * This structure holds the divider configuration data for divider clocks
+ * belonging to the CMU_CPU clock domain. The parent frequency at which these
+ * divider values are vaild is specified in @prate.
+ */
+struct exynos4210_armclk_data {
+ unsigned long prate;
+ unsigned int div0;
+ unsigned int div1;
+};
+
+/**
+ * struct exynos_cpuclk: information about clock supplied to a CPU core.
+ * @hw: handle between ccf and cpu clock.
+ * @alt_parent: alternate parent clock to use when switching the speed
+ * of the primary parent clock.
+ * @ctrl_base: base address of the clock controller.
+ * @offset: offset from the ctrl_base address where the cpu clock div/mux
+ * registers can be accessed.
+ * @clk_nb: clock notifier registered for changes in clock speed of the
+ * primary parent clock.
+ * @lock: register access lock.
+ * @data: optional data which the acutal instantiation of this clock
+ * can use.
+ */
+struct exynos_cpuclk {
+ struct clk_hw hw;
+ struct clk *alt_parent;
+ void __iomem *ctrl_base;
+ unsigned long offset;
+ struct notifier_block clk_nb;
+ spinlock_t *lock;
+ void *data;
+};
+
+#define to_exynos_cpuclk_hw(hw) container_of(hw, struct exynos_cpuclk, hw)
+#define to_exynos_cpuclk_nb(nb) container_of(nb, struct exynos_cpuclk, clk_nb)
+
+/**
+ * struct exynos_cpuclk_soc_data: soc specific data for cpu clocks.
+ * @parser: pointer to a function that can parse SoC specific data.
+ * @ops: clock operations to be used for this clock.
+ * @offset: optional offset from base of clock controller register base, to
+ * be used when accessing clock controller registers related to the
+ * cpu clock.
+ * @clk_cb: the clock notifier callback to be called for changes in the
+ * clock rate of the primary parent clock.
+ *
+ * This structure provides SoC specific data for ARM clocks. Based on
+ * the compatible value of the clock controller node, the value of the
+ * fields in this structure can be populated.
+ */
+struct exynos_cpuclk_soc_data {
+ int (*parser)(struct device_node *, void **);
+ const struct clk_ops *ops;
+ unsigned int offset;
+ int (*clk_cb)(struct notifier_block *nb, unsigned long evt, void *data);
+};
+
+/* common round rate callback useable for all types of cpu clocks */
+static long exynos_cpuclk_round_rate(struct clk_hw *hw,
+ unsigned long drate, unsigned long *prate)
+{
+ struct clk *parent = __clk_get_parent(hw->clk);
+ unsigned long max_prate = __clk_round_rate(parent, UINT_MAX);
+ unsigned long t_prate, div = 1, best_div = 1;
+ unsigned long delta, min_delta = UINT_MAX;
+
+ do {
+ t_prate = __clk_round_rate(parent, drate * div);
+ delta = drate - (t_prate / div);
+ if (delta < min_delta) {
+ *prate = t_prate;
+ best_div = div;
+ min_delta = delta;
+ }
+ if (!delta)
+ break;
+ div++;
+ } while ((drate * div) < max_prate && div <= MAX_DIV);
+
+ return *prate / best_div;
+}
+
+static unsigned long _calc_div(unsigned long prate, unsigned long drate)
+{
+ unsigned long div = prate / drate;
+
+ WARN_ON(div >= MAX_DIV);
+ return (!(prate % drate)) ? div-- : div;
+}
+
+/* helper function to register a cpu clock */
+static int __init exynos_cpuclk_register(unsigned int lookup_id,
+ const char *name, const char **parents,
+ unsigned int num_parents, void __iomem *base,
+ const struct exynos_cpuclk_soc_data *soc_data,
+ struct device_node *np, const struct clk_ops *ops,
+ spinlock_t *lock)
+{
+ struct exynos_cpuclk *cpuclk;
+ struct clk_init_data init;
+ struct clk *clk;
+ int ret;
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ if (!cpuclk) {
+ pr_err("%s: could not allocate memory for %s clock\n",
+ __func__, name);
+ return -ENOMEM;
+ }
+
+ init.name = name;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = parents;
+ init.num_parents = 1;
+ init.ops = ops;
+
+ cpuclk->hw.init = &init;
+ cpuclk->ctrl_base = base;
+ cpuclk->lock = lock;
+
+ ret = soc_data->parser(np, &cpuclk->data);
+ if (ret) {
+ pr_err("%s: error %d in parsing %s clock data",
+ __func__, ret, name);
+ ret = -EINVAL;
+ goto free_cpuclk;
+ }
+ cpuclk->offset = soc_data->offset;
+ init.ops = soc_data->ops;
+
+ cpuclk->clk_nb.notifier_call = soc_data->clk_cb;
+ if (clk_notifier_register(__clk_lookup(parents[0]), &cpuclk->clk_nb)) {
+ pr_err("%s: failed to register clock notifier for %s\n",
+ __func__, name);
+ goto free_cpuclk_data;
+ }
+
+ cpuclk->alt_parent = __clk_lookup(parents[1]);
+ if (!cpuclk->alt_parent) {
+ pr_err("%s: could not lookup alternate parent %s\n",
+ __func__, parents[1]);
+ ret = -EINVAL;
+ goto free_cpuclk_data;
+ }
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: could not register cpuclk %s\n", __func__, name);
+ ret = PTR_ERR(clk);
+ goto free_cpuclk_data;
+ }
+
+ samsung_clk_add_lookup(clk, lookup_id);
+ return 0;
+
+free_cpuclk_data:
+ kfree(cpuclk->data);
+free_cpuclk:
+ kfree(cpuclk);
+ return ret;
+}
+
+static void _exynos4210_set_armclk_div(void __iomem *base, unsigned long div)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+ writel((readl(base + DIV_CPU0) & ~0x7) | div, base + DIV_CPU0);
+ while (time_before(jiffies, timeout))
+ if (!readl(base + DIV_STAT_CPU0))
+ return;
+ pr_err("%s: timeout in divider stablization\n", __func__);
+}
+
+static unsigned long exynos4210_armclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
+ void __iomem *base = armclk->ctrl_base + armclk->offset;
+ unsigned long div0 = readl(base + DIV_CPU0);
+
+ return parent_rate / EXYNOS4210_ARM_DIV1(div0) /
+ EXYNOS4210_ARM_DIV2(div0);
+}
+
+static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data *ndata,
+ struct exynos_cpuclk *armclk, void __iomem *base)
+{
+ struct exynos4210_armclk_data *armclk_data = armclk->data;
+ unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
+ unsigned long alt_div, div0, div1, tdiv0, mux_reg;
+ unsigned long cur_armclk_rate, timeout;
+ unsigned long flags;
+
+ /* find out the divider values to use for clock data */
+ while (armclk_data->prate != ndata->new_rate) {
+ if (armclk_data->prate == 0)
+ return -EINVAL;
+ armclk_data++;
+ }
+
+ div0 = armclk_data->div0;
+ div1 = armclk_data->div1;
+ if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
+ div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
+ div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
+ }
+
+ /*
+ * if the new and old parent clock speed is less than the clock speed
+ * of the alternate parent, then it should be ensured that at no point
+ * the armclk speed is more than the old_prate until the dividers are
+ * set.
+ */
+ tdiv0 = readl(base + DIV_CPU0);
+ cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
+ EXYNOS4210_ARM_DIV2(tdiv0);
+ if (alt_prate > cur_armclk_rate) {
+ alt_div = _calc_div(alt_prate, cur_armclk_rate);
+ _exynos4210_set_armclk_div(base, alt_div);
+ div0 |= alt_div;
+ }
+
+ /* select sclk_mpll as the alternate parent */
+ spin_lock_irqsave(armclk->lock, flags);
+ mux_reg = readl(base + SRC_CPU);
+ writel(mux_reg | (1 << 16), base + SRC_CPU);
+
+ timeout = jiffies + msecs_to_jiffies(10);
+ while (time_before(jiffies, timeout))
+ if (((readl(base + STAT_CPU) >> 16) & 0x7) == 2)
+ break;
+ spin_unlock_irqrestore(armclk->lock, flags);
+
+ if (((readl(base + STAT_CPU) >> 16) & 0x7) != 2)
+ pr_err("%s: re-parenting to sclk_mpll failed\n", __func__);
+
+ /* alternate parent is active now. set the dividers */
+ writel(div0, base + DIV_CPU0);
+ timeout = jiffies + msecs_to_jiffies(10);
+ while (time_before(jiffies, timeout))
+ if (!readl(base + DIV_STAT_CPU0))
+ break;
+
+ if (readl(base + DIV_STAT_CPU0))
+ pr_err("%s: timeout in divider0 stablization\n", __func__);
+
+ writel(div1, base + DIV_CPU1);
+ timeout = jiffies + msecs_to_jiffies(10);
+ while (time_before(jiffies, timeout))
+ if (!readl(base + DIV_STAT_CPU1))
+ break;
+ if (readl(base + DIV_STAT_CPU1))
+ pr_err("%s: timeout in divider1 stablization\n", __func__);
+
+ return 0;
+}
+
+static int exynos4210_armclk_post_rate_change(struct exynos_cpuclk *armclk,
+ void __iomem *base)
+{
+ unsigned long mux_reg, flags;
+ unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+ spin_lock_irqsave(armclk->lock, flags);
+ mux_reg = readl(base + SRC_CPU);
+ writel(mux_reg & ~(1 << 16), base + SRC_CPU);
+ while (time_before(jiffies, timeout))
+ if (((readl(base + STAT_CPU) >> 16) & 0x7) == 1)
+ break;
+ spin_unlock_irqrestore(armclk->lock, flags);
+
+ if (((readl(base + STAT_CPU) >> 16) & 0x7) != 1)
+ pr_err("%s: re-parenting to mout_apll failed\n", __func__);
+
+ return 0;
+}
+
+/*
+ * This clock notifier is called when the frequency of the parent clock
+ * of armclk is to be changed. This notifier handles the setting up all
+ * the divider clocks, remux to temporary parent and handling the safe
+ * frequency levels when using temporary parent.
+ */
+static int exynos4210_armclk_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct clk_notifier_data *ndata = data;
+ struct exynos_cpuclk *armclk = to_exynos_cpuclk_nb(nb);
+ void __iomem *base = armclk->ctrl_base + armclk->offset;
+ int err = 0;
+
+ if (event == PRE_RATE_CHANGE)
+ err = exynos4210_armclk_pre_rate_change(ndata, armclk, base);
+ else if (event == POST_RATE_CHANGE)
+ err = exynos4210_armclk_post_rate_change(armclk, base);
+
+ return notifier_from_errno(err);
+}
+
+static int exynos4210_armclk_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
+ void __iomem *base = armclk->ctrl_base + armclk->offset;
+ unsigned long div;
+
+ div = drate < prate ? _calc_div(prate, drate) : 0;
+ _exynos4210_set_armclk_div(base, div);
+ return 0;
+}
+
+static const struct clk_ops exynos4210_armclk_clk_ops = {
+ .recalc_rate = exynos4210_armclk_recalc_rate,
+ .round_rate = exynos_cpuclk_round_rate,
+ .set_rate = exynos4210_armclk_set_rate,
+};
+
+/*
+ * parse divider configuration data from dt for all the cpu clock domain
+ * clocks in exynos4210 and compatible SoC's.
+ */
+static int __init exynos4210_armclk_parser(struct device_node *np, void **data)
+{
+ struct exynos4210_armclk_data *tdata;
+ u32 cfg[10], num_rows, row, col;
+ struct property *prop;
+ const __be32 *ptr = NULL;
+ u32 cells;
+ int ret;
+
+ if (of_property_read_u32(np, "samsung,armclk-cells", &cells))
+ return -EINVAL;
+ prop = of_find_property(np, "samsung,armclk-divider-table", NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -EINVAL;
+ if ((prop->length / sizeof(u32)) % cells)
+ return -EINVAL;
+ num_rows = (prop->length / sizeof(u32)) / cells;
+
+ /* allocate a zero terminated table */
+ *data = kzalloc(sizeof(*tdata) * (num_rows + 1), GFP_KERNEL);
+ if (!*data)
+ ret = -ENOMEM;
+ tdata = *data;
+
+ for (row = 0; row < num_rows; row++, tdata++) {
+ for (col = 0; col < cells; col++)
+ ptr = of_prop_next_u32(prop, ptr, &cfg[col]);
+
+ tdata->prate = cfg[0] * 1000;
+ tdata->div0 = EXYNOS4210_DIV_CPU0(cfg[6], cfg[5], cfg[4],
+ cfg[3], cfg[2], cfg[1]);
+ tdata->div1 = cells == 10 ?
+ EXYNOS4210_DIV_CPU1(cfg[9], cfg[8], cfg[7]) :
+ EXYNOS4210_DIV_CPU1(0, cfg[8], cfg[7]);
+ }
+ tdata->prate = 0;
+ return 0;
+}
+
+static const struct exynos_cpuclk_soc_data exynos4210_cpuclk_soc_data = {
+ .parser = exynos4210_armclk_parser,
+ .ops = &exynos4210_armclk_clk_ops,
+ .offset = 0x14200,
+ .clk_cb = exynos4210_armclk_notifier_cb,
+};
+
+static const struct exynos_cpuclk_soc_data exynos5250_cpuclk_soc_data = {
+ .parser = exynos4210_armclk_parser,
+ .ops = &exynos4210_armclk_clk_ops,
+ .offset = 0x200,
+ .clk_cb = exynos4210_armclk_notifier_cb,
+};
+
+static const struct of_device_id exynos_clock_ids_armclk[] = {
+ { .compatible = "samsung,exynos4210-clock",
+ .data = &exynos4210_cpuclk_soc_data, },
+ { .compatible = "samsung,exynos4412-clock",
+ .data = &exynos4210_cpuclk_soc_data, },
+ { .compatible = "samsung,exynos5250-clock",
+ .data = &exynos5250_cpuclk_soc_data, },
+ { },
+};
+
+/**
+ * exynos_register_arm_clock: register arm clock with ccf.
+ * @lookup_id: armclk clock output id for the clock controller.
+ * @parent_names: name of the parent clock for armclk.
+ * @num_parents: number of parents in the @parent_names array.
+ * @base: base address of the clock controller from which armclk is generated.
+ * @np: device tree node pointer of the clock controller (optional).
+ * @ops: clock ops for this clock (optional).
+ * @lock: register access lock.
+ */
+int __init exynos_register_arm_clock(unsigned int lookup_id,
+ const char **parent_names, unsigned int num_parents,
+ void __iomem *base, struct device_node *np, struct clk_ops *ops,
+ spinlock_t *lock)
+{
+ const struct of_device_id *match;
+ const struct exynos_cpuclk_soc_data *data = NULL;
+
+ if (!np)
+ return -EINVAL;
+
+ match = of_match_node(exynos_clock_ids_armclk, np);
+ if (!match)
+ return -EINVAL;
+
+ data = match->data;
+ return exynos_cpuclk_register(lookup_id, "armclk", parent_names,
+ num_parents, base, data, np, ops, lock);
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 951bc85..10e0a8d 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -350,4 +350,9 @@ extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
const unsigned long *rdump,
unsigned long nr_rdump);
+int __init exynos_register_arm_clock(unsigned int lookup_id,
+ const char **parent_names, unsigned int num_parents,
+ void __iomem *base, struct device_node *np,
+ struct clk_ops *ops, spinlock_t *lock);
+
#endif /* __SAMSUNG_CLK_H */
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (2 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-16 23:24 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock Thomas Abraham
` (5 subsequent siblings)
9 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
From; Thomas Abraham <thomas.ab@samsung.com>
The clock blocks within the CMU_CPU clock domain are put together into a
new composite clock type called the cpu clock. This clock type requires
configuration data that will be atomically programmed in the multiple
clock blocks encapsulated within the cpu clock type when the parent clock
frequency is changed. This configuration data is held in the clock controller
node. Update clock binding documentation about this configuration data format
for Samsung Exynos4 and Exynos5 platforms.
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
.../devicetree/bindings/clock/exynos4-clock.txt | 37 ++++++++++++++++++++
.../devicetree/bindings/clock/exynos5250-clock.txt | 36 +++++++++++++++++++
2 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
index f5a5b19..0934e02 100644
--- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -15,6 +15,35 @@ Required Properties:
- #clock-cells: should be 1.
+- samsung,armclk-divider-table: when the frequency of the APLL is changed
+ the divider clocks in CMU_CPU clock domain also need to be updated. These
+ divider clocks have SoC specific divider clock output requirements for a
+ specific APLL clock speeds. When APLL clock rate is changed, these divider
+ clocks are reprogrammed with pre-determined values in order to maintain the
+ SoC specific divider clock outputs. This property lists the divider values
+ for divider clocks in the CMU_CPU block for supported APLL clock speeds.
+ The format of each entry included in the arm-frequency-table should be
+ as defined below
+
+ - for Exynos4210 and Exynos4212 based platforms:
+ cell #1: arm clock parent frequency
+ cell #2 ~ cell 9#: value of clock divider in the following order
+ corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
+ pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio.
+
+ - for Exynos4412 based platforms:
+ cell #1: expected arm clock parent frequency
+ cell #2 ~ cell #10: value of clock divider in the following order
+ corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
+ pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio, cores_ratio
+
+- samsung,armclk-cells: defines the number of cells in
+ samsung,armclk-divider-table property. The value of this property depends on
+ the SoC type.
+
+ - for Exynos4210 and Exynos4212: the value should be 9.
+ - for Exynos4412: the value should be 10.
+
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume.
@@ -28,6 +57,14 @@ Example 1: An example of a clock controller node is listed below.
compatible = "samsung,exynos4210-clock";
reg = <0x10030000 0x20000>;
#clock-cells = <1>;
+
+ samsung,armclk-cells = <9>;
+ samsung,armclk-divider-table = <1200000 3 7 3 4 1 7 5 0>,
+ <1000000 3 7 3 4 1 7 4 0>,
+ < 800000 3 7 3 3 1 7 3 0>,
+ < 500000 3 7 3 3 1 7 3 0>,
+ < 400000 3 7 3 3 1 7 3 0>,
+ < 200000 1 3 1 1 1 0 3 0>;
};
Example 2: UART controller node that consumes the clock generated by the clock
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
index 536eacd..3d63d09 100644
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -13,6 +13,24 @@ Required Properties:
- #clock-cells: should be 1.
+- samsung,armclk-divider-table: when the frequency of the APLL is changed
+ the divider clocks in CMU_CPU clock domain also need to be updated. These
+ divider clocks have SoC specific divider clock output requirements for a
+ specific APLL clock speeds. When APLL clock rate is changed, these divider
+ clocks are reprogrammed with pre-determined values in order to maintain the
+ SoC specific divider clock outputs. This property lists the divider values
+ for divider clocks in the CMU_CPU block for supported APLL clock speeds.
+ The format of each entry included in the arm-frequency-table should be
+ as defined below
+
+ cell #1: expected arm clock parent frequency
+ cell #2 ~ cell #9: value of clock divider in the following order
+ cpud_ratio, acp_ratio, periph_ratio, atb_ratio,
+ pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio
+
+- samsung,armclk-cells: defines the number of cells in
+ samsung,armclk-divider-table property. The value of this property should be 9.
+
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume.
@@ -26,6 +44,24 @@ Example 1: An example of a clock controller node is listed below.
compatible = "samsung,exynos5250-clock";
reg = <0x10010000 0x30000>;
#clock-cells = <1>;
+
+ samsung,armclk-cells = <9>;
+ samsung,armclk-divider-table = <1700000 3 7 7 7 3 5 0 2>,
+ <1600000 3 7 7 7 1 4 0 2>,
+ <1500000 2 7 7 7 1 4 0 2>,
+ <1400000 2 7 7 6 1 4 0 2>,
+ <1300000 2 7 7 6 1 3 0 2>,
+ <1200000 2 7 7 5 1 3 0 2>,
+ <1100000 3 7 7 5 1 3 0 2>,
+ <1000000 1 7 7 4 1 2 0 2>,
+ < 900000 1 7 7 4 1 2 0 2>,
+ < 800000 1 7 7 4 1 2 0 2>,
+ < 700000 1 7 7 3 1 1 0 2>,
+ < 600000 1 7 7 3 1 1 0 2>,
+ < 500000 1 7 7 2 1 1 0 2>,
+ < 400000 1 7 7 2 1 1 0 2>,
+ < 300000 1 7 7 1 1 1 0 2>,
+ < 200000 1 7 7 1 1 1 0 2>;
};
Example 2: UART controller node that consumes the clock generated by the clock
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (3 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5 Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-14 21:37 ` Mike Turquette
2014-05-16 23:57 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data Thomas Abraham
` (4 subsequent siblings)
9 siblings, 2 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
With the addition of the new Samsung specific cpu-clock type, the
arm clock can be represented as a cpu-clock type and the independent
clock blocks that made up the arm clock can be removed.
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 25 +++++++++----------------
drivers/clk/samsung/clk-exynos5250.c | 12 ++++++------
include/dt-bindings/clock/exynos5250.h | 1 +
3 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index b4f9672..7e3bb16c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -471,7 +471,6 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
- MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
@@ -530,7 +529,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
- MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
@@ -572,8 +570,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
/* list of divider clocks supported in all exynos4 soc's */
static struct samsung_div_clock exynos4_div_clks[] __initdata = {
- DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
- DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
@@ -619,8 +615,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
- DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
- DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
+ DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
+ CLK_GET_RATE_NOCACHE, 0),
DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
CLK_SET_RATE_PARENT, 0),
DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
@@ -1003,12 +999,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
0),
};
-static struct samsung_clock_alias exynos4_aliases[] __initdata = {
- ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
- ALIAS(CLK_ARM_CLK, NULL, "armclk"),
- ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
-};
-
static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
};
@@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4210_gate_clks));
samsung_clk_register_alias(exynos4210_aliases,
ARRAY_SIZE(exynos4210_aliases));
+ exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4210,
+ ARRAY_SIZE(mout_core_p4210), reg_base, np, NULL,
+ &samsung_clk_lock);
} else {
samsung_clk_register_mux(exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks));
@@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4x12_gate_clks));
samsung_clk_register_alias(exynos4x12_aliases,
ARRAY_SIZE(exynos4x12_aliases));
+ exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4x12,
+ ARRAY_SIZE(mout_core_p4x12), reg_base, np, NULL,
+ &samsung_clk_lock);
}
- samsung_clk_register_alias(exynos4_aliases,
- ARRAY_SIZE(exynos4_aliases));
-
exynos4_clk_sleep_init();
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
@@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
_get_rate("sclk_apll"), _get_rate("sclk_mpll"),
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
- _get_rate("arm_clk"));
+ _get_rate("armclk"));
}
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index e7ee442..3fe1ca0 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -260,8 +260,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
*/
MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
CLK_SET_RATE_PARENT, 0, "mout_apll"),
- MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
-
/*
* CMU_CORE
*/
@@ -339,9 +337,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
/*
* CMU_CPU
*/
- DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
- DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
- DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
+ DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
+ CLK_GET_RATE_NOCACHE, 0),
/*
* CMU_TOP
@@ -721,10 +718,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
ARRAY_SIZE(exynos5250_div_clks));
samsung_clk_register_gate(exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
+ exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
+ ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
+ &samsung_clk_lock);
exynos5250_clk_sleep_init();
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
- _get_rate("div_arm2"));
+ _get_rate("armclk"));
}
CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h
index 922f2dc..59a10fb 100644
--- a/include/dt-bindings/clock/exynos5250.h
+++ b/include/dt-bindings/clock/exynos5250.h
@@ -21,6 +21,7 @@
#define CLK_FOUT_CPLL 6
#define CLK_FOUT_EPLL 7
#define CLK_FOUT_VPLL 8
+#define CLK_ARM_CLK 12
/* gate for special clocks (sclk) */
#define CLK_SCLK_CAM_BAYER 128
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (4 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-16 23:16 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver Thomas Abraham
` (3 subsequent siblings)
9 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
For all Exynos based platforms, add CPU nodes, operating points and cpu
clock data for migrating from Exynos specific cpufreq driver to using
generic cpufreq-cpu0 driver.
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
arch/arm/boot/dts/exynos4210-origen.dts | 6 +++
arch/arm/boot/dts/exynos4210-trats.dts | 6 +++
arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +++
arch/arm/boot/dts/exynos4210.dtsi | 35 +++++++++++++++++++
arch/arm/boot/dts/exynos4212.dtsi | 18 ++++++++++
arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +++
arch/arm/boot/dts/exynos4412-origen.dts | 6 +++
arch/arm/boot/dts/exynos4412-trats2.dts | 6 +++
arch/arm/boot/dts/exynos4412.dtsi | 31 +++++++++++++++++
arch/arm/boot/dts/exynos4x12.dtsi | 36 ++++++++++++++++++++
arch/arm/boot/dts/exynos5250-arndale.dts | 6 +++
arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +++
arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +++
arch/arm/boot/dts/exynos5250.dtsi | 41 +++++++++++++++++++++++
14 files changed, 215 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 72fb11f..4324b25 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -32,6 +32,12 @@
bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck1_reg>;
+ };
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 63aa2bb..7cc0a57 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -30,6 +30,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
};
+ cpus {
+ cpu: cpu@0 {
+ cpu0-supply = <&varm_breg>;
+ };
+ };
+
regulators {
compatible = "simple-bus";
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index 63e34b2..844f3fb 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -28,6 +28,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
};
+ cpus {
+ cpu: cpu@0 {
+ cpu0-supply = <&vdd_arm_reg>;
+ };
+ };
+
mct@10050000 {
compatible = "none";
};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index cacf614..22b967d 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -36,6 +36,33 @@
reg = <0x10023CA0 0x20>;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ clocks = <&clock CLK_ARM_CLK>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 1200000 1250000
+ 1000000 1150000
+ 800000 1075000
+ 500000 975000
+ 400000 975000
+ 200000 950000
+ >;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
gic: interrupt-controller@10490000 {
cpu-offset = <0x8000>;
};
@@ -73,6 +100,14 @@
compatible = "samsung,exynos4210-clock";
reg = <0x10030000 0x20000>;
#clock-cells = <1>;
+
+ samsung,armclk-cells = <9>;
+ samsung,armclk-divider-table = <1200000 3 7 3 4 1 7 5 0>,
+ <1000000 3 7 3 4 1 7 4 0>,
+ < 800000 3 7 3 3 1 7 3 0>,
+ < 500000 3 7 3 3 1 7 3 0>,
+ < 400000 3 7 3 3 1 7 3 0>,
+ < 200000 1 3 1 1 1 0 3 0>;
};
pmu {
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index 3c00e6e..87847d5 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -22,6 +22,24 @@
/ {
compatible = "samsung,exynos4212", "samsung,exynos4";
+ clock: clock-controller@10030000 {
+ samsung,armclk-cells = <9>;
+ samsung,armclk-divider-table = <1500000 3 7 0 6 1 2 6 0>,
+ <1400000 3 7 0 6 1 2 6 0>,
+ <1300000 3 7 0 5 1 2 5 0>,
+ <1200000 3 7 0 5 1 2 5 0>,
+ <1100000 3 6 0 4 1 2 4 0>,
+ <1000000 2 5 0 4 1 1 4 0>,
+ < 900000 2 5 0 3 1 1 3 0>,
+ < 800000 2 5 0 3 1 1 3 0>,
+ < 700000 2 4 0 3 1 1 3 0>,
+ < 600000 2 4 0 3 1 1 3 0>,
+ < 500000 2 4 0 3 1 1 3 0>,
+ < 400000 2 4 0 3 1 1 3 0>,
+ < 300000 2 4 0 2 1 1 3 0>,
+ < 200000 1 3 0 1 1 1 3 0>;
+ };
+
combiner: interrupt-controller@10440000 {
samsung,combiner-nr = <18>;
};
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 31db28a..4671714 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -22,6 +22,12 @@
reg = <0x40000000 0x40000000>;
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
leds {
compatible = "gpio-leds";
led1 {
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index e2c0dca..442bf90 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -27,6 +27,12 @@
bootargs ="console=ttySAC2,115200";
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
firmware@0203F000 {
compatible = "samsung,secure-firmware";
reg = <0x0203F000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 9583563..6567c9d 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -31,6 +31,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
firmware@0204F000 {
compatible = "samsung,secure-firmware";
reg = <0x0204F000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index 15d3c0a..85005d1 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -22,6 +22,37 @@
/ {
compatible = "samsung,exynos4412", "samsung,exynos4";
+ cpus {
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ };
+ };
+
+ clock: clock-controller@10030000 {
+ samsung,armclk-cells = <10>;
+ samsung,armclk-divider-table = <1500000 3 7 0 6 1 2 6 0 7>,
+ <1400000 3 7 0 6 1 2 6 0 6>,
+ <1300000 3 7 0 5 1 2 5 0 6>,
+ <1200000 3 7 0 5 1 2 5 0 5>,
+ <1100000 3 6 0 4 1 2 4 0 5>,
+ <1000000 2 5 0 4 1 1 4 0 4>,
+ < 900000 2 5 0 3 1 1 3 0 4>,
+ < 800000 2 5 0 3 1 1 3 0 3>,
+ < 700000 2 4 0 3 1 1 3 0 3>,
+ < 600000 2 4 0 3 1 1 3 0 2>,
+ < 500000 2 4 0 3 1 1 3 0 2>,
+ < 400000 2 4 0 3 1 1 3 0 1>,
+ < 300000 2 4 0 2 1 1 3 0 1>,
+ < 200000 1 3 0 1 1 1 3 0 0>;
+ };
+
combiner: interrupt-controller@10440000 {
samsung,combiner-nr = <20>;
};
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index c4a9306..09a86e7 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -31,6 +31,42 @@
mshc0 = &mshc_0;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ clocks = <&clock CLK_ARM_CLK>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 1500000 1350000
+ 1400000 1287500
+ 1300000 1250000
+ 1200000 1187500
+ 1100000 1137500
+ 1000000 1087500
+ 900000 1037500
+ 800000 1000000
+ 700000 987500
+ 600000 975000
+ 500000 950000
+ 400000 925000
+ 300000 900000
+ 200000 900000
+ >;
+ clock-latency = <200000>;
+ boost-frequency = <1500000>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
pmu {
compatible = "arm,cortex-a9-pmu";
interrupt-parent = <&combiner>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index 090f983..443c0d3 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -25,6 +25,12 @@
bootargs = "console=ttySAC2,115200";
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
rtc@101E0000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5250-cros-common.dtsi b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
index 2c1560d..4bde756 100644
--- a/arch/arm/boot/dts/exynos5250-cros-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
@@ -19,6 +19,12 @@
chosen {
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
pinctrl@11400000 {
/*
* Disabled pullups since external part has its own pullups and
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a794a70..3632f7a 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -27,6 +27,12 @@
bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
};
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
rtc@101E0000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 3742331..f59f8a9 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -63,6 +63,29 @@
compatible = "arm,cortex-a15";
reg = <0>;
clock-frequency = <1700000000>;
+
+ clocks = <&clock CLK_ARM_CLK>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 1700000 1300000
+ 1600000 1250000
+ 1500000 1225000
+ 1400000 1200000
+ 1300000 1150000
+ 1200000 1125000
+ 1100000 1100000
+ 1000000 1075000
+ 900000 1050000
+ 800000 1025000
+ 700000 1012500
+ 600000 1000000
+ 500000 975000
+ 400000 950000
+ 300000 937500
+ 200000 925000
+ >;
+ clock-latency = <200000>;
};
cpu@1 {
device_type = "cpu";
@@ -86,6 +109,24 @@
compatible = "samsung,exynos5250-clock";
reg = <0x10010000 0x30000>;
#clock-cells = <1>;
+
+ samsung,armclk-cells = <9>;
+ samsung,armclk-divider-table = <1700000 3 7 7 7 3 5 0 2>,
+ <1600000 3 7 7 7 1 4 0 2>,
+ <1500000 2 7 7 7 1 4 0 2>,
+ <1400000 2 7 7 6 1 4 0 2>,
+ <1300000 2 7 7 6 1 3 0 2>,
+ <1200000 2 7 7 5 1 3 0 2>,
+ <1100000 3 7 7 5 1 3 0 2>,
+ <1000000 1 7 7 4 1 2 0 2>,
+ < 900000 1 7 7 4 1 2 0 2>,
+ < 800000 1 7 7 4 1 2 0 2>,
+ < 700000 1 7 7 3 1 1 0 2>,
+ < 600000 1 7 7 3 1 1 0 2>,
+ < 500000 1 7 7 2 1 1 0 2>,
+ < 400000 1 7 7 2 1 1 0 2>,
+ < 300000 1 7 7 1 1 1 0 2>,
+ < 200000 1 7 7 1 1 1 0 2>;
};
clock_audss: audss-clock-controller@3810000 {
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (5 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-14 12:50 ` Arnd Bergmann
2014-05-17 0:04 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support Thomas Abraham
` (2 subsequent siblings)
9 siblings, 2 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
Remove the platform device instantiation for Exynos specific cpufreq
driver and add the platform device for cpufreq-cpu0 driver.
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
arch/arm/mach-exynos/exynos.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index b32a907..489a495 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -232,7 +232,9 @@ void __init exynos_cpuidle_init(void)
void __init exynos_cpufreq_init(void)
{
- platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
+ if (!(of_machine_is_compatible("samsung,exynos5420")) &&
+ !(of_machine_is_compatible("samsung,exynos5440")))
+ platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
}
void __init exynos_init_late(void)
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (6 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver Thomas Abraham
@ 2014-05-14 1:11 ` Thomas Abraham
2014-05-14 3:57 ` Viresh Kumar
2014-05-14 7:20 ` Lukasz Majewski
2014-05-14 12:51 ` [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Arnd Bergmann
2014-05-17 0:14 ` Tomasz Figa
9 siblings, 2 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 1:11 UTC (permalink / raw)
To: cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
From: Thomas Abraham <thomas.ab@samsung.com>
Exynos4210, Exynos4x12 and Exynos5250 based platforms have switched over
to use cpufreq-cpu0 driver for cpufreq functionality. So the Exynos
specific cpufreq drivers for these platforms can be removed.
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/cpufreq/Kconfig.arm | 52 ---------
drivers/cpufreq/Makefile | 4 -
drivers/cpufreq/exynos-cpufreq.c | 209 ---------------------------------
drivers/cpufreq/exynos-cpufreq.h | 91 ---------------
drivers/cpufreq/exynos4210-cpufreq.c | 157 -------------------------
drivers/cpufreq/exynos4x12-cpufreq.c | 211 ----------------------------------
drivers/cpufreq/exynos5250-cpufreq.c | 183 -----------------------------
7 files changed, 0 insertions(+), 907 deletions(-)
delete mode 100644 drivers/cpufreq/exynos-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.h
delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos4x12-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos5250-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 5805035..9721674 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -24,43 +24,6 @@ config ARM_VEXPRESS_SPC_CPUFREQ
This add the CPUfreq driver support for Versatile Express
big.LITTLE platforms using SPC for power management.
-
-config ARM_EXYNOS_CPUFREQ
- bool
-
-config ARM_EXYNOS4210_CPUFREQ
- bool "SAMSUNG EXYNOS4210"
- depends on CPU_EXYNOS4210 && !ARCH_MULTIPLATFORM
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS4210
- SoC (S5PV310 or S5PC210).
-
- If in doubt, say N.
-
-config ARM_EXYNOS4X12_CPUFREQ
- bool "SAMSUNG EXYNOS4x12"
- depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS4X12
- SoC (EXYNOS4212 or EXYNOS4412).
-
- If in doubt, say N.
-
-config ARM_EXYNOS5250_CPUFREQ
- bool "SAMSUNG EXYNOS5250"
- depends on SOC_EXYNOS5250 && !ARCH_MULTIPLATFORM
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS5250
- SoC.
-
- If in doubt, say N.
-
config ARM_EXYNOS5440_CPUFREQ
bool "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440
@@ -75,21 +38,6 @@ config ARM_EXYNOS5440_CPUFREQ
If in doubt, say N.
-config ARM_EXYNOS_CPU_FREQ_BOOST_SW
- bool "EXYNOS Frequency Overclocking - Software"
- depends on ARM_EXYNOS_CPUFREQ
- select CPU_FREQ_BOOST_SW
- select EXYNOS_THERMAL
- help
- This driver supports software managed overclocking (BOOST).
- It allows usage of special frequencies for Samsung Exynos
- processors if thermal conditions are appropriate.
-
- It reguires, for safe operation, thermal framework with properly
- defined trip points.
-
- If in doubt, say N.
-
config ARM_HIGHBANK_CPUFREQ
tristate "Calxeda Highbank-based"
depends on ARCH_HIGHBANK && GENERIC_CPUFREQ_CPU0 && REGULATOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 738c8b7..8a75419 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -51,10 +51,6 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += davinci-cpufreq.o
obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
deleted file mode 100644
index f99cfe2..0000000
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS - CPU frequency scaling support for EXYNOS series
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/cpufreq.h>
-#include <linux/platform_device.h>
-
-#include <plat/cpu.h>
-
-#include "exynos-cpufreq.h"
-
-static struct exynos_dvfs_info *exynos_info;
-static struct regulator *arm_regulator;
-static unsigned int locking_frequency;
-
-static int exynos_cpufreq_get_index(unsigned int freq)
-{
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
- int index;
-
- for (index = 0;
- freq_table[index].frequency != CPUFREQ_TABLE_END; index++)
- if (freq_table[index].frequency == freq)
- break;
-
- if (freq_table[index].frequency == CPUFREQ_TABLE_END)
- return -EINVAL;
-
- return index;
-}
-
-static int exynos_cpufreq_scale(unsigned int target_freq)
-{
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
- unsigned int *volt_table = exynos_info->volt_table;
- struct cpufreq_policy *policy = cpufreq_cpu_get(0);
- unsigned int arm_volt, safe_arm_volt = 0;
- unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
- unsigned int old_freq;
- int index, old_index;
- int ret = 0;
-
- old_freq = policy->cur;
-
- /*
- * The policy max have been changed so that we cannot get proper
- * old_index with cpufreq_frequency_table_target(). Thus, ignore
- * policy and get the index from the raw frequency table.
- */
- old_index = exynos_cpufreq_get_index(old_freq);
- if (old_index < 0) {
- ret = old_index;
- goto out;
- }
-
- index = exynos_cpufreq_get_index(target_freq);
- if (index < 0) {
- ret = index;
- goto out;
- }
-
- /*
- * ARM clock source will be changed APLL to MPLL temporary
- * To support this level, need to control regulator for
- * required voltage level
- */
- if (exynos_info->need_apll_change != NULL) {
- if (exynos_info->need_apll_change(old_index, index) &&
- (freq_table[index].frequency < mpll_freq_khz) &&
- (freq_table[old_index].frequency < mpll_freq_khz))
- safe_arm_volt = volt_table[exynos_info->pll_safe_idx];
- }
- arm_volt = volt_table[index];
-
- /* When the new frequency is higher than current frequency */
- if ((target_freq > old_freq) && !safe_arm_volt) {
- /* Firstly, voltage up to increase frequency */
- ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, arm_volt);
- return ret;
- }
- }
-
- if (safe_arm_volt) {
- ret = regulator_set_voltage(arm_regulator, safe_arm_volt,
- safe_arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, safe_arm_volt);
- return ret;
- }
- }
-
- exynos_info->set_freq(old_index, index);
-
- /* When the new frequency is lower than current frequency */
- if ((target_freq < old_freq) ||
- ((target_freq > old_freq) && safe_arm_volt)) {
- /* down the voltage after frequency change */
- ret = regulator_set_voltage(arm_regulator, arm_volt,
- arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, arm_volt);
- goto out;
- }
- }
-
-out:
- cpufreq_cpu_put(policy);
-
- return ret;
-}
-
-static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
-{
- return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
-}
-
-static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- policy->clk = exynos_info->cpu_clk;
- policy->suspend_freq = locking_frequency;
- return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
-}
-
-static struct cpufreq_driver exynos_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = exynos_target,
- .get = cpufreq_generic_get,
- .init = exynos_cpufreq_cpu_init,
- .name = "exynos_cpufreq",
- .attr = cpufreq_generic_attr,
-#ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
- .boost_supported = true,
-#endif
-#ifdef CONFIG_PM
- .suspend = cpufreq_generic_suspend,
-#endif
-};
-
-static int exynos_cpufreq_probe(struct platform_device *pdev)
-{
- int ret = -EINVAL;
-
- exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
- if (!exynos_info)
- return -ENOMEM;
-
- if (soc_is_exynos4210())
- ret = exynos4210_cpufreq_init(exynos_info);
- else if (soc_is_exynos4212() || soc_is_exynos4412())
- ret = exynos4x12_cpufreq_init(exynos_info);
- else if (soc_is_exynos5250())
- ret = exynos5250_cpufreq_init(exynos_info);
- else
- return 0;
-
- if (ret)
- goto err_vdd_arm;
-
- if (exynos_info->set_freq == NULL) {
- pr_err("%s: No set_freq function (ERR)\n", __func__);
- goto err_vdd_arm;
- }
-
- arm_regulator = regulator_get(NULL, "vdd_arm");
- if (IS_ERR(arm_regulator)) {
- pr_err("%s: failed to get resource vdd_arm\n", __func__);
- goto err_vdd_arm;
- }
-
- /* Done here as we want to capture boot frequency */
- locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
-
- if (!cpufreq_register_driver(&exynos_driver))
- return 0;
-
- pr_err("%s: failed to register cpufreq driver\n", __func__);
- regulator_put(arm_regulator);
-err_vdd_arm:
- kfree(exynos_info);
- return -EINVAL;
-}
-
-static struct platform_driver exynos_cpufreq_platdrv = {
- .driver = {
- .name = "exynos-cpufreq",
- .owner = THIS_MODULE,
- },
- .probe = exynos_cpufreq_probe,
-};
-module_platform_driver(exynos_cpufreq_platdrv);
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h
deleted file mode 100644
index 3ddade8..0000000
--- a/drivers/cpufreq/exynos-cpufreq.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS - CPUFreq support
- *
- * 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.
-*/
-
-enum cpufreq_level_index {
- L0, L1, L2, L3, L4,
- L5, L6, L7, L8, L9,
- L10, L11, L12, L13, L14,
- L15, L16, L17, L18, L19,
- L20,
-};
-
-#define APLL_FREQ(f, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, m, p, s) \
- { \
- .freq = (f) * 1000, \
- .clk_div_cpu0 = ((a0) | (a1) << 4 | (a2) << 8 | (a3) << 12 | \
- (a4) << 16 | (a5) << 20 | (a6) << 24 | (a7) << 28), \
- .clk_div_cpu1 = (b0 << 0 | b1 << 4 | b2 << 8), \
- .mps = ((m) << 16 | (p) << 8 | (s)), \
- }
-
-struct apll_freq {
- unsigned int freq;
- u32 clk_div_cpu0;
- u32 clk_div_cpu1;
- u32 mps;
-};
-
-struct exynos_dvfs_info {
- unsigned long mpll_freq_khz;
- unsigned int pll_safe_idx;
- struct clk *cpu_clk;
- unsigned int *volt_table;
- struct cpufreq_frequency_table *freq_table;
- void (*set_freq)(unsigned int, unsigned int);
- bool (*need_apll_change)(unsigned int, unsigned int);
-};
-
-#ifdef CONFIG_ARM_EXYNOS4210_CPUFREQ
-extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-#ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ
-extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-#ifdef CONFIG_ARM_EXYNOS5250_CPUFREQ
-extern int exynos5250_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-
-#include <plat/cpu.h>
-#include <mach/map.h>
-
-#define EXYNOS4_CLKSRC_CPU (S5P_VA_CMU + 0x14200)
-#define EXYNOS4_CLKMUX_STATCPU (S5P_VA_CMU + 0x14400)
-
-#define EXYNOS4_CLKDIV_CPU (S5P_VA_CMU + 0x14500)
-#define EXYNOS4_CLKDIV_CPU1 (S5P_VA_CMU + 0x14504)
-#define EXYNOS4_CLKDIV_STATCPU (S5P_VA_CMU + 0x14600)
-#define EXYNOS4_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x14604)
-
-#define EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT (16)
-#define EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK (0x7 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)
-
-#define EXYNOS5_APLL_LOCK (S5P_VA_CMU + 0x00000)
-#define EXYNOS5_APLL_CON0 (S5P_VA_CMU + 0x00100)
-#define EXYNOS5_CLKMUX_STATCPU (S5P_VA_CMU + 0x00400)
-#define EXYNOS5_CLKDIV_CPU0 (S5P_VA_CMU + 0x00500)
-#define EXYNOS5_CLKDIV_CPU1 (S5P_VA_CMU + 0x00504)
-#define EXYNOS5_CLKDIV_STATCPU0 (S5P_VA_CMU + 0x00600)
-#define EXYNOS5_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x00604)
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
deleted file mode 100644
index 6384e5b..0000000
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4210 - CPU frequency scaling support
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos4210_volt_table[] = {
- 1250000, 1150000, 1050000, 975000, 950000,
-};
-
-static struct cpufreq_frequency_table exynos4210_freq_table[] = {
- {0, L0, 1200 * 1000},
- {0, L1, 1000 * 1000},
- {0, L2, 800 * 1000},
- {0, L3, 500 * 1000},
- {0, L4, 200 * 1000},
- {0, 0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq apll_freq_4210[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, RESERVED
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1200, 0, 3, 7, 3, 4, 1, 7, 0, 5, 0, 0, 150, 3, 1),
- APLL_FREQ(1000, 0, 3, 7, 3, 4, 1, 7, 0, 4, 0, 0, 250, 6, 1),
- APLL_FREQ(800, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 200, 6, 1),
- APLL_FREQ(500, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 250, 6, 2),
- APLL_FREQ(200, 0, 1, 3, 1, 3, 1, 0, 0, 3, 0, 0, 200, 6, 3),
-};
-
-static void exynos4210_set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_4210[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU);
- } while (tmp & 0x1111111);
-
- /* Change Divider - CPU1 */
-
- tmp = apll_freq_4210[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1);
- } while (tmp & 0x11);
-}
-
-static void exynos4210_set_apll(unsigned int index)
-{
- unsigned int tmp, freq = apll_freq_4210[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
- >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
- tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
- } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4210_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- exynos4210_set_clkdiv(new_index);
- exynos4210_set_apll(new_index);
- } else if (old_index < new_index) {
- exynos4210_set_apll(new_index);
- exynos4210_set_clkdiv(new_index);
- }
-}
-
-int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "moutcore");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L2;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos4210_volt_table;
- info->freq_table = exynos4210_freq_table;
- info->set_freq = exynos4210_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_debug("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c
deleted file mode 100644
index 466c76a..0000000
--- a/drivers/cpufreq/exynos4x12-cpufreq.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4X12 - CPU frequency scaling support
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos4x12_volt_table[] = {
- 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500,
- 1000000, 987500, 975000, 950000, 925000, 900000, 900000
-};
-
-static struct cpufreq_frequency_table exynos4x12_freq_table[] = {
- {CPUFREQ_BOOST_FREQ, L0, 1500 * 1000},
- {0, L1, 1400 * 1000},
- {0, L2, 1300 * 1000},
- {0, L3, 1200 * 1000},
- {0, L4, 1100 * 1000},
- {0, L5, 1000 * 1000},
- {0, L6, 900 * 1000},
- {0, L7, 800 * 1000},
- {0, L8, 700 * 1000},
- {0, L9, 600 * 1000},
- {0, L10, 500 * 1000},
- {0, L11, 400 * 1000},
- {0, L12, 300 * 1000},
- {0, L13, 200 * 1000},
- {0, 0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq *apll_freq_4x12;
-
-static struct apll_freq apll_freq_4212[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 250, 4, 0),
- APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 175, 3, 0),
- APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 325, 6, 0),
- APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 2, 0, 275, 6, 0),
- APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 2, 0, 125, 3, 0),
- APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 150, 4, 0),
- APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 0),
- APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 175, 3, 1),
- APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 200, 4, 1),
- APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 125, 3, 1),
- APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 1),
- APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 2, 0, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 2, 0, 100, 3, 2),
-};
-
-static struct apll_freq apll_freq_4412[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2
- * clock divider for COPY, HPM, CORES
- * PLL M, P, S
- */
- APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 250, 4, 0),
- APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 6, 175, 3, 0),
- APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 6, 325, 6, 0),
- APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 5, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 0, 5, 275, 6, 0),
- APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 0, 4, 125, 3, 0),
- APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 4, 150, 4, 0),
- APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 3, 100, 3, 0),
- APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 3, 175, 3, 1),
- APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 200, 4, 1),
- APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 125, 3, 1),
- APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 1, 100, 3, 1),
- APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 0, 1, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 0, 0, 100, 3, 2),
-};
-
-static void exynos4x12_set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
- unsigned int stat_cpu1;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_4x12[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU);
-
- while (__raw_readl(EXYNOS4_CLKDIV_STATCPU) & 0x11111111)
- cpu_relax();
-
- /* Change Divider - CPU1 */
- tmp = apll_freq_4x12[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);
- if (soc_is_exynos4212())
- stat_cpu1 = 0x11;
- else
- stat_cpu1 = 0x111;
-
- while (__raw_readl(EXYNOS4_CLKDIV_STATCPU1) & stat_cpu1)
- cpu_relax();
-}
-
-static void exynos4x12_set_apll(unsigned int index)
-{
- unsigned int tmp, freq = apll_freq_4x12[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- cpu_relax();
- tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
- >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- cpu_relax();
- tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
- tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
- } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4x12_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- exynos4x12_set_clkdiv(new_index);
- exynos4x12_set_apll(new_index);
- } else if (old_index < new_index) {
- exynos4x12_set_apll(new_index);
- exynos4x12_set_clkdiv(new_index);
- }
-}
-
-int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "moutcore");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- if (soc_is_exynos4212())
- apll_freq_4x12 = apll_freq_4212;
- else
- apll_freq_4x12 = apll_freq_4412;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L7;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos4x12_volt_table;
- info->freq_table = exynos4x12_freq_table;
- info->set_freq = exynos4x12_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_debug("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c
deleted file mode 100644
index 363a0b3..0000000
--- a/drivers/cpufreq/exynos5250-cpufreq.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2010-20122Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS5250 - CPU frequency scaling support
- *
- * 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.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos5250_volt_table[] = {
- 1300000, 1250000, 1225000, 1200000, 1150000,
- 1125000, 1100000, 1075000, 1050000, 1025000,
- 1012500, 1000000, 975000, 950000, 937500,
- 925000
-};
-
-static struct cpufreq_frequency_table exynos5250_freq_table[] = {
- {0, L0, 1700 * 1000},
- {0, L1, 1600 * 1000},
- {0, L2, 1500 * 1000},
- {0, L3, 1400 * 1000},
- {0, L4, 1300 * 1000},
- {0, L5, 1200 * 1000},
- {0, L6, 1100 * 1000},
- {0, L7, 1000 * 1000},
- {0, L8, 900 * 1000},
- {0, L9, 800 * 1000},
- {0, L10, 700 * 1000},
- {0, L11, 600 * 1000},
- {0, L12, 500 * 1000},
- {0, L13, 400 * 1000},
- {0, L14, 300 * 1000},
- {0, L15, 200 * 1000},
- {0, 0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq apll_freq_5250[] = {
- /*
- * values:
- * freq
- * clock divider for ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1700, 0, 3, 7, 7, 7, 3, 5, 0, 0, 2, 0, 425, 6, 0),
- APLL_FREQ(1600, 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 0, 200, 3, 0),
- APLL_FREQ(1500, 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 0, 250, 4, 0),
- APLL_FREQ(1400, 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 0, 175, 3, 0),
- APLL_FREQ(1300, 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 0, 325, 6, 0),
- APLL_FREQ(1200, 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 0, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 0, 275, 6, 0),
- APLL_FREQ(1000, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 125, 3, 0),
- APLL_FREQ(900, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 150, 4, 0),
- APLL_FREQ(800, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 100, 3, 0),
- APLL_FREQ(700, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 175, 3, 1),
- APLL_FREQ(600, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 200, 4, 1),
- APLL_FREQ(500, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 125, 3, 1),
- APLL_FREQ(400, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 100, 3, 1),
- APLL_FREQ(300, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 100, 3, 2),
-};
-
-static void set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_5250[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0);
-
- while (__raw_readl(EXYNOS5_CLKDIV_STATCPU0) & 0x11111111)
- cpu_relax();
-
- /* Change Divider - CPU1 */
- tmp = apll_freq_5250[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1);
-
- while (__raw_readl(EXYNOS5_CLKDIV_STATCPU1) & 0x11)
- cpu_relax();
-}
-
-static void set_apll(unsigned int index)
-{
- unsigned int tmp;
- unsigned int freq = apll_freq_5250[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- cpu_relax();
- tmp = (__raw_readl(EXYNOS5_CLKMUX_STATCPU) >> 16);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- cpu_relax();
- tmp = __raw_readl(EXYNOS5_CLKMUX_STATCPU);
- tmp &= (0x7 << 16);
- } while (tmp != (0x1 << 16));
-}
-
-static void exynos5250_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- set_clkdiv(new_index);
- set_apll(new_index);
- } else if (old_index < new_index) {
- set_apll(new_index);
- set_clkdiv(new_index);
- }
-}
-
-int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "mout_cpu");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L9;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos5250_volt_table;
- info->freq_table = exynos5250_freq_table;
- info->set_freq = exynos5250_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_err("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
--
1.7.4.4
^ permalink raw reply related [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 1:11 ` [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies Thomas Abraham
@ 2014-05-14 3:46 ` Viresh Kumar
2014-05-14 6:17 ` Lukasz Majewski
0 siblings, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 3:46 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Heiko Stübner, Thomas P Abraham
On 14 May 2014 06:41, Thomas Abraham <ta.omasab@gmail.com> wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Lookup for the optional boost-frequency property in cpu0 node and if
> available, enable support for boost mode frequencies. The frequencies
> usable in boost mode are determined while preparing the cpufreq table
> from the list of operating points available.
>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 2 ++
> drivers/cpufreq/Kconfig | 11 +++++++++++
> drivers/cpufreq/cpufreq-cpu0.c | 5 +++++
> 3 files changed, 18 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> index f055515..60f321a 100644
> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> @@ -19,6 +19,8 @@ Optional properties:
> - cooling-min-level:
> - cooling-max-level:
> Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
> +- boost-frequency:
> + Please refer to Documentation/devicetree/bindings/cpufreq/cpufreq-boost.txt
>
> Examples:
>
> diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
> index 1fbe11f..0ca4485 100644
> --- a/drivers/cpufreq/Kconfig
> +++ b/drivers/cpufreq/Kconfig
> @@ -194,6 +194,17 @@ config GENERIC_CPUFREQ_CPU0
>
> If in doubt, say N.
>
> +config GENERIC_CPUFREQ_CPU0_BOOST
Get rid of this.. just not required.
> + bool "Boost frequency support for generic CPU0 cpufreq driver"
> + depends on GENERIC_CPUFREQ_CPU0
> + select CPU_FREQ_BOOST_SW
> + help
> + This enables support for software managed overclocking (BOOST). It
> + allows usage of special frequencies (those beyond the normal operating
> + frequencies).
> +
> + If in doubt, say N.
> +
> menu "x86 CPU frequency scaling drivers"
> depends on X86
> source "drivers/cpufreq/Kconfig.x86"
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index 1bf6bba..e6c21a8 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -194,6 +194,11 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
> transition_latency += ret * 1000;
> }
>
> +#ifdef CONFIG_GENERIC_CPUFREQ_CPU0_BOOST
> + if (of_find_property(cpu_dev->of_node, "boost-frequency", NULL))
Lets see what happens to the other thread for this.
> + cpu0_cpufreq_driver.boost_supported = true;
> +#endif
> +
> ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
> if (ret) {
> pr_err("failed register driver: %d\n", ret);
> --
> 1.7.4.4
>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global
2014-05-14 1:11 ` [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global Thomas Abraham
@ 2014-05-14 3:50 ` Viresh Kumar
2014-05-14 13:26 ` Thomas Abraham
2014-05-16 12:30 ` Tomasz Figa
1 sibling, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 3:50 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Heiko Stübner, Thomas P Abraham
On 14 May 2014 06:41, Thomas Abraham <ta.omasab@gmail.com> wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Access to samsung clock lock is required to support newer samsung specific
> clock types. So change the scope of the samsung clock lock to global. And
Maybe bit more detail on why exactly it should be available outside this file.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support
2014-05-14 1:11 ` [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support Thomas Abraham
@ 2014-05-14 3:57 ` Viresh Kumar
2014-05-14 7:20 ` Lukasz Majewski
1 sibling, 0 replies; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 3:57 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Heiko Stübner, Thomas P Abraham
On 14 May 2014 06:41, Thomas Abraham <ta.omasab@gmail.com> wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Exynos4210, Exynos4x12 and Exynos5250 based platforms have switched over
> to use cpufreq-cpu0 driver for cpufreq functionality. So the Exynos
> specific cpufreq drivers for these platforms can be removed.
>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> drivers/cpufreq/Kconfig.arm | 52 ---------
> drivers/cpufreq/Makefile | 4 -
> drivers/cpufreq/exynos-cpufreq.c | 209 ---------------------------------
> drivers/cpufreq/exynos-cpufreq.h | 91 ---------------
> drivers/cpufreq/exynos4210-cpufreq.c | 157 -------------------------
> drivers/cpufreq/exynos4x12-cpufreq.c | 211 ----------------------------------
> drivers/cpufreq/exynos5250-cpufreq.c | 183 -----------------------------
> 7 files changed, 0 insertions(+), 907 deletions(-)
I *loved* this :)
Ack Ack Ack ...
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 3:46 ` Viresh Kumar
@ 2014-05-14 6:17 ` Lukasz Majewski
2014-05-14 6:20 ` Viresh Kumar
0 siblings, 1 reply; 58+ messages in thread
From: Lukasz Majewski @ 2014-05-14 6:17 UTC (permalink / raw)
To: Viresh Kumar, Thomas P Abraham
Cc: Thomas Abraham, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
Hi Viresh, Tomas,
> On 14 May 2014 06:41, Thomas Abraham <ta.omasab@gmail.com> wrote:
> > From: Thomas Abraham <thomas.ab@samsung.com>
> >
> > Lookup for the optional boost-frequency property in cpu0 node and if
> > available, enable support for boost mode frequencies. The
> > frequencies usable in boost mode are determined while preparing the
> > cpufreq table from the list of operating points available.
> >
> > Cc: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> > ---
> > .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 2 ++
> > drivers/cpufreq/Kconfig | 11
> > +++++++++++ drivers/cpufreq/cpufreq-cpu0.c |
> > 5 +++++ 3 files changed, 18 insertions(+), 0 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> > b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt index
> > f055515..60f321a 100644 ---
> > a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt +++
> > b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt @@
> > -19,6 +19,8 @@ Optional properties:
> > - cooling-min-level:
> > - cooling-max-level:
> > Please refer to
> > Documentation/devicetree/bindings/thermal/thermal.txt. +-
> > boost-frequency:
> > + Please refer to
> > Documentation/devicetree/bindings/cpufreq/cpufreq-boost.txt
> >
> > Examples:
> >
> > diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
> > index 1fbe11f..0ca4485 100644
> > --- a/drivers/cpufreq/Kconfig
> > +++ b/drivers/cpufreq/Kconfig
> > @@ -194,6 +194,17 @@ config GENERIC_CPUFREQ_CPU0
> >
> > If in doubt, say N.
> >
> > +config GENERIC_CPUFREQ_CPU0_BOOST
>
> Get rid of this.. just not required.
I think that you can rely solely on the CPU_FREQ_BOOST_SW flag if the
original author of cpufreq-cpu0.c don't mind.
>
> > + bool "Boost frequency support for generic CPU0 cpufreq
> > driver"
> > + depends on GENERIC_CPUFREQ_CPU0
> > + select CPU_FREQ_BOOST_SW
> > + help
> > + This enables support for software managed overclocking
> > (BOOST). It
> > + allows usage of special frequencies (those beyond the
> > normal operating
> > + frequencies).
> > +
> > + If in doubt, say N.
> > +
> > menu "x86 CPU frequency scaling drivers"
> > depends on X86
> > source "drivers/cpufreq/Kconfig.x86"
> > diff --git a/drivers/cpufreq/cpufreq-cpu0.c
> > b/drivers/cpufreq/cpufreq-cpu0.c index 1bf6bba..e6c21a8 100644
> > --- a/drivers/cpufreq/cpufreq-cpu0.c
> > +++ b/drivers/cpufreq/cpufreq-cpu0.c
> > @@ -194,6 +194,11 @@ static int cpu0_cpufreq_probe(struct
> > platform_device *pdev) transition_latency += ret * 1000;
> > }
> >
> > +#ifdef CONFIG_GENERIC_CPUFREQ_CPU0_BOOST
> > + if (of_find_property(cpu_dev->of_node, "boost-frequency",
> > NULL))
>
> Lets see what happens to the other thread for this.
>
> > + cpu0_cpufreq_driver.boost_supported = true;
> > +#endif
> > +
> > ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
> > if (ret) {
> > pr_err("failed register driver: %d\n", ret);
> > --
> > 1.7.4.4
> >
--
Best regards,
Lukasz Majewski
Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 6:17 ` Lukasz Majewski
@ 2014-05-14 6:20 ` Viresh Kumar
2014-05-14 13:43 ` Thomas Abraham
0 siblings, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 6:20 UTC (permalink / raw)
To: Lukasz Majewski
Cc: Thomas P Abraham, Thomas Abraham, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
On 14 May 2014 11:47, Lukasz Majewski <l.majewski@samsung.com> wrote:
> I think that you can rely solely on the CPU_FREQ_BOOST_SW flag if the
> original author of cpufreq-cpu0.c don't mind.
We don't have to. struct cpufreq_driver: boost_supported is always available.
Just update it without any ugly #ifdefs ..
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support
2014-05-14 1:11 ` [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support Thomas Abraham
2014-05-14 3:57 ` Viresh Kumar
@ 2014-05-14 7:20 ` Lukasz Majewski
2014-05-14 13:53 ` Thomas Abraham
1 sibling, 1 reply; 58+ messages in thread
From: Lukasz Majewski @ 2014-05-14 7:20 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq, linux-arm-kernel, devicetree, kgene.kim, mturquette,
heiko, viresh.kumar, t.figa, rjw, linux-samsung-soc, thomas.ab,
shawn.guo
Hi Thomas,
> -config ARM_EXYNOS_CPU_FREQ_BOOST_SW
> - bool "EXYNOS Frequency Overclocking - Software"
> - depends on ARM_EXYNOS_CPUFREQ
> - select CPU_FREQ_BOOST_SW
> - select EXYNOS_THERMAL
> - help
> - This driver supports software managed overclocking (BOOST).
> - It allows usage of special frequencies for Samsung Exynos
> - processors if thermal conditions are appropriate.
> -
> - It reguires, for safe operation, thermal framework with
> properly
> - defined trip points.
> -
> - If in doubt, say N.
> -
If I might ask, where this switch,to enable BOOST, will be moved? All
in all, I would like to be able to enable boost :-).
In my opinion we should have the Kconfig option to enable/disable the
CPU_FREQ_BOOST_SW and this may be used with cpufreq-cpu0 driver as I've
pointed out in the other patch.
--
Best regards,
Lukasz Majewski
Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 1:11 ` [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver Thomas Abraham
@ 2014-05-14 12:50 ` Arnd Bergmann
2014-05-14 13:05 ` Viresh Kumar
2014-05-14 14:09 ` Thomas Abraham
2014-05-17 0:04 ` Tomasz Figa
1 sibling, 2 replies; 58+ messages in thread
From: Arnd Bergmann @ 2014-05-14 12:50 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Thomas Abraham, cpufreq, devicetree, l.majewski, kgene.kim,
mturquette, heiko, viresh.kumar, t.figa, rjw, linux-samsung-soc,
thomas.ab, shawn.guo
On Wednesday 14 May 2014 06:41:15 Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Remove the platform device instantiation for Exynos specific cpufreq
> driver and add the platform device for cpufreq-cpu0 driver.
>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> arch/arm/mach-exynos/exynos.c | 4 +++-
> 1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
> index b32a907..489a495 100644
> --- a/arch/arm/mach-exynos/exynos.c
> +++ b/arch/arm/mach-exynos/exynos.c
> @@ -232,7 +232,9 @@ void __init exynos_cpuidle_init(void)
>
> void __init exynos_cpufreq_init(void)
> {
> - platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
> + if (!(of_machine_is_compatible("samsung,exynos5420")) &&
> + !(of_machine_is_compatible("samsung,exynos5440")))
> + platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
> }
>
Could we please come up with a way to probe this from DT in the cpufreq-cpu0
driver itself, so we don't have to add a device in every platform using it?
I realize you copied it from the other platforms using this driver, but
it still seems really wrong.
Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (7 preceding siblings ...)
2014-05-14 1:11 ` [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support Thomas Abraham
@ 2014-05-14 12:51 ` Arnd Bergmann
2014-05-14 13:07 ` Viresh Kumar
2014-05-17 0:14 ` Tomasz Figa
9 siblings, 1 reply; 58+ messages in thread
From: Arnd Bergmann @ 2014-05-14 12:51 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Thomas Abraham, cpufreq, devicetree, l.majewski, kgene.kim,
mturquette, heiko, viresh.kumar, t.figa, rjw, linux-samsung-soc,
thomas.ab, shawn.guo
On Wednesday 14 May 2014 06:41:08 Thomas Abraham wrote:
>
> The patch series removes the use of Exynos specific cpufreq driver and enables
> the use of cpufreq-cpu0 driver for Exynos4210, Exynos4x12 and Exynos5250 based
> platforms. This is being done for few reasons.
>
> (a) The Exynos cpufreq driver reads/writes clock controller registers
> bypassing the Exynos CCF driver which is sort of problematic.
> (b) Removes the need for having clock controller register definitions
> in the cpufreq driver and also removes the need for statically
> io-remapping clock controller address space (helps in moving towards
> multiplatform kernel).
>
Thanks a lot for your continued effort. Looks great overall, but I have one
comment about the general way the cpu0 cpufreq driver works, not specific
to the exynos implementation. See my reply to patch 4.
Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 12:50 ` Arnd Bergmann
@ 2014-05-14 13:05 ` Viresh Kumar
2014-05-14 13:11 ` Heiko Stübner
2014-05-14 14:09 ` Thomas Abraham
1 sibling, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 13:05 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel@lists.infradead.org, Thomas Abraham,
cpufreq@vger.kernel.org, devicetree@vger.kernel.org,
Lukasz Majewski, Kukjin Kim, Mike Turquette, Heiko Stübner,
Tomasz Figa, Rafael J. Wysocki, linux-samsung-soc,
Thomas P Abraham, Shawn Guo
On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
> Could we please come up with a way to probe this from DT in the cpufreq-cpu0
> driver itself, so we don't have to add a device in every platform using it?
Its followed that way because DT Maintainers had strong objections
to creating virtual device nodes and haven't allowed creation of nodes
for cpufreq drivers.. For which there is no physical device, as CPU already
has a separate node..
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
2014-05-14 12:51 ` [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Arnd Bergmann
@ 2014-05-14 13:07 ` Viresh Kumar
2014-05-14 13:16 ` Arnd Bergmann
0 siblings, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 13:07 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel@lists.infradead.org, Thomas Abraham,
cpufreq@vger.kernel.org, devicetree@vger.kernel.org,
Lukasz Majewski, Kukjin Kim, Mike Turquette, Heiko Stübner,
Tomasz Figa, Rafael J. Wysocki, linux-samsung-soc,
Thomas P Abraham, Shawn Guo
On 14 May 2014 18:21, Arnd Bergmann <arnd@arndb.de> wrote:
> Thanks a lot for your continued effort. Looks great overall, but I have one
> comment about the general way the cpu0 cpufreq driver works, not specific
> to the exynos implementation. See my reply to patch 4.
I hope you meant 7 here instead of 4 ?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:05 ` Viresh Kumar
@ 2014-05-14 13:11 ` Heiko Stübner
2014-05-14 13:14 ` Viresh Kumar
2014-05-14 14:03 ` Thomas Abraham
0 siblings, 2 replies; 58+ messages in thread
From: Heiko Stübner @ 2014-05-14 13:11 UTC (permalink / raw)
To: Viresh Kumar
Cc: Arnd Bergmann, linux-arm-kernel@lists.infradead.org,
Thomas Abraham, cpufreq@vger.kernel.org,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Mike Turquette, Tomasz Figa, Rafael J. Wysocki, linux-samsung-soc,
Thomas P Abraham, Shawn Guo
Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
> > Could we please come up with a way to probe this from DT in the
> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
> > platform using it?
> Its followed that way because DT Maintainers had strong objections
> to creating virtual device nodes and haven't allowed creation of nodes
> for cpufreq drivers.. For which there is no physical device, as CPU already
> has a separate node..
as we already have the "enable-method" property for enabling/disabling cpus,
would something like a "scaling-method" be feasible?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:11 ` Heiko Stübner
@ 2014-05-14 13:14 ` Viresh Kumar
2014-05-14 13:18 ` Arnd Bergmann
2014-05-14 14:03 ` Thomas Abraham
1 sibling, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 13:14 UTC (permalink / raw)
To: Heiko Stübner, Rob Herring, Grant Likely
Cc: Arnd Bergmann, linux-arm-kernel@lists.infradead.org,
Thomas Abraham, cpufreq@vger.kernel.org,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Mike Turquette, Tomasz Figa, Rafael J. Wysocki, linux-samsung-soc,
Thomas P Abraham, Shawn Guo
On 14 May 2014 18:41, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
>> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
>> > Could we please come up with a way to probe this from DT in the
>> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
>> > platform using it?
>> Its followed that way because DT Maintainers had strong objections
>> to creating virtual device nodes and haven't allowed creation of nodes
>> for cpufreq drivers.. For which there is no physical device, as CPU already
>> has a separate node..
>
> as we already have the "enable-method" property for enabling/disabling cpus,
> would something like a "scaling-method" be feasible?
Lets see what DT maintainers have to say on this, I would rather go for a
more straight forward name: "scaling-driver" :) ..
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
2014-05-14 13:07 ` Viresh Kumar
@ 2014-05-14 13:16 ` Arnd Bergmann
0 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2014-05-14 13:16 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Viresh Kumar, devicetree@vger.kernel.org, Lukasz Majewski,
Kukjin Kim, Thomas Abraham, Heiko Stübner, Tomasz Figa,
Rafael J. Wysocki, cpufreq@vger.kernel.org, linux-samsung-soc,
Thomas P Abraham, Mike Turquette, Shawn Guo
On Wednesday 14 May 2014 18:37:13 Viresh Kumar wrote:
> On 14 May 2014 18:21, Arnd Bergmann <arnd@arndb.de> wrote:
> > Thanks a lot for your continued effort. Looks great overall, but I have one
> > comment about the general way the cpu0 cpufreq driver works, not specific
> > to the exynos implementation. See my reply to patch 4.
>
> I hope you meant 7 here instead of 4 ?
Yes, that's right, sorry for the confusion.
Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:14 ` Viresh Kumar
@ 2014-05-14 13:18 ` Arnd Bergmann
2014-05-14 13:45 ` Rob Herring
0 siblings, 1 reply; 58+ messages in thread
From: Arnd Bergmann @ 2014-05-14 13:18 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Viresh Kumar, Heiko Stübner, Rob Herring, Grant Likely,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Thomas Abraham, Tomasz Figa, Rafael J. Wysocki,
cpufreq@vger.kernel.org, linux-samsung-soc, Thomas P Abraham,
Mike Turquette, Shawn Guo
On Wednesday 14 May 2014 18:44:46 Viresh Kumar wrote:
> On 14 May 2014 18:41, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
> >> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
> >> > Could we please come up with a way to probe this from DT in the
> >> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
> >> > platform using it?
>
> >> Its followed that way because DT Maintainers had strong objections
> >> to creating virtual device nodes and haven't allowed creation of nodes
> >> for cpufreq drivers.. For which there is no physical device, as CPU already
> >> has a separate node..
> >
> > as we already have the "enable-method" property for enabling/disabling cpus,
> > would something like a "scaling-method" be feasible?
Good idea to put it as a property into the CPU node.
> Lets see what DT maintainers have to say on this, I would rather go for a
> more straight forward name: "scaling-driver" ..
Both sound fine to me.
Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global
2014-05-14 3:50 ` Viresh Kumar
@ 2014-05-14 13:26 ` Thomas Abraham
0 siblings, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 13:26 UTC (permalink / raw)
To: Viresh Kumar
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Heiko Stübner
On Wed, May 14, 2014 at 9:20 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 14 May 2014 06:41, Thomas Abraham <ta.omasab@gmail.com> wrote:
>> From: Thomas Abraham <thomas.ab@samsung.com>
>>
>> Access to samsung clock lock is required to support newer samsung specific
>> clock types. So change the scope of the samsung clock lock to global. And
>
> Maybe bit more detail on why exactly it should be available outside this file.
Okay, will do in the next version.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 6:20 ` Viresh Kumar
@ 2014-05-14 13:43 ` Thomas Abraham
2014-05-14 13:50 ` Viresh Kumar
0 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 13:43 UTC (permalink / raw)
To: Viresh Kumar
Cc: Lukasz Majewski, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
Hi Lukasz, Viresh,
On Wed, May 14, 2014 at 11:50 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 14 May 2014 11:47, Lukasz Majewski <l.majewski@samsung.com> wrote:
>> I think that you can rely solely on the CPU_FREQ_BOOST_SW flag if the
>> original author of cpufreq-cpu0.c don't mind.
>
> We don't have to. struct cpufreq_driver: boost_supported is always available.
> Just update it without any ugly #ifdefs ..
Okay, so you are suggesting that Kconfig entry used to select
cpufreq-cpu0 should also enable CPU_FREQ_BOOST_SW config as well.
Considering that exynos4412 is the only user of this feature in
mainline, should we do this?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:18 ` Arnd Bergmann
@ 2014-05-14 13:45 ` Rob Herring
2014-05-14 14:33 ` Arnd Bergmann
0 siblings, 1 reply; 58+ messages in thread
From: Rob Herring @ 2014-05-14 13:45 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel@lists.infradead.org, Viresh Kumar,
Heiko Stübner, Rob Herring, Grant Likely,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Thomas Abraham, Tomasz Figa, Rafael J. Wysocki,
cpufreq@vger.kernel.org, linux-samsung-soc, Thomas P Abraham,
Mike Turquette, Shawn Guo
On Wed, May 14, 2014 at 8:18 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 14 May 2014 18:44:46 Viresh Kumar wrote:
>> On 14 May 2014 18:41, Heiko Stübner <heiko@sntech.de> wrote:
>> > Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
>> >> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
>> >> > Could we please come up with a way to probe this from DT in the
>> >> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
>> >> > platform using it?
>>
>> >> Its followed that way because DT Maintainers had strong objections
>> >> to creating virtual device nodes and haven't allowed creation of nodes
>> >> for cpufreq drivers.. For which there is no physical device, as CPU already
>> >> has a separate node..
>> >
>> > as we already have the "enable-method" property for enabling/disabling cpus,
>> > would something like a "scaling-method" be feasible?
>
> Good idea to put it as a property into the CPU node.
We already have properties which indicate this driver can be used by a
platform: opp table and a clock for the cpu. If this information is
not sufficient to determine whether you can use this driver or not,
then you simply need to match against the platform. Perhaps the match
list should be a blacklist rather than a whitelist, so new platforms
work without a kernel change.
Alternatively, create a new OPP binding that addresses this and all
the other limitations in the current OPP binding.
>> Lets see what DT maintainers have to say on this, I would rather go for a
>> more straight forward name: "scaling-driver" ..
>
> Both sound fine to me.
The fact that linux needs a way to create a platform device to enable
a certain driver is not a DT problem. I proposed a solution for how to
get this out of the platform code [1], but evidently we want people to
open code the exceptions and adding boilerplate helpers will just
encourage the exceptions.
Rob
[1] https://lkml.org/lkml/2013/10/30/30
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 13:43 ` Thomas Abraham
@ 2014-05-14 13:50 ` Viresh Kumar
2014-05-14 14:18 ` Thomas Abraham
0 siblings, 1 reply; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 13:50 UTC (permalink / raw)
To: Thomas Abraham
Cc: Lukasz Majewski, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
On 14 May 2014 19:13, Thomas Abraham <ta.omasab@gmail.com> wrote:
> Okay, so you are suggesting that Kconfig entry used to select
> cpufreq-cpu0 should also enable CPU_FREQ_BOOST_SW config as well.
I never said that... That should be enabled by your defconfig instead.
What I said was, don't put code within any #ifdefs in cpufreq-cpu0.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support
2014-05-14 7:20 ` Lukasz Majewski
@ 2014-05-14 13:53 ` Thomas Abraham
0 siblings, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 13:53 UTC (permalink / raw)
To: Lukasz Majewski
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, Kukjin Kim, Mike Turquette,
Heiko Stübner, Viresh Kumar, Tomasz Figa, rjw@rjwysocki.net,
linux-samsung-soc@vger.kernel.org, Shawn Guo
Hi Lukasz,
On Wed, May 14, 2014 at 12:50 PM, Lukasz Majewski
<l.majewski@samsung.com> wrote:
> Hi Thomas,
>
>> -config ARM_EXYNOS_CPU_FREQ_BOOST_SW
>> - bool "EXYNOS Frequency Overclocking - Software"
>> - depends on ARM_EXYNOS_CPUFREQ
>> - select CPU_FREQ_BOOST_SW
>> - select EXYNOS_THERMAL
>> - help
>> - This driver supports software managed overclocking (BOOST).
>> - It allows usage of special frequencies for Samsung Exynos
>> - processors if thermal conditions are appropriate.
>> -
>> - It reguires, for safe operation, thermal framework with
>> properly
>> - defined trip points.
>> -
>> - If in doubt, say N.
>> -
>
> If I might ask, where this switch,to enable BOOST, will be moved? All
> in all, I would like to be able to enable boost :-).
The intent was to have a separate boost config option for cpufreq-cpu0
driver, only available if cpufreq-cpu0 driver is selected, as done in
the other patch.
>
> In my opinion we should have the Kconfig option to enable/disable the
> CPU_FREQ_BOOST_SW and this may be used with cpufreq-cpu0 driver as I've
> pointed out in the other patch.
Okay, this is how this patch series handles CPU_FREQ_BOOST_SW config option.
Thanks,
Thomas.
>
> --
> Best regards,
>
> Lukasz Majewski
>
> Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:11 ` Heiko Stübner
2014-05-14 13:14 ` Viresh Kumar
@ 2014-05-14 14:03 ` Thomas Abraham
2014-05-14 14:09 ` Sudeep Holla
1 sibling, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 14:03 UTC (permalink / raw)
To: Heiko Stübner
Cc: Viresh Kumar, Arnd Bergmann, linux-arm-kernel@lists.infradead.org,
cpufreq@vger.kernel.org, devicetree@vger.kernel.org,
Lukasz Majewski, Kukjin Kim, Mike Turquette, Tomasz Figa,
Rafael J. Wysocki, linux-samsung-soc, Shawn Guo
On Wed, May 14, 2014 at 6:41 PM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
>> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
>> > Could we please come up with a way to probe this from DT in the
>> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
>> > platform using it?
>> Its followed that way because DT Maintainers had strong objections
>> to creating virtual device nodes and haven't allowed creation of nodes
>> for cpufreq drivers.. For which there is no physical device, as CPU already
>> has a separate node..
>
> as we already have the "enable-method" property for enabling/disabling cpus,
> would something like a "scaling-method" be feasible?
>
"scaling-method" also sounds like a software specific property. Would
that be something that will be acceptable in dt?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 14:03 ` Thomas Abraham
@ 2014-05-14 14:09 ` Sudeep Holla
0 siblings, 0 replies; 58+ messages in thread
From: Sudeep Holla @ 2014-05-14 14:09 UTC (permalink / raw)
To: Thomas Abraham, Heiko Stübner
Cc: Sudeep Holla, Viresh Kumar, Arnd Bergmann,
linux-arm-kernel@lists.infradead.org, cpufreq@vger.kernel.org,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Mike Turquette, Tomasz Figa, Rafael J. Wysocki, linux-samsung-soc,
Shawn Guo
On 14/05/14 15:03, Thomas Abraham wrote:
> On Wed, May 14, 2014 at 6:41 PM, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
>>> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
>>>> Could we please come up with a way to probe this from DT in the
>>>> cpufreq-cpu0 driver itself, so we don't have to add a device in every
>>>> platform using it?
>>> Its followed that way because DT Maintainers had strong objections
>>> to creating virtual device nodes and haven't allowed creation of nodes
>>> for cpufreq drivers.. For which there is no physical device, as CPU already
>>> has a separate node..
>>
>> as we already have the "enable-method" property for enabling/disabling cpus,
>> would something like a "scaling-method" be feasible?
>>
>
> "scaling-method" also sounds like a software specific property. Would
> that be something that will be acceptable in dt?
How about dvfs-method ? But the value should not be based on the driver they
use, but something more generic.
Regards,
Sudeep
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 12:50 ` Arnd Bergmann
2014-05-14 13:05 ` Viresh Kumar
@ 2014-05-14 14:09 ` Thomas Abraham
1 sibling, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 14:09 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel@lists.infradead.org, cpufreq@vger.kernel.org,
devicetree@vger.kernel.org, Lukasz Majewski, Kukjin Kim,
Mike Turquette, Heiko Stübner, Viresh Kumar, Tomasz Figa,
rjw@rjwysocki.net, linux-samsung-soc@vger.kernel.org, Shawn Guo
On Wed, May 14, 2014 at 6:20 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 14 May 2014 06:41:15 Thomas Abraham wrote:
>> From: Thomas Abraham <thomas.ab@samsung.com>
>>
>> Remove the platform device instantiation for Exynos specific cpufreq
>> driver and add the platform device for cpufreq-cpu0 driver.
>>
>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> ---
>> arch/arm/mach-exynos/exynos.c | 4 +++-
>> 1 files changed, 3 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
>> index b32a907..489a495 100644
>> --- a/arch/arm/mach-exynos/exynos.c
>> +++ b/arch/arm/mach-exynos/exynos.c
>> @@ -232,7 +232,9 @@ void __init exynos_cpuidle_init(void)
>>
>> void __init exynos_cpufreq_init(void)
>> {
>> - platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
>> + if (!(of_machine_is_compatible("samsung,exynos5420")) &&
>> + !(of_machine_is_compatible("samsung,exynos5440")))
>> + platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
>> }
>>
>
> Could we please come up with a way to probe this from DT in the cpufreq-cpu0
> driver itself, so we don't have to add a device in every platform using it?
Okay, I don't have a solution for this as of now. Would this be
considered as a blocker for this series? I hope we could just live
with this for now.
Thanks,
Thomas.
>
> I realize you copied it from the other platforms using this driver, but
> it still seems really wrong.
>
> Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 13:50 ` Viresh Kumar
@ 2014-05-14 14:18 ` Thomas Abraham
2014-05-14 14:20 ` Viresh Kumar
0 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-14 14:18 UTC (permalink / raw)
To: Viresh Kumar
Cc: Lukasz Majewski, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
On Wed, May 14, 2014 at 7:20 PM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 14 May 2014 19:13, Thomas Abraham <ta.omasab@gmail.com> wrote:
>> Okay, so you are suggesting that Kconfig entry used to select
>> cpufreq-cpu0 should also enable CPU_FREQ_BOOST_SW config as well.
>
> I never said that... That should be enabled by your defconfig instead.
> What I said was, don't put code within any #ifdefs in cpufreq-cpu0.
Okay, I get the point about #ifdef in cpufreq-cpu0. What about your
earlier comment about the new Kconfig entry ("Get rid of this.. just
not required.")? The new Kconfig entry would be needed in that case.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
2014-05-14 14:18 ` Thomas Abraham
@ 2014-05-14 14:20 ` Viresh Kumar
0 siblings, 0 replies; 58+ messages in thread
From: Viresh Kumar @ 2014-05-14 14:20 UTC (permalink / raw)
To: Thomas Abraham
Cc: Lukasz Majewski, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Heiko Stübner
On 14 May 2014 19:48, Thomas Abraham <ta.omasab@gmail.com> wrote:
> Okay, I get the point about #ifdef in cpufreq-cpu0. What about your
> earlier comment about the new Kconfig entry ("Get rid of this.. just
> not required.")? The new Kconfig entry would be needed in that case.
The only place you used that ifdef was in cpufreq-cpu0, which we
already decided should stay without any ifdefs..
Now, you must enable CPU_FREQ_BOOST_SW from your defconfig.
Did I make it clear this time ?
--
viresh
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 13:45 ` Rob Herring
@ 2014-05-14 14:33 ` Arnd Bergmann
2014-07-08 5:15 ` Viresh Kumar
0 siblings, 1 reply; 58+ messages in thread
From: Arnd Bergmann @ 2014-05-14 14:33 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Rob Herring, devicetree@vger.kernel.org, Lukasz Majewski,
Kukjin Kim, Thomas Abraham, Heiko Stübner, Rob Herring,
Viresh Kumar, Tomasz Figa, Rafael J. Wysocki,
cpufreq@vger.kernel.org, linux-samsung-soc, Thomas P Abraham,
Grant Likely, Mike Turquette, Shawn Guo
On Wednesday 14 May 2014 08:45:23 Rob Herring wrote:
> On Wed, May 14, 2014 at 8:18 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Wednesday 14 May 2014 18:44:46 Viresh Kumar wrote:
> >> On 14 May 2014 18:41, Heiko Stübner <heiko@sntech.de> wrote:
> >> > Am Mittwoch, 14. Mai 2014, 18:35:29 schrieb Viresh Kumar:
> >> >> On 14 May 2014 18:20, Arnd Bergmann <arnd@arndb.de> wrote:
> >> >> > Could we please come up with a way to probe this from DT in the
> >> >> > cpufreq-cpu0 driver itself, so we don't have to add a device in every
> >> >> > platform using it?
> >>
> >> >> Its followed that way because DT Maintainers had strong objections
> >> >> to creating virtual device nodes and haven't allowed creation of nodes
> >> >> for cpufreq drivers.. For which there is no physical device, as CPU already
> >> >> has a separate node..
> >> >
> >> > as we already have the "enable-method" property for enabling/disabling cpus,
> >> > would something like a "scaling-method" be feasible?
> >
> > Good idea to put it as a property into the CPU node.
>
> We already have properties which indicate this driver can be used by a
> platform: opp table and a clock for the cpu. If this information is
> not sufficient to determine whether you can use this driver or not,
> then you simply need to match against the platform. Perhaps the match
> list should be a blacklist rather than a whitelist, so new platforms
> work without a kernel change.
We'd not only need a blacklist, but also a way to tell whether we
want to use the cpu0 or the big/little implementation, which currently
have indistinguishable bindings.
> Alternatively, create a new OPP binding that addresses this and all
> the other limitations in the current OPP binding.
Yes.
> >> Lets see what DT maintainers have to say on this, I would rather go for a
> >> more straight forward name: "scaling-driver" ..
> >
> > Both sound fine to me.
>
> The fact that linux needs a way to create a platform device to enable
> a certain driver is not a DT problem. I proposed a solution for how to
> get this out of the platform code [1], but evidently we want people to
> open code the exceptions and adding boilerplate helpers will just
> encourage the exceptions.
I think the only benefit we have from using platform devices at all
for cpufreq (not for cpuidle, which has a similar problem) is module
autoloading. I think your patch doesn't actually help with that.
Arnd
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-14 1:11 ` [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock Thomas Abraham
@ 2014-05-14 21:37 ` Mike Turquette
2014-05-15 7:48 ` Thomas Abraham
2014-05-16 5:14 ` Thomas Abraham
2014-05-16 23:57 ` Tomasz Figa
1 sibling, 2 replies; 58+ messages in thread
From: Mike Turquette @ 2014-05-14 21:37 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: shawn.guo, devicetree, rjw, linux-samsung-soc, kgene.kim, t.figa,
l.majewski, viresh.kumar, heiko, thomas.ab
Quoting Thomas Abraham (2014-05-13 18:11:13)
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> With the addition of the new Samsung specific cpu-clock type, the
> arm clock can be represented as a cpu-clock type and the independent
> clock blocks that made up the arm clock can be removed.
<rant>
I am not a fan of this type of "clock hiding". Certainly the design of
the CCF allows for a clock provider to obfuscate it's internals; there
was never a requirement that every clock node be exposed to Linux as a
struct clk. A truly obfuscated system could only expose leaf clocks that
are consumed by Linux device drivers, and never expose any of the
intermediary clocks in between the input clock signal (if it exists) and
the leaf nodes.
However I feel that this patch is more of a workaround to the fact that
the clock framework today does not make DVFS transitions (or
coordinated, multi-clock rate change transitions) easy to control. The
generic "walk up the tree" algorithm might give you the right rate, but
perhaps using a non-validated combination of PLL frequency and
adjustable-rate dividers, or a combination that his higher jitter or is
more likely to unlock at higher temperatures, etc.
Back in the pre-CCF days lots of folks implemented this with "virtual"
clock nodes that simply called "clk_set_rate" or whatever on the
affected clocks, or even worse just banged a bunch of registers.
The cbus clock series for Tegra is also looks a little like this.
</rant>
Thomas,
Would a coordinated clock rate change method solve this problem for you
in place of the cpu-clock provider type? A poorly conceived call graph
for this might look something like:
clk_set_rate(div_arm2, 1000000);
-> if (div_arm2->coordinated == true)
clk_coordinate_rates(div_arm2, 1000000);
-> clk->ops->coordinate(div_arm2->hw, 1000000);
-> vendor_supplied_magic()
The vendor_supplied_magic() would be a callback that essentially calls
clk_set_rate() on all of the affected (coordinated) clocks. In your case
that looks like mout_core, div_core, div_core2, arm_clk and sclk_apll
for Exynos4.
The trick is that calling clk_set_rate() from any driver would initiate
this coordinated rate change, and then the exynos clock driver would set
up the coordinated clocks itself. No new API is introduced to drivers
(since it still uses clk_set_rate) and now a new clock provider doesn't
have to be invented every time we have a couple of clocks involved in a
DVFS transition.
Does this sound right to you or have I horribly misinterpreted the point
of these clock patches?
Thanks,
Mike
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> drivers/clk/samsung/clk-exynos4.c | 25 +++++++++----------------
> drivers/clk/samsung/clk-exynos5250.c | 12 ++++++------
> include/dt-bindings/clock/exynos5250.h | 1 +
> 3 files changed, 16 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> index b4f9672..7e3bb16c 100644
> --- a/drivers/clk/samsung/clk-exynos4.c
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -471,7 +471,6 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
> MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
> MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
> MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
> @@ -530,7 +529,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
> MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
> MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
> MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
> @@ -572,8 +570,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>
> /* list of divider clocks supported in all exynos4 soc's */
> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
> @@ -619,8 +615,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
> DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
> DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
> DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
> + CLK_GET_RATE_NOCACHE, 0),
> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
> CLK_SET_RATE_PARENT, 0),
> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
> 0),
> };
>
> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
> -};
> -
> static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
> ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
> };
> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct device_node *np,
> ARRAY_SIZE(exynos4210_gate_clks));
> samsung_clk_register_alias(exynos4210_aliases,
> ARRAY_SIZE(exynos4210_aliases));
> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4210,
> + ARRAY_SIZE(mout_core_p4210), reg_base, np, NULL,
> + &samsung_clk_lock);
> } else {
> samsung_clk_register_mux(exynos4x12_mux_clks,
> ARRAY_SIZE(exynos4x12_mux_clks));
> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct device_node *np,
> ARRAY_SIZE(exynos4x12_gate_clks));
> samsung_clk_register_alias(exynos4x12_aliases,
> ARRAY_SIZE(exynos4x12_aliases));
> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4x12,
> + ARRAY_SIZE(mout_core_p4x12), reg_base, np, NULL,
> + &samsung_clk_lock);
> }
>
> - samsung_clk_register_alias(exynos4_aliases,
> - ARRAY_SIZE(exynos4_aliases));
> -
> exynos4_clk_sleep_init();
>
> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
> exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
> _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
> - _get_rate("arm_clk"));
> + _get_rate("armclk"));
> }
>
>
> diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
> index e7ee442..3fe1ca0 100644
> --- a/drivers/clk/samsung/clk-exynos5250.c
> +++ b/drivers/clk/samsung/clk-exynos5250.c
> @@ -260,8 +260,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
> */
> MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
> CLK_SET_RATE_PARENT, 0, "mout_apll"),
> - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
> -
> /*
> * CMU_CORE
> */
> @@ -339,9 +337,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
> /*
> * CMU_CPU
> */
> - DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
> - DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
> - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
> + DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
> + CLK_GET_RATE_NOCACHE, 0),
>
> /*
> * CMU_TOP
> @@ -721,10 +718,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
> ARRAY_SIZE(exynos5250_div_clks));
> samsung_clk_register_gate(exynos5250_gate_clks,
> ARRAY_SIZE(exynos5250_gate_clks));
> + exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
> + ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
> + &samsung_clk_lock);
>
> exynos5250_clk_sleep_init();
>
> pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
> - _get_rate("div_arm2"));
> + _get_rate("armclk"));
> }
> CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
> diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h
> index 922f2dc..59a10fb 100644
> --- a/include/dt-bindings/clock/exynos5250.h
> +++ b/include/dt-bindings/clock/exynos5250.h
> @@ -21,6 +21,7 @@
> #define CLK_FOUT_CPLL 6
> #define CLK_FOUT_EPLL 7
> #define CLK_FOUT_VPLL 8
> +#define CLK_ARM_CLK 12
>
> /* gate for special clocks (sclk) */
> #define CLK_SCLK_CAM_BAYER 128
> --
> 1.7.4.4
>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-14 21:37 ` Mike Turquette
@ 2014-05-15 7:48 ` Thomas Abraham
2014-05-15 8:10 ` Lukasz Majewski
2014-05-16 5:14 ` Thomas Abraham
1 sibling, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-15 7:48 UTC (permalink / raw)
To: Mike Turquette
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Shawn Guo, devicetree@vger.kernel.org, rjw@rjwysocki.net,
linux-samsung-soc@vger.kernel.org, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Viresh Kumar, Heiko Stübner
On Thu, May 15, 2014 at 3:07 AM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Thomas Abraham (2014-05-13 18:11:13)
>> From: Thomas Abraham <thomas.ab@samsung.com>
>>
>> With the addition of the new Samsung specific cpu-clock type, the
>> arm clock can be represented as a cpu-clock type and the independent
>> clock blocks that made up the arm clock can be removed.
>
> <rant>
>
> I am not a fan of this type of "clock hiding". Certainly the design of
> the CCF allows for a clock provider to obfuscate it's internals; there
> was never a requirement that every clock node be exposed to Linux as a
> struct clk. A truly obfuscated system could only expose leaf clocks that
> are consumed by Linux device drivers, and never expose any of the
> intermediary clocks in between the input clock signal (if it exists) and
> the leaf nodes.
>
> However I feel that this patch is more of a workaround to the fact that
> the clock framework today does not make DVFS transitions (or
> coordinated, multi-clock rate change transitions) easy to control. The
> generic "walk up the tree" algorithm might give you the right rate, but
> perhaps using a non-validated combination of PLL frequency and
> adjustable-rate dividers, or a combination that his higher jitter or is
> more likely to unlock at higher temperatures, etc.
>
> Back in the pre-CCF days lots of folks implemented this with "virtual"
> clock nodes that simply called "clk_set_rate" or whatever on the
> affected clocks, or even worse just banged a bunch of registers.
>
> The cbus clock series for Tegra is also looks a little like this.
>
> </rant>
>
> Thomas,
>
> Would a coordinated clock rate change method solve this problem for you
> in place of the cpu-clock provider type? A poorly conceived call graph
> for this might look something like:
>
> clk_set_rate(div_arm2, 1000000);
> -> if (div_arm2->coordinated == true)
> clk_coordinate_rates(div_arm2, 1000000);
> -> clk->ops->coordinate(div_arm2->hw, 1000000);
> -> vendor_supplied_magic()
>
> The vendor_supplied_magic() would be a callback that essentially calls
> clk_set_rate() on all of the affected (coordinated) clocks. In your case
> that looks like mout_core, div_core, div_core2, arm_clk and sclk_apll
> for Exynos4.
>
> The trick is that calling clk_set_rate() from any driver would initiate
> this coordinated rate change, and then the exynos clock driver would set
> up the coordinated clocks itself. No new API is introduced to drivers
> (since it still uses clk_set_rate) and now a new clock provider doesn't
> have to be invented every time we have a couple of clocks involved in a
> DVFS transition.
>
> Does this sound right to you or have I horribly misinterpreted the point
> of these clock patches?
Mike,
Thanks for your comments. If I have understood the coordinated clock
as described above, I believe this patch series also attempts to do
almost the same thing. The advantage of using coordinated clock over
the approach in this series is that each platform need not define a
new clock type.
In this patch series, for all exynos SoC's, a new cpu clock type was
introduced which is reusable for multi-cluster exynos SoCs as well.
The new clock type is part of the clock driver and all drivers can use
standard clock API to access this clock type instance.
So probably, all the logic for the new cpu_clk clock type introduced
in this patch would go into the vendor_supplied_magic() callback. So
it sounds like the coordinated clock approach would be helpful. Is
this something that you are already working on?
Thanks,
Thomas.
>
> Thanks,
> Mike
>
>>
>> Cc: Tomasz Figa <t.figa@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> ---
>> drivers/clk/samsung/clk-exynos4.c | 25 +++++++++----------------
>> drivers/clk/samsung/clk-exynos5250.c | 12 ++++++------
>> include/dt-bindings/clock/exynos5250.h | 1 +
>> 3 files changed, 16 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
>> index b4f9672..7e3bb16c 100644
>> --- a/drivers/clk/samsung/clk-exynos4.c
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -471,7 +471,6 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
>> MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
>> MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
>> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
>> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
>> MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
>> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
>> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
>> @@ -530,7 +529,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>> MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
>> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
>> MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
>> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
>> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
>> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
>> MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
>> @@ -572,8 +570,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>>
>> /* list of divider clocks supported in all exynos4 soc's */
>> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
>> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
>> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
>> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
>> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
>> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
>> @@ -619,8 +615,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
>> DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
>> DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
>> DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
>> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
>> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
>> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
>> + CLK_GET_RATE_NOCACHE, 0),
>> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
>> CLK_SET_RATE_PARENT, 0),
>> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
>> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
>> 0),
>> };
>>
>> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
>> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
>> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
>> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
>> -};
>> -
>> static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
>> ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
>> };
>> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct device_node *np,
>> ARRAY_SIZE(exynos4210_gate_clks));
>> samsung_clk_register_alias(exynos4210_aliases,
>> ARRAY_SIZE(exynos4210_aliases));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4210,
>> + ARRAY_SIZE(mout_core_p4210), reg_base, np, NULL,
>> + &samsung_clk_lock);
>> } else {
>> samsung_clk_register_mux(exynos4x12_mux_clks,
>> ARRAY_SIZE(exynos4x12_mux_clks));
>> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct device_node *np,
>> ARRAY_SIZE(exynos4x12_gate_clks));
>> samsung_clk_register_alias(exynos4x12_aliases,
>> ARRAY_SIZE(exynos4x12_aliases));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4x12,
>> + ARRAY_SIZE(mout_core_p4x12), reg_base, np, NULL,
>> + &samsung_clk_lock);
>> }
>>
>> - samsung_clk_register_alias(exynos4_aliases,
>> - ARRAY_SIZE(exynos4_aliases));
>> -
>> exynos4_clk_sleep_init();
>>
>> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
>> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
>> exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
>> _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
>> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
>> - _get_rate("arm_clk"));
>> + _get_rate("armclk"));
>> }
>>
>>
>> diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
>> index e7ee442..3fe1ca0 100644
>> --- a/drivers/clk/samsung/clk-exynos5250.c
>> +++ b/drivers/clk/samsung/clk-exynos5250.c
>> @@ -260,8 +260,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
>> */
>> MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
>> CLK_SET_RATE_PARENT, 0, "mout_apll"),
>> - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
>> -
>> /*
>> * CMU_CORE
>> */
>> @@ -339,9 +337,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
>> /*
>> * CMU_CPU
>> */
>> - DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
>> - DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
>> - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
>> + DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
>> + CLK_GET_RATE_NOCACHE, 0),
>>
>> /*
>> * CMU_TOP
>> @@ -721,10 +718,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
>> ARRAY_SIZE(exynos5250_div_clks));
>> samsung_clk_register_gate(exynos5250_gate_clks,
>> ARRAY_SIZE(exynos5250_gate_clks));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
>> + ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
>> + &samsung_clk_lock);
>>
>> exynos5250_clk_sleep_init();
>>
>> pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
>> - _get_rate("div_arm2"));
>> + _get_rate("armclk"));
>> }
>> CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
>> diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h
>> index 922f2dc..59a10fb 100644
>> --- a/include/dt-bindings/clock/exynos5250.h
>> +++ b/include/dt-bindings/clock/exynos5250.h
>> @@ -21,6 +21,7 @@
>> #define CLK_FOUT_CPLL 6
>> #define CLK_FOUT_EPLL 7
>> #define CLK_FOUT_VPLL 8
>> +#define CLK_ARM_CLK 12
>>
>> /* gate for special clocks (sclk) */
>> #define CLK_SCLK_CAM_BAYER 128
>> --
>> 1.7.4.4
>>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-15 7:48 ` Thomas Abraham
@ 2014-05-15 8:10 ` Lukasz Majewski
2014-05-15 9:59 ` Thomas Abraham
0 siblings, 1 reply; 58+ messages in thread
From: Lukasz Majewski @ 2014-05-15 8:10 UTC (permalink / raw)
To: Thomas Abraham
Cc: Mike Turquette, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org, Heiko Stübner,
Viresh Kumar, Tomasz Figa, rjw@rjwysocki.net,
cpufreq@vger.kernel.org, Kukjin Kim, Shawn Guo,
linux-arm-kernel@lists.infradead.org
Hi Thomas,
> On Thu, May 15, 2014 at 3:07 AM, Mike Turquette
> <mturquette@linaro.org> wrote:
> > Quoting Thomas Abraham (2014-05-13 18:11:13)
> >> From: Thomas Abraham <thomas.ab@samsung.com>
> >>
> >> With the addition of the new Samsung specific cpu-clock type, the
> >> arm clock can be represented as a cpu-clock type and the
> >> independent clock blocks that made up the arm clock can be removed.
> >
> > <rant>
> >
> > I am not a fan of this type of "clock hiding". Certainly the design
> > of the CCF allows for a clock provider to obfuscate it's internals;
> > there was never a requirement that every clock node be exposed to
> > Linux as a struct clk. A truly obfuscated system could only expose
> > leaf clocks that are consumed by Linux device drivers, and never
> > expose any of the intermediary clocks in between the input clock
> > signal (if it exists) and the leaf nodes.
> >
> > However I feel that this patch is more of a workaround to the fact
> > that the clock framework today does not make DVFS transitions (or
> > coordinated, multi-clock rate change transitions) easy to control.
> > The generic "walk up the tree" algorithm might give you the right
> > rate, but perhaps using a non-validated combination of PLL
> > frequency and adjustable-rate dividers, or a combination that his
> > higher jitter or is more likely to unlock at higher temperatures,
> > etc.
> >
> > Back in the pre-CCF days lots of folks implemented this with
> > "virtual" clock nodes that simply called "clk_set_rate" or whatever
> > on the affected clocks, or even worse just banged a bunch of
> > registers.
> >
> > The cbus clock series for Tegra is also looks a little like this.
> >
> > </rant>
> >
> > Thomas,
> >
> > Would a coordinated clock rate change method solve this problem for
> > you in place of the cpu-clock provider type? A poorly conceived
> > call graph for this might look something like:
> >
> > clk_set_rate(div_arm2, 1000000);
> > -> if (div_arm2->coordinated == true)
> > clk_coordinate_rates(div_arm2, 1000000);
> > -> clk->ops->coordinate(div_arm2->hw, 1000000);
> > -> vendor_supplied_magic()
> >
> > The vendor_supplied_magic() would be a callback that essentially
> > calls clk_set_rate() on all of the affected (coordinated) clocks.
> > In your case that looks like mout_core, div_core, div_core2,
> > arm_clk and sclk_apll for Exynos4.
I might misinterpret the idea here, but is clk_set_rate() function
ready to handle atomic change for several clocks? Especially setting
rate of dividers located in the same register, represented as different
clocks to CCF.
As fair as I remember it was not possible to serialize operations on
clocks with calling clk_set_rate() several times. Those had to be done
instantly, otherwise platform hanged.
Am I missing something, or a major improvement had I overlooked?
> >
> > The trick is that calling clk_set_rate() from any driver would
> > initiate this coordinated rate change, and then the exynos clock
> > driver would set up the coordinated clocks itself. No new API is
> > introduced to drivers (since it still uses clk_set_rate) and now a
> > new clock provider doesn't have to be invented every time we have a
> > couple of clocks involved in a DVFS transition.
> >
> > Does this sound right to you or have I horribly misinterpreted the
> > point of these clock patches?
>
> Mike,
>
> Thanks for your comments. If I have understood the coordinated clock
> as described above, I believe this patch series also attempts to do
> almost the same thing. The advantage of using coordinated clock over
> the approach in this series is that each platform need not define a
> new clock type.
>
> In this patch series, for all exynos SoC's, a new cpu clock type was
> introduced which is reusable for multi-cluster exynos SoCs as well.
> The new clock type is part of the clock driver and all drivers can use
> standard clock API to access this clock type instance.
>
> So probably, all the logic for the new cpu_clk clock type introduced
> in this patch would go into the vendor_supplied_magic() callback. So
> it sounds like the coordinated clock approach would be helpful. Is
> this something that you are already working on?
>
> Thanks,
> Thomas.
>
> >
> > Thanks,
> > Mike
> >
> >>
> >> Cc: Tomasz Figa <t.figa@samsung.com>
> >> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> >> ---
> >> drivers/clk/samsung/clk-exynos4.c | 25
> >> +++++++++---------------- drivers/clk/samsung/clk-exynos5250.c
> >> | 12 ++++++------ include/dt-bindings/clock/exynos5250.h | 1 +
> >> 3 files changed, 16 insertions(+), 22 deletions(-)
> >>
> >> diff --git a/drivers/clk/samsung/clk-exynos4.c
> >> b/drivers/clk/samsung/clk-exynos4.c index b4f9672..7e3bb16c 100644
> >> --- a/drivers/clk/samsung/clk-exynos4.c
> >> +++ b/drivers/clk/samsung/clk-exynos4.c
> >> @@ -471,7 +471,6 @@ static struct samsung_mux_clock
> >> exynos4210_mux_clks[] __initdata = { MUX(0, "mout_fimd1",
> >> group1_p4210, E4210_SRC_LCD1, 0, 4), MUX(0, "mout_mipi1",
> >> group1_p4210, E4210_SRC_LCD1, 12, 4), MUX(CLK_SCLK_MPLL,
> >> "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
> >> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU,
> >> 16, 1), MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0,
> >> 8, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0,
> >> 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
> >> @@ -530,7 +529,6 @@ static struct samsung_mux_clock
> >> exynos4x12_mux_clks[] __initdata = { MUX(0, "mout_jpeg",
> >> mout_jpeg_p, E4X12_SRC_CAM1, 8, 1), MUX(CLK_SCLK_MPLL,
> >> "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1), MUX(CLK_SCLK_VPLL,
> >> "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
> >> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU,
> >> 16, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM,
> >> 0, 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4,
> >> 4), MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
> >> @@ -572,8 +570,6 @@ static struct samsung_mux_clock
> >> exynos4x12_mux_clks[] __initdata = {
> >>
> >> /* list of divider clocks supported in all exynos4 soc's */
> >> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
> >> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
> >> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
> >> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
> >> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
> >> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
> >> @@ -619,8 +615,8 @@ static struct samsung_div_clock
> >> exynos4_div_clks[] __initdata = { DIV(0, "div_spi_pre2",
> >> "div_spi2", DIV_PERIL2, 8, 8), DIV(0, "div_audio1", "mout_audio1",
> >> DIV_PERIL4, 0, 4), DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4,
> >> 16, 4),
> >> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
> >> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24,
> >> 3),
> >> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0,
> >> 24, 3,
> >> + CLK_GET_RATE_NOCACHE, 0),
> >> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
> >> CLK_SET_RATE_PARENT, 0),
> >> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
> >> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock
> >> exynos4x12_gate_clks[] __initdata = { 0),
> >> };
> >>
> >> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
> >> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
> >> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
> >> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
> >> -};
> >> -
> >> static struct samsung_clock_alias exynos4210_aliases[] __initdata
> >> = { ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
> >> };
> >> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct
> >> device_node *np, ARRAY_SIZE(exynos4210_gate_clks));
> >> samsung_clk_register_alias(exynos4210_aliases,
> >> ARRAY_SIZE(exynos4210_aliases));
> >> + exynos_register_arm_clock(CLK_ARM_CLK,
> >> mout_core_p4210,
> >> + ARRAY_SIZE(mout_core_p4210), reg_base, np,
> >> NULL,
> >> + &samsung_clk_lock);
> >> } else {
> >> samsung_clk_register_mux(exynos4x12_mux_clks,
> >> ARRAY_SIZE(exynos4x12_mux_clks));
> >> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct
> >> device_node *np, ARRAY_SIZE(exynos4x12_gate_clks));
> >> samsung_clk_register_alias(exynos4x12_aliases,
> >> ARRAY_SIZE(exynos4x12_aliases));
> >> + exynos_register_arm_clock(CLK_ARM_CLK,
> >> mout_core_p4x12,
> >> + ARRAY_SIZE(mout_core_p4x12), reg_base, np,
> >> NULL,
> >> + &samsung_clk_lock);
> >> }
> >>
> >> - samsung_clk_register_alias(exynos4_aliases,
> >> - ARRAY_SIZE(exynos4_aliases));
> >> -
> >> exynos4_clk_sleep_init();
> >>
> >> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
> >> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct
> >> device_node *np, exynos4_soc == EXYNOS4210 ? "Exynos4210" :
> >> "Exynos4x12", _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
> >> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
> >> - _get_rate("arm_clk"));
> >> + _get_rate("armclk"));
> >> }
> >>
> >>
> >> diff --git a/drivers/clk/samsung/clk-exynos5250.c
> >> b/drivers/clk/samsung/clk-exynos5250.c index e7ee442..3fe1ca0
> >> 100644 --- a/drivers/clk/samsung/clk-exynos5250.c
> >> +++ b/drivers/clk/samsung/clk-exynos5250.c
> >> @@ -260,8 +260,6 @@ static struct samsung_mux_clock
> >> exynos5250_mux_clks[] __initdata = { */
> >> MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
> >> CLK_SET_RATE_PARENT, 0,
> >> "mout_apll"),
> >> - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1,
> >> "mout_cpu"), -
> >> /*
> >> * CMU_CORE
> >> */
> >> @@ -339,9 +337,8 @@ static struct samsung_div_clock
> >> exynos5250_div_clks[] __initdata = { /*
> >> * CMU_CPU
> >> */
> >> - DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
> >> - DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
> >> - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
> >> + DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
> >> + CLK_GET_RATE_NOCACHE, 0),
> >>
> >> /*
> >> * CMU_TOP
> >> @@ -721,10 +718,13 @@ static void __init
> >> exynos5250_clk_init(struct device_node *np)
> >> ARRAY_SIZE(exynos5250_div_clks));
> >> samsung_clk_register_gate(exynos5250_gate_clks,
> >> ARRAY_SIZE(exynos5250_gate_clks));
> >> + exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
> >> + ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
> >> + &samsung_clk_lock);
> >>
> >> exynos5250_clk_sleep_init();
> >>
> >> pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
> >> - _get_rate("div_arm2"));
> >> + _get_rate("armclk"));
> >> }
> >> CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock",
> >> exynos5250_clk_init); diff --git
> >> a/include/dt-bindings/clock/exynos5250.h
> >> b/include/dt-bindings/clock/exynos5250.h index 922f2dc..59a10fb
> >> 100644 --- a/include/dt-bindings/clock/exynos5250.h +++
> >> b/include/dt-bindings/clock/exynos5250.h @@ -21,6 +21,7 @@
> >> #define CLK_FOUT_CPLL 6
> >> #define CLK_FOUT_EPLL 7
> >> #define CLK_FOUT_VPLL 8
> >> +#define CLK_ARM_CLK 12
> >>
> >> /* gate for special clocks (sclk) */
> >> #define CLK_SCLK_CAM_BAYER 128
> >> --
> >> 1.7.4.4
> >>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Best regards,
Lukasz Majewski
Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-15 8:10 ` Lukasz Majewski
@ 2014-05-15 9:59 ` Thomas Abraham
0 siblings, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-15 9:59 UTC (permalink / raw)
To: Lukasz Majewski
Cc: Mike Turquette, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org, Heiko Stübner,
Viresh Kumar, Tomasz Figa, rjw@rjwysocki.net,
cpufreq@vger.kernel.org, Kukjin Kim, Shawn Guo,
linux-arm-kernel@lists.infradead.org
On Thu, May 15, 2014 at 1:40 PM, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Hi Thomas,
>
>> On Thu, May 15, 2014 at 3:07 AM, Mike Turquette
>> <mturquette@linaro.org> wrote:
>> > Quoting Thomas Abraham (2014-05-13 18:11:13)
>> >> From: Thomas Abraham <thomas.ab@samsung.com>
>> >>
>> >> With the addition of the new Samsung specific cpu-clock type, the
>> >> arm clock can be represented as a cpu-clock type and the
>> >> independent clock blocks that made up the arm clock can be removed.
>> >
>> > <rant>
>> >
>> > I am not a fan of this type of "clock hiding". Certainly the design
>> > of the CCF allows for a clock provider to obfuscate it's internals;
>> > there was never a requirement that every clock node be exposed to
>> > Linux as a struct clk. A truly obfuscated system could only expose
>> > leaf clocks that are consumed by Linux device drivers, and never
>> > expose any of the intermediary clocks in between the input clock
>> > signal (if it exists) and the leaf nodes.
>> >
>> > However I feel that this patch is more of a workaround to the fact
>> > that the clock framework today does not make DVFS transitions (or
>> > coordinated, multi-clock rate change transitions) easy to control.
>> > The generic "walk up the tree" algorithm might give you the right
>> > rate, but perhaps using a non-validated combination of PLL
>> > frequency and adjustable-rate dividers, or a combination that his
>> > higher jitter or is more likely to unlock at higher temperatures,
>> > etc.
>> >
>> > Back in the pre-CCF days lots of folks implemented this with
>> > "virtual" clock nodes that simply called "clk_set_rate" or whatever
>> > on the affected clocks, or even worse just banged a bunch of
>> > registers.
>> >
>> > The cbus clock series for Tegra is also looks a little like this.
>> >
>> > </rant>
>> >
>> > Thomas,
>> >
>> > Would a coordinated clock rate change method solve this problem for
>> > you in place of the cpu-clock provider type? A poorly conceived
>> > call graph for this might look something like:
>> >
>> > clk_set_rate(div_arm2, 1000000);
>> > -> if (div_arm2->coordinated == true)
>> > clk_coordinate_rates(div_arm2, 1000000);
>> > -> clk->ops->coordinate(div_arm2->hw, 1000000);
>> > -> vendor_supplied_magic()
>> >
>> > The vendor_supplied_magic() would be a callback that essentially
>> > calls clk_set_rate() on all of the affected (coordinated) clocks.
>> > In your case that looks like mout_core, div_core, div_core2,
>> > arm_clk and sclk_apll for Exynos4.
>
> I might misinterpret the idea here, but is clk_set_rate() function
> ready to handle atomic change for several clocks? Especially setting
> rate of dividers located in the same register, represented as different
> clocks to CCF.
>
> As fair as I remember it was not possible to serialize operations on
> clocks with calling clk_set_rate() several times. Those had to be done
> instantly, otherwise platform hanged.
>
> Am I missing something, or a major improvement had I overlooked?
Hi Lukasz,
Not sure what Mike would suggest here, but probably the clk_set_rate()
itself might not be called for coordinated clocks. It could be some
internal clock framework function that takes care of setting rate of
coordinated clocks. I don't have a good understanding of how the
implementation for this will look like.
Thanks,
Thomas.
>
>> >
>> > The trick is that calling clk_set_rate() from any driver would
>> > initiate this coordinated rate change, and then the exynos clock
>> > driver would set up the coordinated clocks itself. No new API is
>> > introduced to drivers (since it still uses clk_set_rate) and now a
>> > new clock provider doesn't have to be invented every time we have a
>> > couple of clocks involved in a DVFS transition.
>> >
>> > Does this sound right to you or have I horribly misinterpreted the
>> > point of these clock patches?
>>
>> Mike,
>>
>> Thanks for your comments. If I have understood the coordinated clock
>> as described above, I believe this patch series also attempts to do
>> almost the same thing. The advantage of using coordinated clock over
>> the approach in this series is that each platform need not define a
>> new clock type.
>>
>> In this patch series, for all exynos SoC's, a new cpu clock type was
>> introduced which is reusable for multi-cluster exynos SoCs as well.
>> The new clock type is part of the clock driver and all drivers can use
>> standard clock API to access this clock type instance.
>>
>> So probably, all the logic for the new cpu_clk clock type introduced
>> in this patch would go into the vendor_supplied_magic() callback. So
>> it sounds like the coordinated clock approach would be helpful. Is
>> this something that you are already working on?
>>
>> Thanks,
>> Thomas.
>>
>> >
>> > Thanks,
>> > Mike
>> >
>> >>
>> >> Cc: Tomasz Figa <t.figa@samsung.com>
>> >> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> >> ---
>> >> drivers/clk/samsung/clk-exynos4.c | 25
>> >> +++++++++---------------- drivers/clk/samsung/clk-exynos5250.c
>> >> | 12 ++++++------ include/dt-bindings/clock/exynos5250.h | 1 +
>> >> 3 files changed, 16 insertions(+), 22 deletions(-)
>> >>
>> >> diff --git a/drivers/clk/samsung/clk-exynos4.c
>> >> b/drivers/clk/samsung/clk-exynos4.c index b4f9672..7e3bb16c 100644
>> >> --- a/drivers/clk/samsung/clk-exynos4.c
>> >> +++ b/drivers/clk/samsung/clk-exynos4.c
>> >> @@ -471,7 +471,6 @@ static struct samsung_mux_clock
>> >> exynos4210_mux_clks[] __initdata = { MUX(0, "mout_fimd1",
>> >> group1_p4210, E4210_SRC_LCD1, 0, 4), MUX(0, "mout_mipi1",
>> >> group1_p4210, E4210_SRC_LCD1, 12, 4), MUX(CLK_SCLK_MPLL,
>> >> "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
>> >> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU,
>> >> 16, 1), MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0,
>> >> 8, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0,
>> >> 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
>> >> @@ -530,7 +529,6 @@ static struct samsung_mux_clock
>> >> exynos4x12_mux_clks[] __initdata = { MUX(0, "mout_jpeg",
>> >> mout_jpeg_p, E4X12_SRC_CAM1, 8, 1), MUX(CLK_SCLK_MPLL,
>> >> "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1), MUX(CLK_SCLK_VPLL,
>> >> "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
>> >> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU,
>> >> 16, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM,
>> >> 0, 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4,
>> >> 4), MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
>> >> @@ -572,8 +570,6 @@ static struct samsung_mux_clock
>> >> exynos4x12_mux_clks[] __initdata = {
>> >>
>> >> /* list of divider clocks supported in all exynos4 soc's */
>> >> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
>> >> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
>> >> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
>> >> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
>> >> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
>> >> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
>> >> @@ -619,8 +615,8 @@ static struct samsung_div_clock
>> >> exynos4_div_clks[] __initdata = { DIV(0, "div_spi_pre2",
>> >> "div_spi2", DIV_PERIL2, 8, 8), DIV(0, "div_audio1", "mout_audio1",
>> >> DIV_PERIL4, 0, 4), DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4,
>> >> 16, 4),
>> >> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
>> >> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24,
>> >> 3),
>> >> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0,
>> >> 24, 3,
>> >> + CLK_GET_RATE_NOCACHE, 0),
>> >> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
>> >> CLK_SET_RATE_PARENT, 0),
>> >> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
>> >> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock
>> >> exynos4x12_gate_clks[] __initdata = { 0),
>> >> };
>> >>
>> >> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
>> >> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
>> >> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
>> >> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
>> >> -};
>> >> -
>> >> static struct samsung_clock_alias exynos4210_aliases[] __initdata
>> >> = { ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
>> >> };
>> >> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct
>> >> device_node *np, ARRAY_SIZE(exynos4210_gate_clks));
>> >> samsung_clk_register_alias(exynos4210_aliases,
>> >> ARRAY_SIZE(exynos4210_aliases));
>> >> + exynos_register_arm_clock(CLK_ARM_CLK,
>> >> mout_core_p4210,
>> >> + ARRAY_SIZE(mout_core_p4210), reg_base, np,
>> >> NULL,
>> >> + &samsung_clk_lock);
>> >> } else {
>> >> samsung_clk_register_mux(exynos4x12_mux_clks,
>> >> ARRAY_SIZE(exynos4x12_mux_clks));
>> >> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct
>> >> device_node *np, ARRAY_SIZE(exynos4x12_gate_clks));
>> >> samsung_clk_register_alias(exynos4x12_aliases,
>> >> ARRAY_SIZE(exynos4x12_aliases));
>> >> + exynos_register_arm_clock(CLK_ARM_CLK,
>> >> mout_core_p4x12,
>> >> + ARRAY_SIZE(mout_core_p4x12), reg_base, np,
>> >> NULL,
>> >> + &samsung_clk_lock);
>> >> }
>> >>
>> >> - samsung_clk_register_alias(exynos4_aliases,
>> >> - ARRAY_SIZE(exynos4_aliases));
>> >> -
>> >> exynos4_clk_sleep_init();
>> >>
>> >> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
>> >> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct
>> >> device_node *np, exynos4_soc == EXYNOS4210 ? "Exynos4210" :
>> >> "Exynos4x12", _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
>> >> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
>> >> - _get_rate("arm_clk"));
>> >> + _get_rate("armclk"));
>> >> }
>> >>
>> >>
>> >> diff --git a/drivers/clk/samsung/clk-exynos5250.c
>> >> b/drivers/clk/samsung/clk-exynos5250.c index e7ee442..3fe1ca0
>> >> 100644 --- a/drivers/clk/samsung/clk-exynos5250.c
>> >> +++ b/drivers/clk/samsung/clk-exynos5250.c
>> >> @@ -260,8 +260,6 @@ static struct samsung_mux_clock
>> >> exynos5250_mux_clks[] __initdata = { */
>> >> MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
>> >> CLK_SET_RATE_PARENT, 0,
>> >> "mout_apll"),
>> >> - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1,
>> >> "mout_cpu"), -
>> >> /*
>> >> * CMU_CORE
>> >> */
>> >> @@ -339,9 +337,8 @@ static struct samsung_div_clock
>> >> exynos5250_div_clks[] __initdata = { /*
>> >> * CMU_CPU
>> >> */
>> >> - DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
>> >> - DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
>> >> - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
>> >> + DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
>> >> + CLK_GET_RATE_NOCACHE, 0),
>> >>
>> >> /*
>> >> * CMU_TOP
>> >> @@ -721,10 +718,13 @@ static void __init
>> >> exynos5250_clk_init(struct device_node *np)
>> >> ARRAY_SIZE(exynos5250_div_clks));
>> >> samsung_clk_register_gate(exynos5250_gate_clks,
>> >> ARRAY_SIZE(exynos5250_gate_clks));
>> >> + exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
>> >> + ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
>> >> + &samsung_clk_lock);
>> >>
>> >> exynos5250_clk_sleep_init();
>> >>
>> >> pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
>> >> - _get_rate("div_arm2"));
>> >> + _get_rate("armclk"));
>> >> }
>> >> CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock",
>> >> exynos5250_clk_init); diff --git
>> >> a/include/dt-bindings/clock/exynos5250.h
>> >> b/include/dt-bindings/clock/exynos5250.h index 922f2dc..59a10fb
>> >> 100644 --- a/include/dt-bindings/clock/exynos5250.h +++
>> >> b/include/dt-bindings/clock/exynos5250.h @@ -21,6 +21,7 @@
>> >> #define CLK_FOUT_CPLL 6
>> >> #define CLK_FOUT_EPLL 7
>> >> #define CLK_FOUT_VPLL 8
>> >> +#define CLK_ARM_CLK 12
>> >>
>> >> /* gate for special clocks (sclk) */
>> >> #define CLK_SCLK_CAM_BAYER 128
>> >> --
>> >> 1.7.4.4
>> >>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
>
>
> --
> Best regards,
>
> Lukasz Majewski
>
> Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-14 1:11 ` [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks Thomas Abraham
@ 2014-05-15 18:18 ` Doug Anderson
2014-05-15 19:17 ` Heiko Stübner
2014-05-16 17:17 ` Tomasz Figa
1 sibling, 1 reply; 58+ messages in thread
From: Doug Anderson @ 2014-05-15 18:18 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq, linux-arm-kernel@lists.infradead.org, Mike Turquette,
Shawn Guo, devicetree@vger.kernel.org, Rafael J. Wysocki,
linux-samsung-soc, Kukjin Kim, Tomasz Figa, l.majewski,
Viresh Kumar, Heiko Stübner, Thomas P Abraham
Thomas,
On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com> wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
> +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data *ndata,
> + struct exynos_cpuclk *armclk, void __iomem *base)
> +{
> + struct exynos4210_armclk_data *armclk_data = armclk->data;
> + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
> + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
> + unsigned long cur_armclk_rate, timeout;
> + unsigned long flags;
> +
> + /* find out the divider values to use for clock data */
> + while (armclk_data->prate != ndata->new_rate) {
> + if (armclk_data->prate == 0)
> + return -EINVAL;
> + armclk_data++;
> + }
> +
> + div0 = armclk_data->div0;
> + div1 = armclk_data->div1;
> + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
> + div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
> + div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
> + }
> +
> + /*
> + * if the new and old parent clock speed is less than the clock speed
> + * of the alternate parent, then it should be ensured that at no point
> + * the armclk speed is more than the old_prate until the dividers are
> + * set.
> + */
> + tdiv0 = readl(base + DIV_CPU0);
> + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
> + EXYNOS4210_ARM_DIV2(tdiv0);
> + if (alt_prate > cur_armclk_rate) {
> + alt_div = _calc_div(alt_prate, cur_armclk_rate);
> + _exynos4210_set_armclk_div(base, alt_div);
> + div0 |= alt_div;
Don't you need to up the voltage here, too? ...I haven't reviewed
this whole patch (so perhaps it's elsewhere in the patch or in the
series), but I stumbled upon this while trying to solve a different
problem and figured I'd check...
-Doug
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-15 18:18 ` Doug Anderson
@ 2014-05-15 19:17 ` Heiko Stübner
2014-05-15 19:36 ` Doug Anderson
0 siblings, 1 reply; 58+ messages in thread
From: Heiko Stübner @ 2014-05-15 19:17 UTC (permalink / raw)
To: Doug Anderson
Cc: Thomas Abraham, cpufreq, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
l.majewski, Viresh Kumar, Thomas P Abraham
Am Donnerstag, 15. Mai 2014, 11:18:44 schrieb Doug Anderson:
> Thomas,
>
> On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com> wrote:
> > From: Thomas Abraham <thomas.ab@samsung.com>
> > +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data
> > *ndata, + struct exynos_cpuclk *armclk, void
> > __iomem *base) +{
> > + struct exynos4210_armclk_data *armclk_data = armclk->data;
> > + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
> > + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
> > + unsigned long cur_armclk_rate, timeout;
> > + unsigned long flags;
> > +
> > + /* find out the divider values to use for clock data */
> > + while (armclk_data->prate != ndata->new_rate) {
> > + if (armclk_data->prate == 0)
> > + return -EINVAL;
> > + armclk_data++;
> > + }
> > +
> > + div0 = armclk_data->div0;
> > + div1 = armclk_data->div1;
> > + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
> > + div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
> > + div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
> > + }
> > +
> > + /*
> > + * if the new and old parent clock speed is less than the clock
> > speed + * of the alternate parent, then it should be ensured that
> > at no point + * the armclk speed is more than the old_prate until
> > the dividers are + * set.
> > + */
> > + tdiv0 = readl(base + DIV_CPU0);
> > + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
> > + EXYNOS4210_ARM_DIV2(tdiv0);
> > + if (alt_prate > cur_armclk_rate) {
> > + alt_div = _calc_div(alt_prate, cur_armclk_rate);
> > + _exynos4210_set_armclk_div(base, alt_div);
> > + div0 |= alt_div;
>
> Don't you need to up the voltage here, too? ...I haven't reviewed
> this whole patch (so perhaps it's elsewhere in the patch or in the
> series), but I stumbled upon this while trying to solve a different
> problem and figured I'd check...
setting the voltage should be done by the cpufreq driver like cpufreq-cpu0 -
whose usage this series intents to allow.
As I've hijacked Thomas' concept for my current rockchip clock work, I've
already seen this working nicely :-) .
Heiko
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-15 19:17 ` Heiko Stübner
@ 2014-05-15 19:36 ` Doug Anderson
2014-05-15 20:12 ` Heiko Stübner
0 siblings, 1 reply; 58+ messages in thread
From: Doug Anderson @ 2014-05-15 19:36 UTC (permalink / raw)
To: Heiko Stübner
Cc: Thomas Abraham, cpufreq, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
l.majewski, Viresh Kumar, Thomas P Abraham
Heiko,
On Thu, May 15, 2014 at 12:17 PM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Donnerstag, 15. Mai 2014, 11:18:44 schrieb Doug Anderson:
>> Thomas,
>>
>> On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com> wrote:
>> > From: Thomas Abraham <thomas.ab@samsung.com>
>> > +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data
>> > *ndata, + struct exynos_cpuclk *armclk, void
>> > __iomem *base) +{
>> > + struct exynos4210_armclk_data *armclk_data = armclk->data;
>> > + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
>> > + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
>> > + unsigned long cur_armclk_rate, timeout;
>> > + unsigned long flags;
>> > +
>> > + /* find out the divider values to use for clock data */
>> > + while (armclk_data->prate != ndata->new_rate) {
>> > + if (armclk_data->prate == 0)
>> > + return -EINVAL;
>> > + armclk_data++;
>> > + }
>> > +
>> > + div0 = armclk_data->div0;
>> > + div1 = armclk_data->div1;
>> > + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
>> > + div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
>> > + div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
>> > + }
>> > +
>> > + /*
>> > + * if the new and old parent clock speed is less than the clock
>> > speed + * of the alternate parent, then it should be ensured that
>> > at no point + * the armclk speed is more than the old_prate until
>> > the dividers are + * set.
>> > + */
>> > + tdiv0 = readl(base + DIV_CPU0);
>> > + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
>> > + EXYNOS4210_ARM_DIV2(tdiv0);
>> > + if (alt_prate > cur_armclk_rate) {
>> > + alt_div = _calc_div(alt_prate, cur_armclk_rate);
>> > + _exynos4210_set_armclk_div(base, alt_div);
>> > + div0 |= alt_div;
>>
>> Don't you need to up the voltage here, too? ...I haven't reviewed
>> this whole patch (so perhaps it's elsewhere in the patch or in the
>> series), but I stumbled upon this while trying to solve a different
>> problem and figured I'd check...
>
> setting the voltage should be done by the cpufreq driver like cpufreq-cpu0 -
> whose usage this series intents to allow.
>
> As I've hijacked Thomas' concept for my current rockchip clock work, I've
> already seen this working nicely :-) .
I guess I should have been more clear. I was talking more
specifically about upping the voltage as part of the mux switch in the
case that alt_prate > cur_armclk_rate.
...if you're switching from 200MHz to 300MHz and the alt_prate is
800MHz, you need to account for that fact. The code here accounts for
the fact in setting the "armclk_div", but (I don't think) it accounts
for the fact that 800MHz will need a higher voltage.
As per a separate discussion, a clean solution might be to move the
mux switching to the core of CPU_FREQ. That would have the side
effect of also making it very easy to send notifications.
-Doug
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-15 19:36 ` Doug Anderson
@ 2014-05-15 20:12 ` Heiko Stübner
2014-05-15 20:26 ` Doug Anderson
0 siblings, 1 reply; 58+ messages in thread
From: Heiko Stübner @ 2014-05-15 20:12 UTC (permalink / raw)
To: Doug Anderson
Cc: Thomas Abraham, cpufreq, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
l.majewski, Viresh Kumar, Thomas P Abraham
Hi Doug,
Am Donnerstag, 15. Mai 2014, 12:36:45 schrieb Doug Anderson:
> On Thu, May 15, 2014 at 12:17 PM, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Donnerstag, 15. Mai 2014, 11:18:44 schrieb Doug Anderson:
> >> Thomas,
> >>
> >> On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com>
wrote:
> >> > From: Thomas Abraham <thomas.ab@samsung.com>
> >> > +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data
> >> > *ndata, + struct exynos_cpuclk *armclk, void
> >> > __iomem *base) +{
> >> > + struct exynos4210_armclk_data *armclk_data = armclk->data;
> >> > + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
> >> > + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
> >> > + unsigned long cur_armclk_rate, timeout;
> >> > + unsigned long flags;
> >> > +
> >> > + /* find out the divider values to use for clock data */
> >> > + while (armclk_data->prate != ndata->new_rate) {
> >> > + if (armclk_data->prate == 0)
> >> > + return -EINVAL;
> >> > + armclk_data++;
> >> > + }
> >> > +
> >> > + div0 = armclk_data->div0;
> >> > + div1 = armclk_data->div1;
> >> > + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
> >> > + div1 = readl(base + DIV_CPU1) &
> >> > EXYNOS4210_DIV1_HPM_MASK;
> >> > + div1 |= ((armclk_data->div1) &
> >> > ~EXYNOS4210_DIV1_HPM_MASK);
> >> > + }
> >> > +
> >> > + /*
> >> > + * if the new and old parent clock speed is less than the clock
> >> > speed + * of the alternate parent, then it should be ensured
> >> > that
> >> > at no point + * the armclk speed is more than the old_prate
> >> > until
> >> > the dividers are + * set.
> >> > + */
> >> > + tdiv0 = readl(base + DIV_CPU0);
> >> > + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0)
> >> > /
> >> > + EXYNOS4210_ARM_DIV2(tdiv0);
> >> > + if (alt_prate > cur_armclk_rate) {
> >> > + alt_div = _calc_div(alt_prate, cur_armclk_rate);
> >> > + _exynos4210_set_armclk_div(base, alt_div);
> >> > + div0 |= alt_div;
> >>
> >> Don't you need to up the voltage here, too? ...I haven't reviewed
> >> this whole patch (so perhaps it's elsewhere in the patch or in the
> >> series), but I stumbled upon this while trying to solve a different
> >> problem and figured I'd check...
> >
> > setting the voltage should be done by the cpufreq driver like cpufreq-cpu0
> > - whose usage this series intents to allow.
> >
> > As I've hijacked Thomas' concept for my current rockchip clock work, I've
> > already seen this working nicely :-) .
>
> I guess I should have been more clear. I was talking more
> specifically about upping the voltage as part of the mux switch in the
> case that alt_prate > cur_armclk_rate.
from earlier discussions I remember Thomas and me talked about setting a
divider to make sure that alt_prate <= cur_armclk_rate, so the voltage can
stay at its current level. I haven't looked deeply into this revision, but the
last one did exactly this.
> ...if you're switching from 200MHz to 300MHz and the alt_prate is
> 800MHz, you need to account for that fact. The code here accounts for
> the fact in setting the "armclk_div", but (I don't think) it accounts
> for the fact that 800MHz will need a higher voltage.
>
> As per a separate discussion, a clean solution might be to move the
> mux switching to the core of CPU_FREQ. That would have the side
> effect of also making it very easy to send notifications.
I'll just wait until you all decide what the best solution is :-), but
personally I like the concept of keeping the clock logic inside the clock
driver, especially as this is not limited to setting the mux but also adapting
tightly bound child clocks and this all may not fit into a generic
implementation of a cpufreq driver.
And this is also working really nice on my rockchip platform.
Heiko
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-15 20:12 ` Heiko Stübner
@ 2014-05-15 20:26 ` Doug Anderson
2014-05-16 4:55 ` Thomas Abraham
0 siblings, 1 reply; 58+ messages in thread
From: Doug Anderson @ 2014-05-15 20:26 UTC (permalink / raw)
To: Heiko Stübner
Cc: Thomas Abraham, cpufreq, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
Rafael J. Wysocki, linux-samsung-soc, Kukjin Kim, Tomasz Figa,
l.majewski, Viresh Kumar, Thomas P Abraham
Heiko,
On Thu, May 15, 2014 at 1:12 PM, Heiko Stübner <heiko@sntech.de> wrote:
> Hi Doug,
>
> Am Donnerstag, 15. Mai 2014, 12:36:45 schrieb Doug Anderson:
>> On Thu, May 15, 2014 at 12:17 PM, Heiko Stübner <heiko@sntech.de> wrote:
>> > Am Donnerstag, 15. Mai 2014, 11:18:44 schrieb Doug Anderson:
>> >> Thomas,
>> >>
>> >> On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com>
> wrote:
>> >> > From: Thomas Abraham <thomas.ab@samsung.com>
>> >> > +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data
>> >> > *ndata, + struct exynos_cpuclk *armclk, void
>> >> > __iomem *base) +{
>> >> > + struct exynos4210_armclk_data *armclk_data = armclk->data;
>> >> > + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
>> >> > + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
>> >> > + unsigned long cur_armclk_rate, timeout;
>> >> > + unsigned long flags;
>> >> > +
>> >> > + /* find out the divider values to use for clock data */
>> >> > + while (armclk_data->prate != ndata->new_rate) {
>> >> > + if (armclk_data->prate == 0)
>> >> > + return -EINVAL;
>> >> > + armclk_data++;
>> >> > + }
>> >> > +
>> >> > + div0 = armclk_data->div0;
>> >> > + div1 = armclk_data->div1;
>> >> > + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
>> >> > + div1 = readl(base + DIV_CPU1) &
>> >> > EXYNOS4210_DIV1_HPM_MASK;
>> >> > + div1 |= ((armclk_data->div1) &
>> >> > ~EXYNOS4210_DIV1_HPM_MASK);
>> >> > + }
>> >> > +
>> >> > + /*
>> >> > + * if the new and old parent clock speed is less than the clock
>> >> > speed + * of the alternate parent, then it should be ensured
>> >> > that
>> >> > at no point + * the armclk speed is more than the old_prate
>> >> > until
>> >> > the dividers are + * set.
>> >> > + */
>> >> > + tdiv0 = readl(base + DIV_CPU0);
>> >> > + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0)
>> >> > /
>> >> > + EXYNOS4210_ARM_DIV2(tdiv0);
>> >> > + if (alt_prate > cur_armclk_rate) {
>> >> > + alt_div = _calc_div(alt_prate, cur_armclk_rate);
>> >> > + _exynos4210_set_armclk_div(base, alt_div);
>> >> > + div0 |= alt_div;
>> >>
>> >> Don't you need to up the voltage here, too? ...I haven't reviewed
>> >> this whole patch (so perhaps it's elsewhere in the patch or in the
>> >> series), but I stumbled upon this while trying to solve a different
>> >> problem and figured I'd check...
>> >
>> > setting the voltage should be done by the cpufreq driver like cpufreq-cpu0
>> > - whose usage this series intents to allow.
>> >
>> > As I've hijacked Thomas' concept for my current rockchip clock work, I've
>> > already seen this working nicely :-) .
>>
>> I guess I should have been more clear. I was talking more
>> specifically about upping the voltage as part of the mux switch in the
>> case that alt_prate > cur_armclk_rate.
>
> from earlier discussions I remember Thomas and me talked about setting a
> divider to make sure that alt_prate <= cur_armclk_rate, so the voltage can
> stay at its current level. I haven't looked deeply into this revision, but the
> last one did exactly this.
Ah-ha, that's a reasonable solution to this problem. I was familiar
with the old code and know that it used to set the CPUD ratio here, so
I assumed that was what Thomas's code did. ...but you're right, his
code is setting the divider here. I didn't double-check all of his
code / calculations, but he's certainly tweaking the right bits.
Nice!
>> ...if you're switching from 200MHz to 300MHz and the alt_prate is
>> 800MHz, you need to account for that fact. The code here accounts for
>> the fact in setting the "armclk_div", but (I don't think) it accounts
>> for the fact that 800MHz will need a higher voltage.
>>
>> As per a separate discussion, a clean solution might be to move the
>> mux switching to the core of CPU_FREQ. That would have the side
>> effect of also making it very easy to send notifications.
>
> I'll just wait until you all decide what the best solution is :-), but
> personally I like the concept of keeping the clock logic inside the clock
> driver, especially as this is not limited to setting the mux but also adapting
> tightly bound child clocks and this all may not fit into a generic
> implementation of a cpufreq driver.
Yup, I didn't think of the solution you guys came up with. Your
solution handles things nicely.
Thanks!
-Doug
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-15 20:26 ` Doug Anderson
@ 2014-05-16 4:55 ` Thomas Abraham
0 siblings, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-16 4:55 UTC (permalink / raw)
To: Doug Anderson
Cc: Heiko Stübner, cpufreq@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mike Turquette, Shawn Guo,
devicetree@vger.kernel.org, Rafael J. Wysocki, linux-samsung-soc,
Kukjin Kim, Tomasz Figa, Lukasz Majewski, Viresh Kumar
On Fri, May 16, 2014 at 1:56 AM, Doug Anderson <dianders@chromium.org> wrote:
> Heiko,
>
> On Thu, May 15, 2014 at 1:12 PM, Heiko Stübner <heiko@sntech.de> wrote:
>> Hi Doug,
>>
>> Am Donnerstag, 15. Mai 2014, 12:36:45 schrieb Doug Anderson:
>>> On Thu, May 15, 2014 at 12:17 PM, Heiko Stübner <heiko@sntech.de> wrote:
>>> > Am Donnerstag, 15. Mai 2014, 11:18:44 schrieb Doug Anderson:
>>> >> Thomas,
>>> >>
>>> >> On Tue, May 13, 2014 at 6:11 PM, Thomas Abraham <ta.omasab@gmail.com>
>> wrote:
>>> >> > From: Thomas Abraham <thomas.ab@samsung.com>
>>> >> > +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data
>>> >> > *ndata, + struct exynos_cpuclk *armclk, void
>>> >> > __iomem *base) +{
>>> >> > + struct exynos4210_armclk_data *armclk_data = armclk->data;
>>> >> > + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
>>> >> > + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
>>> >> > + unsigned long cur_armclk_rate, timeout;
>>> >> > + unsigned long flags;
>>> >> > +
>>> >> > + /* find out the divider values to use for clock data */
>>> >> > + while (armclk_data->prate != ndata->new_rate) {
>>> >> > + if (armclk_data->prate == 0)
>>> >> > + return -EINVAL;
>>> >> > + armclk_data++;
>>> >> > + }
>>> >> > +
>>> >> > + div0 = armclk_data->div0;
>>> >> > + div1 = armclk_data->div1;
>>> >> > + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
>>> >> > + div1 = readl(base + DIV_CPU1) &
>>> >> > EXYNOS4210_DIV1_HPM_MASK;
>>> >> > + div1 |= ((armclk_data->div1) &
>>> >> > ~EXYNOS4210_DIV1_HPM_MASK);
>>> >> > + }
>>> >> > +
>>> >> > + /*
>>> >> > + * if the new and old parent clock speed is less than the clock
>>> >> > speed + * of the alternate parent, then it should be ensured
>>> >> > that
>>> >> > at no point + * the armclk speed is more than the old_prate
>>> >> > until
>>> >> > the dividers are + * set.
>>> >> > + */
>>> >> > + tdiv0 = readl(base + DIV_CPU0);
>>> >> > + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0)
>>> >> > /
>>> >> > + EXYNOS4210_ARM_DIV2(tdiv0);
>>> >> > + if (alt_prate > cur_armclk_rate) {
>>> >> > + alt_div = _calc_div(alt_prate, cur_armclk_rate);
>>> >> > + _exynos4210_set_armclk_div(base, alt_div);
>>> >> > + div0 |= alt_div;
>>> >>
>>> >> Don't you need to up the voltage here, too? ...I haven't reviewed
>>> >> this whole patch (so perhaps it's elsewhere in the patch or in the
>>> >> series), but I stumbled upon this while trying to solve a different
>>> >> problem and figured I'd check...
>>> >
>>> > setting the voltage should be done by the cpufreq driver like cpufreq-cpu0
>>> > - whose usage this series intents to allow.
>>> >
>>> > As I've hijacked Thomas' concept for my current rockchip clock work, I've
>>> > already seen this working nicely :-) .
>>>
>>> I guess I should have been more clear. I was talking more
>>> specifically about upping the voltage as part of the mux switch in the
>>> case that alt_prate > cur_armclk_rate.
>>
>> from earlier discussions I remember Thomas and me talked about setting a
>> divider to make sure that alt_prate <= cur_armclk_rate, so the voltage can
>> stay at its current level. I haven't looked deeply into this revision, but the
>> last one did exactly this.
>
> Ah-ha, that's a reasonable solution to this problem. I was familiar
> with the old code and know that it used to set the CPUD ratio here, so
> I assumed that was what Thomas's code did. ...but you're right, his
> code is setting the divider here. I didn't double-check all of his
> code / calculations, but he's certainly tweaking the right bits.
>
> Nice!
>
>
>>> ...if you're switching from 200MHz to 300MHz and the alt_prate is
>>> 800MHz, you need to account for that fact. The code here accounts for
>>> the fact in setting the "armclk_div", but (I don't think) it accounts
>>> for the fact that 800MHz will need a higher voltage.
>>>
>>> As per a separate discussion, a clean solution might be to move the
>>> mux switching to the core of CPU_FREQ. That would have the side
>>> effect of also making it very easy to send notifications.
>>
>> I'll just wait until you all decide what the best solution is :-), but
>> personally I like the concept of keeping the clock logic inside the clock
>> driver, especially as this is not limited to setting the mux but also adapting
>> tightly bound child clocks and this all may not fit into a generic
>> implementation of a cpufreq driver.
+1. I also prefer to go with this approach.
>
> Yup, I didn't think of the solution you guys came up with. Your
> solution handles things nicely.
>
> Thanks!
>
> -Doug
Doug,
Heiko had suggested to use the divider to keep the armclk within
limits during the frequency transition. This helped to avoid the
corresponding voltage scaling step which greatly simplified the
frequency scaling for exynos. We definitely plan to use the same
suggestion on other exynos platforms as well.
Thanks,
Thomas.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-14 21:37 ` Mike Turquette
2014-05-15 7:48 ` Thomas Abraham
@ 2014-05-16 5:14 ` Thomas Abraham
1 sibling, 0 replies; 58+ messages in thread
From: Thomas Abraham @ 2014-05-16 5:14 UTC (permalink / raw)
To: Mike Turquette
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Shawn Guo, devicetree@vger.kernel.org, rjw@rjwysocki.net,
linux-samsung-soc@vger.kernel.org, Kukjin Kim, Tomasz Figa,
Lukasz Majewski, Viresh Kumar, Heiko Stübner
On Thu, May 15, 2014 at 3:07 AM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Thomas Abraham (2014-05-13 18:11:13)
>> From: Thomas Abraham <thomas.ab@samsung.com>
>>
>> With the addition of the new Samsung specific cpu-clock type, the
>> arm clock can be represented as a cpu-clock type and the independent
>> clock blocks that made up the arm clock can be removed.
>
> <rant>
>
> I am not a fan of this type of "clock hiding". Certainly the design of
> the CCF allows for a clock provider to obfuscate it's internals; there
> was never a requirement that every clock node be exposed to Linux as a
> struct clk. A truly obfuscated system could only expose leaf clocks that
> are consumed by Linux device drivers, and never expose any of the
> intermediary clocks in between the input clock signal (if it exists) and
> the leaf nodes.
>
> However I feel that this patch is more of a workaround to the fact that
> the clock framework today does not make DVFS transitions (or
> coordinated, multi-clock rate change transitions) easy to control. The
> generic "walk up the tree" algorithm might give you the right rate, but
> perhaps using a non-validated combination of PLL frequency and
> adjustable-rate dividers, or a combination that his higher jitter or is
> more likely to unlock at higher temperatures, etc.
>
> Back in the pre-CCF days lots of folks implemented this with "virtual"
> clock nodes that simply called "clk_set_rate" or whatever on the
> affected clocks, or even worse just banged a bunch of registers.
>
> The cbus clock series for Tegra is also looks a little like this.
>
> </rant>
>
> Thomas,
>
> Would a coordinated clock rate change method solve this problem for you
> in place of the cpu-clock provider type? A poorly conceived call graph
> for this might look something like:
>
> clk_set_rate(div_arm2, 1000000);
> -> if (div_arm2->coordinated == true)
> clk_coordinate_rates(div_arm2, 1000000);
> -> clk->ops->coordinate(div_arm2->hw, 1000000);
> -> vendor_supplied_magic()
>
> The vendor_supplied_magic() would be a callback that essentially calls
> clk_set_rate() on all of the affected (coordinated) clocks. In your case
> that looks like mout_core, div_core, div_core2, arm_clk and sclk_apll
> for Exynos4.
>
> The trick is that calling clk_set_rate() from any driver would initiate
> this coordinated rate change, and then the exynos clock driver would set
> up the coordinated clocks itself. No new API is introduced to drivers
> (since it still uses clk_set_rate) and now a new clock provider doesn't
> have to be invented every time we have a couple of clocks involved in a
> DVFS transition.
>
> Does this sound right to you or have I horribly misinterpreted the point
> of these clock patches?
>
> Thanks,
> Mike
Hi Mike,
I have been testing this patch series on three exynos platforms for
about five days now and do not see any issues. There are some review
comments which I need to incorporate. So before that, I wanted to
check with you about the grouping of clocks approach in this patch
series. Is this approach something that we could use until the changes
for coordinated clocks are in place? This patch series also helps with
multi-platform support for exynos as well.
Tomasz, I have addressed most of your comments from v3. If you could
have a look at the v4 series as well, it would be helpful in making
this better.
Thanks,
Thomas.
>
>>
>> Cc: Tomasz Figa <t.figa@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> ---
>> drivers/clk/samsung/clk-exynos4.c | 25 +++++++++----------------
>> drivers/clk/samsung/clk-exynos5250.c | 12 ++++++------
>> include/dt-bindings/clock/exynos5250.h | 1 +
>> 3 files changed, 16 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
>> index b4f9672..7e3bb16c 100644
>> --- a/drivers/clk/samsung/clk-exynos4.c
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -471,7 +471,6 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
>> MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
>> MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
>> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
>> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
>> MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
>> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
>> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
>> @@ -530,7 +529,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>> MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
>> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
>> MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
>> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
>> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
>> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
>> MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
>> @@ -572,8 +570,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>>
>> /* list of divider clocks supported in all exynos4 soc's */
>> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
>> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
>> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
>> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
>> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
>> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
>> @@ -619,8 +615,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
>> DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
>> DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
>> DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
>> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
>> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
>> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
>> + CLK_GET_RATE_NOCACHE, 0),
>> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
>> CLK_SET_RATE_PARENT, 0),
>> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
>> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
>> 0),
>> };
>>
>> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
>> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
>> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
>> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
>> -};
>> -
>> static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
>> ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
>> };
>> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct device_node *np,
>> ARRAY_SIZE(exynos4210_gate_clks));
>> samsung_clk_register_alias(exynos4210_aliases,
>> ARRAY_SIZE(exynos4210_aliases));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4210,
>> + ARRAY_SIZE(mout_core_p4210), reg_base, np, NULL,
>> + &samsung_clk_lock);
>> } else {
>> samsung_clk_register_mux(exynos4x12_mux_clks,
>> ARRAY_SIZE(exynos4x12_mux_clks));
>> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct device_node *np,
>> ARRAY_SIZE(exynos4x12_gate_clks));
>> samsung_clk_register_alias(exynos4x12_aliases,
>> ARRAY_SIZE(exynos4x12_aliases));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4x12,
>> + ARRAY_SIZE(mout_core_p4x12), reg_base, np, NULL,
>> + &samsung_clk_lock);
>> }
>>
>> - samsung_clk_register_alias(exynos4_aliases,
>> - ARRAY_SIZE(exynos4_aliases));
>> -
>> exynos4_clk_sleep_init();
>>
>> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
>> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
>> exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
>> _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
>> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
>> - _get_rate("arm_clk"));
>> + _get_rate("armclk"));
>> }
>>
>>
>> diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
>> index e7ee442..3fe1ca0 100644
>> --- a/drivers/clk/samsung/clk-exynos5250.c
>> +++ b/drivers/clk/samsung/clk-exynos5250.c
>> @@ -260,8 +260,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
>> */
>> MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
>> CLK_SET_RATE_PARENT, 0, "mout_apll"),
>> - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
>> -
>> /*
>> * CMU_CORE
>> */
>> @@ -339,9 +337,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
>> /*
>> * CMU_CPU
>> */
>> - DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
>> - DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
>> - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
>> + DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
>> + CLK_GET_RATE_NOCACHE, 0),
>>
>> /*
>> * CMU_TOP
>> @@ -721,10 +718,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
>> ARRAY_SIZE(exynos5250_div_clks));
>> samsung_clk_register_gate(exynos5250_gate_clks,
>> ARRAY_SIZE(exynos5250_gate_clks));
>> + exynos_register_arm_clock(CLK_ARM_CLK, mout_cpu_p,
>> + ARRAY_SIZE(mout_cpu_p), reg_base, np, NULL,
>> + &samsung_clk_lock);
>>
>> exynos5250_clk_sleep_init();
>>
>> pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
>> - _get_rate("div_arm2"));
>> + _get_rate("armclk"));
>> }
>> CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
>> diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h
>> index 922f2dc..59a10fb 100644
>> --- a/include/dt-bindings/clock/exynos5250.h
>> +++ b/include/dt-bindings/clock/exynos5250.h
>> @@ -21,6 +21,7 @@
>> #define CLK_FOUT_CPLL 6
>> #define CLK_FOUT_EPLL 7
>> #define CLK_FOUT_VPLL 8
>> +#define CLK_ARM_CLK 12
>>
>> /* gate for special clocks (sclk) */
>> #define CLK_SCLK_CAM_BAYER 128
>> --
>> 1.7.4.4
>>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global
2014-05-14 1:11 ` [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global Thomas Abraham
2014-05-14 3:50 ` Viresh Kumar
@ 2014-05-16 12:30 ` Tomasz Figa
1 sibling, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-16 12:30 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, l.majewski, viresh.kumar, heiko, thomas.ab
Hi Thomas,
On 14.05.2014 03:11, Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Access to samsung clock lock is required to support newer samsung specific
> clock types. So change the scope of the samsung clock lock to global. And
> prefix 'samsung_clk_' to the existing name of the lock to prevent name space
> pollution.
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> drivers/clk/samsung/clk.c | 13 ++++++++-----
> drivers/clk/samsung/clk.h | 2 ++
> 2 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> index 91bec3e..c86c28c 100644
> --- a/drivers/clk/samsung/clk.c
> +++ b/drivers/clk/samsung/clk.c
> @@ -14,7 +14,7 @@
> #include <linux/syscore_ops.h>
> #include "clk.h"
>
> -static DEFINE_SPINLOCK(lock);
> +DEFINE_SPINLOCK(samsung_clk_lock);
I'm afraid this series needs to be rebased on top of samsung-clk-next
branch of Samsung clock tree:
git://git.kernel.org/pub/scm/linux/kernel/git/tfiga/samsung-clk.git
You can find there patches adding Samsung clock context struct, which
should be passed to Samsung clock helper functions and which replaces
the global variables above.
So changes introduced by this patch will be no longer necessary, as you
will be able to just pass the context struct to registration function of
your clock type.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-14 1:11 ` [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks Thomas Abraham
2014-05-15 18:18 ` Doug Anderson
@ 2014-05-16 17:17 ` Tomasz Figa
2014-05-23 14:41 ` Thomas Abraham
1 sibling, 1 reply; 58+ messages in thread
From: Tomasz Figa @ 2014-05-16 17:17 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, l.majewski, viresh.kumar, heiko, thomas.ab
Hi Thomas,
On 14.05.2014 03:11, Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> The CPU clock provider supplies the clock to the CPU clock domain. The
> composition and organization of the CPU clock provider could vary among
> Exynos SoCs. A CPU clock provider can be composed of clock mux, dividers
> and gates. This patch defines a new clock type for CPU clock provider and
> adds infrastructure to register the CPU clock providers for Samsung
> platforms.
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> drivers/clk/samsung/Makefile | 2 +-
> drivers/clk/samsung/clk-cpu.c | 458 +++++++++++++++++++++++++++++++++++++++++
> drivers/clk/samsung/clk.h | 5 +
> 3 files changed, 464 insertions(+), 1 deletions(-)
> create mode 100644 drivers/clk/samsung/clk-cpu.c
>
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> index 8eb4799..e2b453f 100644
> --- a/drivers/clk/samsung/Makefile
> +++ b/drivers/clk/samsung/Makefile
> @@ -2,7 +2,7 @@
> # Samsung Clock specific Makefile
> #
>
> -obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
> +obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o
> obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
> obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
> obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
> diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
> new file mode 100644
> index 0000000..6a40862
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-cpu.c
> @@ -0,0 +1,458 @@
> +/*
> + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
> + * Author: Thomas Abraham <thomas.ab@samsung.com>
> + *
> + * 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.
> + *
> + * This file contains the utility functions to register the cpu clocks
> + * for samsung platforms.
s/cpu/CPU/
s/samsung/Samsung/
> +*/
> +
> +#include <linux/errno.h>
> +#include "clk.h"
> +
> +#define SRC_CPU 0x0
> +#define STAT_CPU 0x200
> +#define DIV_CPU0 0x300
> +#define DIV_CPU1 0x304
> +#define DIV_STAT_CPU0 0x400
> +#define DIV_STAT_CPU1 0x404
> +
> +#define MAX_DIV 8
> +
> +#define EXYNOS4210_ARM_DIV1(div) ((div & 0x7) + 1)
> +#define EXYNOS4210_ARM_DIV2(div) (((div >> 28) & 0x7) + 1)
> +
> +#define EXYNOS4210_DIV_CPU0(d5, d4, d3, d2, d1, d0) \
> + ((d5 << 24) | (d4 << 20) | (d3 << 16) | (d2 << 12) | \
> + (d1 << 8) | (d0 << 4))
> +#define EXYNOS4210_DIV_CPU1(d2, d1, d0) \
> + ((d2 << 8) | (d1 << 4) | (d0 << 0))
Macro arguments should be put into parentheses to make sure that whole
argument is subject to further arithmetic operations.
> +
> +#define EXYNOS4210_DIV1_HPM_MASK ((0x7 << 0) | (0x7 << 4))
> +#define EXYNOS4210_MUX_HPM_MASK (1 << 20)
> +
> +/**
> + * struct exynos4210_armclk_data: config data to setup exynos4210 cpu clocks.
> + * @prate: frequency of the parent clock.
> + * @div0: value to be programmed in the div_cpu0 register.
> + * @div1: value to be programmed in the div_cpu1 register.
> + *
> + * This structure holds the divider configuration data for divider clocks
> + * belonging to the CMU_CPU clock domain. The parent frequency at which these
> + * divider values are vaild is specified in @prate.
s/vaild/valid/
> + */
> +struct exynos4210_armclk_data {
> + unsigned long prate;
> + unsigned int div0;
> + unsigned int div1;
> +};
> +
> +/**
> + * struct exynos_cpuclk: information about clock supplied to a CPU core.
> + * @hw: handle between ccf and cpu clock.
s/ccf/CCF/
s/cpu/CPU/
> + * @alt_parent: alternate parent clock to use when switching the speed
> + * of the primary parent clock.
> + * @ctrl_base: base address of the clock controller.
> + * @offset: offset from the ctrl_base address where the cpu clock div/mux
s/cpu/CPU/
> + * registers can be accessed.
> + * @clk_nb: clock notifier registered for changes in clock speed of the
> + * primary parent clock.
> + * @lock: register access lock.
> + * @data: optional data which the acutal instantiation of this clock
> + * can use.
s/acutal/actual/
> + */
> +struct exynos_cpuclk {
> + struct clk_hw hw;
> + struct clk *alt_parent;
> + void __iomem *ctrl_base;
> + unsigned long offset;
> + struct notifier_block clk_nb;
> + spinlock_t *lock;
> + void *data;
> +};
> +
> +#define to_exynos_cpuclk_hw(hw) container_of(hw, struct exynos_cpuclk, hw)
> +#define to_exynos_cpuclk_nb(nb) container_of(nb, struct exynos_cpuclk, clk_nb)
> +
> +/**
> + * struct exynos_cpuclk_soc_data: soc specific data for cpu clocks.
> + * @parser: pointer to a function that can parse SoC specific data.
> + * @ops: clock operations to be used for this clock.
> + * @offset: optional offset from base of clock controller register base, to
> + * be used when accessing clock controller registers related to the
> + * cpu clock.
s/cpu/CPU/
> + * @clk_cb: the clock notifier callback to be called for changes in the
> + * clock rate of the primary parent clock.
> + *
> + * This structure provides SoC specific data for ARM clocks. Based on
> + * the compatible value of the clock controller node, the value of the
> + * fields in this structure can be populated.
> + */
> +struct exynos_cpuclk_soc_data {
> + int (*parser)(struct device_node *, void **);
Here you don't have argument names, but...
> + const struct clk_ops *ops;
> + unsigned int offset;
> + int (*clk_cb)(struct notifier_block *nb, unsigned long evt, void *data);
...here you have. Please keep some consistency.
> +};
> +
> +/* common round rate callback useable for all types of cpu clocks */
s/cpu/CPU/
> +static long exynos_cpuclk_round_rate(struct clk_hw *hw,
> + unsigned long drate, unsigned long *prate)
Hmm, the long return type will overflow with *prate > INT_MAX and
best_div == 1, I wonder why it is defined so in CCF, even though it
shouldn't return error codes...
> +{
> + struct clk *parent = __clk_get_parent(hw->clk);
> + unsigned long max_prate = __clk_round_rate(parent, UINT_MAX);
> + unsigned long t_prate, div = 1, best_div = 1;
> + unsigned long delta, min_delta = UINT_MAX;
By the way, shouldn't this function take into account the list of
available CPU rates and round drate to a less or equal supported one?
Otherwise, in further code you might hit cases where an unsupported rate
is requested, which is against the CCF semantics, if .round_rate()
operation is provided.
> +
> + do {
> + t_prate = __clk_round_rate(parent, drate * div);
> + delta = drate - (t_prate / div);
> + if (delta < min_delta) {
> + *prate = t_prate;
> + best_div = div;
> + min_delta = delta;
> + }
> + if (!delta)
> + break;
> + div++;
> + } while ((drate * div) < max_prate && div <= MAX_DIV);
> +
> + return *prate / best_div;
> +}
> +
> +static unsigned long _calc_div(unsigned long prate, unsigned long drate)
> +{
> + unsigned long div = prate / drate;
> +
> + WARN_ON(div >= MAX_DIV);
> + return (!(prate % drate)) ? div-- : div;
Could you explain what is the purpose of this check and adjustment?
If my assumption that this is essentially DIV_ROUND_UP(prate, drate) - 1
is true then this probably used to obtain a divisor value to get less or
equal rate than drate. Is it right?
> +}
> +
> +/* helper function to register a cpu clock */
> +static int __init exynos_cpuclk_register(unsigned int lookup_id,
> + const char *name, const char **parents,
> + unsigned int num_parents, void __iomem *base,
The num_parents argument doesn't seem to be used in the code. Maybe
instead you should simply replace it and parents arguments with (const
char *parent) and (const char *alt_parent)?
> + const struct exynos_cpuclk_soc_data *soc_data,
> + struct device_node *np, const struct clk_ops *ops,
> + spinlock_t *lock)
> +{
> + struct exynos_cpuclk *cpuclk;
> + struct clk_init_data init;
> + struct clk *clk;
> + int ret;
> +
> + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
> + if (!cpuclk) {
> + pr_err("%s: could not allocate memory for %s clock\n",
> + __func__, name);
> + return -ENOMEM;
> + }
> +
> + init.name = name;
> + init.flags = CLK_SET_RATE_PARENT;
> + init.parent_names = parents;
> + init.num_parents = 1;
> + init.ops = ops;
> +
> + cpuclk->hw.init = &init;
> + cpuclk->ctrl_base = base;
> + cpuclk->lock = lock;
> +
> + ret = soc_data->parser(np, &cpuclk->data);
> + if (ret) {
> + pr_err("%s: error %d in parsing %s clock data",
> + __func__, ret, name);
> + ret = -EINVAL;
> + goto free_cpuclk;
> + }
> + cpuclk->offset = soc_data->offset;
> + init.ops = soc_data->ops;
> +
> + cpuclk->clk_nb.notifier_call = soc_data->clk_cb;
> + if (clk_notifier_register(__clk_lookup(parents[0]), &cpuclk->clk_nb)) {
> + pr_err("%s: failed to register clock notifier for %s\n",
> + __func__, name);
> + goto free_cpuclk_data;
> + }
> +
> + cpuclk->alt_parent = __clk_lookup(parents[1]);
> + if (!cpuclk->alt_parent) {
> + pr_err("%s: could not lookup alternate parent %s\n",
> + __func__, parents[1]);
> + ret = -EINVAL;
> + goto free_cpuclk_data;
Shouldn't it be goto unregister_notifier and the notifier unregistered
there?
> + }
> +
> + clk = clk_register(NULL, &cpuclk->hw);
> + if (IS_ERR(clk)) {
> + pr_err("%s: could not register cpuclk %s\n", __func__, name);
> + ret = PTR_ERR(clk);
> + goto free_cpuclk_data;
Ditto.
> + }
> +
> + samsung_clk_add_lookup(clk, lookup_id);
> + return 0;
> +
> +free_cpuclk_data:
> + kfree(cpuclk->data);
> +free_cpuclk:
> + kfree(cpuclk);
> + return ret;
> +}
> +
> +static void _exynos4210_set_armclk_div(void __iomem *base, unsigned long div)
> +{
> + unsigned long timeout = jiffies + msecs_to_jiffies(10);
> +
> + writel((readl(base + DIV_CPU0) & ~0x7) | div, base + DIV_CPU0);
The 0x7 could be defined as a preprocessor macro. Also for increased
readability, this could be split into separate read, modify and write.
> + while (time_before(jiffies, timeout))
> + if (!readl(base + DIV_STAT_CPU0))
> + return;
> + pr_err("%s: timeout in divider stablization\n", __func__);
> +}
> +
> +static unsigned long exynos4210_armclk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
> + void __iomem *base = armclk->ctrl_base + armclk->offset;
> + unsigned long div0 = readl(base + DIV_CPU0);
> +
> + return parent_rate / EXYNOS4210_ARM_DIV1(div0) /
> + EXYNOS4210_ARM_DIV2(div0);
> +}
> +
> +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data *ndata,
> + struct exynos_cpuclk *armclk, void __iomem *base)
> +{
> + struct exynos4210_armclk_data *armclk_data = armclk->data;
> + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
> + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
> + unsigned long cur_armclk_rate, timeout;
> + unsigned long flags;
> +
> + /* find out the divider values to use for clock data */
> + while (armclk_data->prate != ndata->new_rate) {
I assume this code relies on the assumption that target DIV_CORE and
DIV_CORE2 are always 0 (divide by 1)? Otherwise it should compare
armclk_data->prate with new parent rate, not new target armclk rate,
which would be parent rate divided by DIV_CORE and DIV_CORE2.
> + if (armclk_data->prate == 0)
> + return -EINVAL;
> + armclk_data++;
> + }
> +
> + div0 = armclk_data->div0;
> + div1 = armclk_data->div1;
A comment about the following if would be nice.
> + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
> + div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
> + div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
> + }
> +
> + /*
> + * if the new and old parent clock speed is less than the clock speed
> + * of the alternate parent, then it should be ensured that at no point
> + * the armclk speed is more than the old_prate until the dividers are
> + * set.
> + */
> + tdiv0 = readl(base + DIV_CPU0);
> + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
> + EXYNOS4210_ARM_DIV2(tdiv0);
> + if (alt_prate > cur_armclk_rate) {
Shouldn't you compare two parent rates here, not alt parent rate with
current armclk rate?
Also, this condition compares only alt rate with current rate. Let's see:
1) old >= alt && new >= alt => alt < old X new
The voltage will be always enough to handle the switch, so no division
is needed.
2) old < alt && new >= alt => old < alt <= new
The voltage will be switched to higher or equal necessary one for alt
rate, so no division is needed.
3) old < alt && new < alt => old X new < alt
The voltage won't be enough for alt rate so division is needed.
4) old >= alt && new < alt => new < alt <= old
Current voltage is enough for alt rate and it will be lowered only after
the switching finishes, so division is not needed.
This means that division is necessary only if both new and old rates are
lower than alt and this is what the comment above says, but not what the
code does, which is slightly inefficient.
> + alt_div = _calc_div(alt_prate, cur_armclk_rate);
> + _exynos4210_set_armclk_div(base, alt_div);
> + div0 |= alt_div;
Hmm, this code is barely readable. It is not clear whether _calc_div()
is returning a value ready to be written to the register or real divisor
value. I'd make _calc_div() to simply return raw divisor value and then
use a macro that calculates required bitfield value.
Another thing is whether 8 is big enough maximum divisor. If not, both
DIV_CORE and DIV_CORE2 should be used together to form a 6-bit divisor,
which lets you divide by up to 64.
> + }
> +
> + /* select sclk_mpll as the alternate parent */
> + spin_lock_irqsave(armclk->lock, flags);
Hmm, is the start of critical section really here? The big
read-modify-write section seems to begin at
if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
> + mux_reg = readl(base + SRC_CPU);
> + writel(mux_reg | (1 << 16), base + SRC_CPU);
> +
> + timeout = jiffies + msecs_to_jiffies(10);
> + while (time_before(jiffies, timeout))
> + if (((readl(base + STAT_CPU) >> 16) & 0x7) == 2)
> + break;
> + spin_unlock_irqrestore(armclk->lock, flags);
Is this really end of critical secion? More writes to registers are
happening below. Keep in mind that APLL_RATIO field of CLK_DIV_CPU0
register is used by generic divider clock - "sclk_apll".
> +
> + if (((readl(base + STAT_CPU) >> 16) & 0x7) != 2)
> + pr_err("%s: re-parenting to sclk_mpll failed\n", __func__);
> +
> + /* alternate parent is active now. set the dividers */
> + writel(div0, base + DIV_CPU0);
> + timeout = jiffies + msecs_to_jiffies(10);
> + while (time_before(jiffies, timeout))
> + if (!readl(base + DIV_STAT_CPU0))
> + break;
> +
> + if (readl(base + DIV_STAT_CPU0))
> + pr_err("%s: timeout in divider0 stablization\n", __func__);
> +
> + writel(div1, base + DIV_CPU1);
> + timeout = jiffies + msecs_to_jiffies(10);
> + while (time_before(jiffies, timeout))
> + if (!readl(base + DIV_STAT_CPU1))
> + break;
> + if (readl(base + DIV_STAT_CPU1))
> + pr_err("%s: timeout in divider1 stablization\n", __func__);
IMHO to be safe, the spin_unlock_irqrestore() should be called here.
> +
> + return 0;
> +}
> +
> +static int exynos4210_armclk_post_rate_change(struct exynos_cpuclk *armclk,
> + void __iomem *base)
> +{
> + unsigned long mux_reg, flags;
> + unsigned long timeout = jiffies + msecs_to_jiffies(10);
> +
> + spin_lock_irqsave(armclk->lock, flags);
> + mux_reg = readl(base + SRC_CPU);
> + writel(mux_reg & ~(1 << 16), base + SRC_CPU);
Please replace (1 << 16) with appropriate macro.
> + while (time_before(jiffies, timeout))
> + if (((readl(base + STAT_CPU) >> 16) & 0x7) == 1)
> + break;
> + spin_unlock_irqrestore(armclk->lock, flags);
> +
> + if (((readl(base + STAT_CPU) >> 16) & 0x7) != 1)
> + pr_err("%s: re-parenting to mout_apll failed\n", __func__);
> +
> + return 0;
> +}
> +
> +/*
> + * This clock notifier is called when the frequency of the parent clock
> + * of armclk is to be changed. This notifier handles the setting up all
> + * the divider clocks, remux to temporary parent and handling the safe
> + * frequency levels when using temporary parent.
> + */
> +static int exynos4210_armclk_notifier_cb(struct notifier_block *nb,
> + unsigned long event, void *data)
> +{
> + struct clk_notifier_data *ndata = data;
> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_nb(nb);
> + void __iomem *base = armclk->ctrl_base + armclk->offset;
> + int err = 0;
> +
> + if (event == PRE_RATE_CHANGE)
> + err = exynos4210_armclk_pre_rate_change(ndata, armclk, base);
> + else if (event == POST_RATE_CHANGE)
> + err = exynos4210_armclk_post_rate_change(armclk, base);
> +
> + return notifier_from_errno(err);
> +}
> +
> +static int exynos4210_armclk_set_rate(struct clk_hw *hw, unsigned long drate,
> + unsigned long prate)
> +{
> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
> + void __iomem *base = armclk->ctrl_base + armclk->offset;
> + unsigned long div;
> +
> + div = drate < prate ? _calc_div(prate, drate) : 0;
> + _exynos4210_set_armclk_div(base, div);
Hmm, the code above in pre_rate_change() assumed that both DIV_CORE and
DIV_CORE2 are 0, but here it sets DIV_CORE to a potentially non-zero
value. It doesn't look correct.
> + return 0;
> +}
> +
> +static const struct clk_ops exynos4210_armclk_clk_ops = {
> + .recalc_rate = exynos4210_armclk_recalc_rate,
> + .round_rate = exynos_cpuclk_round_rate,
> + .set_rate = exynos4210_armclk_set_rate,
> +};
> +
> +/*
> + * parse divider configuration data from dt for all the cpu clock domain
> + * clocks in exynos4210 and compatible SoC's.
> + */
> +static int __init exynos4210_armclk_parser(struct device_node *np, void **data)
> +{
> + struct exynos4210_armclk_data *tdata;
> + u32 cfg[10], num_rows, row, col;
> + struct property *prop;
> + const __be32 *ptr = NULL;
> + u32 cells;
> + int ret;
> +
> + if (of_property_read_u32(np, "samsung,armclk-cells", &cells))
> + return -EINVAL;
> + prop = of_find_property(np, "samsung,armclk-divider-table", NULL);
You should rather use the *lenp argument of of_find_property(), instead
of dereferencing the struct.
> + if (!prop)
> + return -EINVAL;
> + if (!prop->value)
> + return -EINVAL;
You can skip the check above, as the calculation below will give you
num_rows equal 0 in this case.
> + if ((prop->length / sizeof(u32)) % cells)
> + return -EINVAL;
> + num_rows = (prop->length / sizeof(u32)) / cells;
> +
> + /* allocate a zero terminated table */
> + *data = kzalloc(sizeof(*tdata) * (num_rows + 1), GFP_KERNEL);
> + if (!*data)
> + ret = -ENOMEM;
Shouldn't you just return -ENOMEM here?
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data
2014-05-14 1:11 ` [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data Thomas Abraham
@ 2014-05-16 23:16 ` Tomasz Figa
0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-16 23:16 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
Hi Thomas,
Please see my comments inline.
On 14.05.2014 03:11, Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> For all Exynos based platforms, add CPU nodes, operating points and cpu
> clock data for migrating from Exynos specific cpufreq driver to using
> generic cpufreq-cpu0 driver.
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> arch/arm/boot/dts/exynos4210-origen.dts | 6 +++
> arch/arm/boot/dts/exynos4210-trats.dts | 6 +++
> arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +++
> arch/arm/boot/dts/exynos4210.dtsi | 35 +++++++++++++++++++
> arch/arm/boot/dts/exynos4212.dtsi | 18 ++++++++++
> arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +++
> arch/arm/boot/dts/exynos4412-origen.dts | 6 +++
> arch/arm/boot/dts/exynos4412-trats2.dts | 6 +++
> arch/arm/boot/dts/exynos4412.dtsi | 31 +++++++++++++++++
> arch/arm/boot/dts/exynos4x12.dtsi | 36 ++++++++++++++++++++
> arch/arm/boot/dts/exynos5250-arndale.dts | 6 +++
> arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +++
> arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +++
> arch/arm/boot/dts/exynos5250.dtsi | 41 +++++++++++++++++++++++
> 14 files changed, 215 insertions(+), 0 deletions(-)
[snip]
> diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
> index cacf614..22b967d 100644
> --- a/arch/arm/boot/dts/exynos4210.dtsi
> +++ b/arch/arm/boot/dts/exynos4210.dtsi
> @@ -36,6 +36,33 @@
> reg = <0x10023CA0 0x20>;
> };
>
> + cpus {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + cpu@0 {
style: Please add blank line between last property and first node.
> + device_type = "cpu";
> + compatible = "arm,cortex-a9";
> + reg = <0>;
This is not the right value. The bottom 24-bits of MPIDR register on
Exynos4210 are 0x900 and 0x901 for CPU0 and CPU1 respectively.
Of course this won't work before fixing the GIC driver to not rely on
wrong assumptions, but I have already posted patches [1] and need to
address comments.
[1] http://thread.gmane.org/gmane.linux.kernel.samsung-soc/29573
> + clocks = <&clock CLK_ARM_CLK>;
> + clock-names = "cpu";
[snip]
> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> index 15d3c0a..85005d1 100644
> --- a/arch/arm/boot/dts/exynos4412.dtsi
> +++ b/arch/arm/boot/dts/exynos4412.dtsi
> @@ -22,6 +22,37 @@
> / {
> compatible = "samsung,exynos4412", "samsung,exynos4";
>
> + cpus {
> + cpu@2 {
> + device_type = "cpu";
> + compatible = "arm,cortex-a9";
> + reg = <2>;
Same here. On Exynos4x12, the MPIDR values for CPUs are 0xa00, 0xa01,
0xa02 and 0xa03 for CPU0, CPU1, CPU2 and CPU3 respectively.
> + };
> + cpu@3 {
style: Please keep a single blank line of spacing between nodes.
Otherwise looks good.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
2014-05-14 1:11 ` [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5 Thomas Abraham
@ 2014-05-16 23:24 ` Tomasz Figa
2014-05-17 0:00 ` Tomasz Figa
2014-05-26 6:05 ` Thomas Abraham
0 siblings, 2 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-16 23:24 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
Hi Thomas,
Please see my comments inline.
On 14.05.2014 03:11, Thomas Abraham wrote:
> From; Thomas Abraham <thomas.ab@samsung.com>
>
> The clock blocks within the CMU_CPU clock domain are put together into a
> new composite clock type called the cpu clock. This clock type requires
> configuration data that will be atomically programmed in the multiple
> clock blocks encapsulated within the cpu clock type when the parent clock
> frequency is changed. This configuration data is held in the clock controller
> node. Update clock binding documentation about this configuration data format
> for Samsung Exynos4 and Exynos5 platforms.
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Kumar Gala <galak@codeaurora.org>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> .../devicetree/bindings/clock/exynos4-clock.txt | 37 ++++++++++++++++++++
> .../devicetree/bindings/clock/exynos5250-clock.txt | 36 +++++++++++++++++++
> 2 files changed, 73 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> index f5a5b19..0934e02 100644
> --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> @@ -15,6 +15,35 @@ Required Properties:
>
> - #clock-cells: should be 1.
>
> +- samsung,armclk-divider-table: when the frequency of the APLL is changed
> + the divider clocks in CMU_CPU clock domain also need to be updated. These
> + divider clocks have SoC specific divider clock output requirements for a
> + specific APLL clock speeds. When APLL clock rate is changed, these divider
> + clocks are reprogrammed with pre-determined values in order to maintain the
> + SoC specific divider clock outputs. This property lists the divider values
> + for divider clocks in the CMU_CPU block for supported APLL clock speeds.
> + The format of each entry included in the arm-frequency-table should be
> + as defined below
As far as I understand, the relation is not between the APLL frequency
and particular clocks in CPU domain, but rather between the latter and
input clock to CPU domain, which is _after_ the two dividers (called
DIV_CORE and DIV_CORE2 or ARM_DIV1 and ARM_DIV2), which is also exactly
the output frequency of ARMCLK.
> +
> + - for Exynos4210 and Exynos4212 based platforms:
> + cell #1: arm clock parent frequency
Considering my comment above, this should be rather ARMCLK frequency.
> + cell #2 ~ cell 9#: value of clock divider in the following order
> + corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
> + pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio.
> +
> + - for Exynos4412 based platforms:
> + cell #1: expected arm clock parent frequency
Ditto.
> + cell #2 ~ cell #10: value of clock divider in the following order
> + corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
> + pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio, cores_ratio
> +
> +- samsung,armclk-cells: defines the number of cells in
> + samsung,armclk-divider-table property. The value of this property depends on
> + the SoC type.
To follow conventions used by all other bindings with variable number of
cells, the property should be called "#samsung,armclk-cells". AFAIK the
"#" should be interpreted as "number of" and so accents the meaning of
the property.
> +
> + - for Exynos4210 and Exynos4212: the value should be 9.
> + - for Exynos4412: the value should be 10.
> +
> Each clock is assigned an identifier and client nodes can use this identifier
> to specify the clock which they consume.
>
> @@ -28,6 +57,14 @@ Example 1: An example of a clock controller node is listed below.
> compatible = "samsung,exynos4210-clock";
> reg = <0x10030000 0x20000>;
> #clock-cells = <1>;
> +
> + samsung,armclk-cells = <9>;
> + samsung,armclk-divider-table = <1200000 3 7 3 4 1 7 5 0>,
> + <1000000 3 7 3 4 1 7 4 0>,
> + < 800000 3 7 3 3 1 7 3 0>,
> + < 500000 3 7 3 3 1 7 3 0>,
> + < 400000 3 7 3 3 1 7 3 0>,
> + < 200000 1 3 1 1 1 0 3 0>;
> };
>
> Example 2: UART controller node that consumes the clock generated by the clock
> diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> index 536eacd..3d63d09 100644
> --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> @@ -13,6 +13,24 @@ Required Properties:
Same comments apply to this file as well.
Also, shouldn't you also extend exynos5420-clock.txt in the same way?
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock.
2014-05-14 1:11 ` [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock Thomas Abraham
2014-05-14 21:37 ` Mike Turquette
@ 2014-05-16 23:57 ` Tomasz Figa
1 sibling, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-16 23:57 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
Hi Thomas,
On 14.05.2014 03:11, Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> With the addition of the new Samsung specific cpu-clock type, the
> arm clock can be represented as a cpu-clock type and the independent
> clock blocks that made up the arm clock can be removed.
>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> drivers/clk/samsung/clk-exynos4.c | 25 +++++++++----------------
> drivers/clk/samsung/clk-exynos5250.c | 12 ++++++------
> include/dt-bindings/clock/exynos5250.h | 1 +
> 3 files changed, 16 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> index b4f9672..7e3bb16c 100644
> --- a/drivers/clk/samsung/clk-exynos4.c
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -471,7 +471,6 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
> MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
> MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
> MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
> @@ -530,7 +529,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
> MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
> MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
> MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
> - MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
> MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
> MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
> MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
> @@ -572,8 +570,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
>
> /* list of divider clocks supported in all exynos4 soc's */
> static struct samsung_div_clock exynos4_div_clks[] __initdata = {
> - DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
> - DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
Please don't remove these clocks, as they will be necessary to define
proper hierarchy CMU_CPU clock output block. In particular, access to
following clocks will be required:
div_corem0
div_corem1
div_cores
div_atb
div_periph
div_pclk_dbg
div_hpm
They might be implemented using normal dividers, but with
CLK_DIVIDER_READ_ONLY [1] and CLK_GET_RATE_NOCACHE flags.
[1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/322977/focus=322978
This also means keeping mout_core clock defined, but with
CLK_MUX_READ_ONLY flag it should be fine.
> DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
> DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
> DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
> @@ -619,8 +615,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
> DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
> DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
> DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
> - DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
> - DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
> + DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
> + CLK_GET_RATE_NOCACHE, 0),
Do you need CLK_GET_RATE_NOCACHE here? AFAIK whenever rate is changed on
APLL the clock core will recalculate rate of this clock.
> DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
> CLK_SET_RATE_PARENT, 0),
> DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
> @@ -1003,12 +999,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
> 0),
> };
>
> -static struct samsung_clock_alias exynos4_aliases[] __initdata = {
> - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
> - ALIAS(CLK_ARM_CLK, NULL, "armclk"),
> - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
> -};
> -
> static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
> ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
> };
> @@ -1241,6 +1231,9 @@ static void __init exynos4_clk_init(struct device_node *np,
> ARRAY_SIZE(exynos4210_gate_clks));
> samsung_clk_register_alias(exynos4210_aliases,
> ARRAY_SIZE(exynos4210_aliases));
> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4210,
> + ARRAY_SIZE(mout_core_p4210), reg_base, np, NULL,
> + &samsung_clk_lock);
> } else {
> samsung_clk_register_mux(exynos4x12_mux_clks,
> ARRAY_SIZE(exynos4x12_mux_clks));
> @@ -1250,11 +1243,11 @@ static void __init exynos4_clk_init(struct device_node *np,
> ARRAY_SIZE(exynos4x12_gate_clks));
> samsung_clk_register_alias(exynos4x12_aliases,
> ARRAY_SIZE(exynos4x12_aliases));
> + exynos_register_arm_clock(CLK_ARM_CLK, mout_core_p4x12,
> + ARRAY_SIZE(mout_core_p4x12), reg_base, np, NULL,
> + &samsung_clk_lock);
> }
>
> - samsung_clk_register_alias(exynos4_aliases,
> - ARRAY_SIZE(exynos4_aliases));
> -
> exynos4_clk_sleep_init();
>
> pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
> @@ -1262,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
> exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
> _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
> _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
> - _get_rate("arm_clk"));
> + _get_rate("armclk"));
I'd prefer name of this clock to be not changed to not cause conflicts
with other patches.
Similar comments apply to clk-exynos5250.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
2014-05-16 23:24 ` Tomasz Figa
@ 2014-05-17 0:00 ` Tomasz Figa
2014-05-26 6:05 ` Thomas Abraham
1 sibling, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-17 0:00 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
On 17.05.2014 01:24, Tomasz Figa wrote:
> Also, shouldn't you also extend exynos5420-clock.txt in the same way?
Please ignore this comment. Somehow I thought other patches of this
series also had support for Exynos5420.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 1:11 ` [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver Thomas Abraham
2014-05-14 12:50 ` Arnd Bergmann
@ 2014-05-17 0:04 ` Tomasz Figa
1 sibling, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-17 0:04 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
On 14.05.2014 03:11, Thomas Abraham wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> Remove the platform device instantiation for Exynos specific cpufreq
> driver and add the platform device for cpufreq-cpu0 driver.
>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> arch/arm/mach-exynos/exynos.c | 4 +++-
> 1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
> index b32a907..489a495 100644
> --- a/arch/arm/mach-exynos/exynos.c
> +++ b/arch/arm/mach-exynos/exynos.c
> @@ -232,7 +232,9 @@ void __init exynos_cpuidle_init(void)
>
> void __init exynos_cpufreq_init(void)
> {
> - platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
> + if (!(of_machine_is_compatible("samsung,exynos5420")) &&
> + !(of_machine_is_compatible("samsung,exynos5440")))
> + platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
> }
>
> void __init exynos_init_late(void)
>
As a good intermediate step that can be completely replaced in future,
if necessary (as opposed to stable DT bindings...):
Acked-by: Tomasz Figa <t.figa@samsung.com>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
` (8 preceding siblings ...)
2014-05-14 12:51 ` [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Arnd Bergmann
@ 2014-05-17 0:14 ` Tomasz Figa
9 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-17 0:14 UTC (permalink / raw)
To: Thomas Abraham, cpufreq, linux-arm-kernel
Cc: mturquette, shawn.guo, devicetree, rjw, linux-samsung-soc,
kgene.kim, t.figa, l.majewski, viresh.kumar, heiko, thomas.ab
Hi Thomas,
In general the design already looks good, but I commented on several
implementation issues I found in particular patches (and some minor
nitpicks while at it).
Please let me know whether you have time to work on addressing them.
Otherwise we can just let me, Lukasz or someone else address remaining
issues.
Best regards,
Tomasz
On 14.05.2014 03:11, Thomas Abraham wrote:
> Changes since v3:
> - Addressed comments from Tomasz Figa <t.figa@samsung.com>
> [http://www.spinics.net/lists/cpufreq/msg09290.html]
> - Rebased to v3.15-rc4
>
> Changes since v2:
> - Safe operating voltage is not required while switching APLL frequency
> since the temporary parent's clock is divided down to keep armclk within
> permissible limits. Thanks to Heiko Stübner <heiko@sntech.de> for this
> suggesting this.
> - Rob had suggested to use max frequency for each of the divider clock
> outputs instead of divider values. But due to certain SoC specific
> characteristics, the divider values corresponding to the input clock
> frequency for the CMU_CPU clock blocks have to be used.
>
> Changes since v1:
> - Removes Exynos4x12 and Exynos5250 cpufreq driver also.
> - Device tree based clock configuration lookup as suggested by Lukasz
> Majewski and Tomasz Figa.
> - safe operating point binding reworked as suggested by Shawn Guo.
>
> The patch series removes the use of Exynos specific cpufreq driver and enables
> the use of cpufreq-cpu0 driver for Exynos4210, Exynos4x12 and Exynos5250 based
> platforms. This is being done for few reasons.
>
> (a) The Exynos cpufreq driver reads/writes clock controller registers
> bypassing the Exynos CCF driver which is sort of problematic.
> (b) Removes the need for having clock controller register definitions
> in the cpufreq driver and also removes the need for statically
> io-remapping clock controller address space (helps in moving towards
> multiplatform kernel).
>
> Thomas Abraham (8):
> cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies
> clk: samsung: change scope of samsung clock lock to global
> clk: samsung: add infrastructure to register cpu clocks
> Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
> clk: exynos: use cpu-clock provider type to represent arm clock
> ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data
> ARM: Exynos: switch to using generic cpufreq-cpu0 driver
> cpufreq: exynos: remove all exynos specific cpufreq driver support
>
>
> .../devicetree/bindings/clock/exynos4-clock.txt | 37 ++
> .../devicetree/bindings/clock/exynos5250-clock.txt | 36 ++
> .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 2 +
> arch/arm/boot/dts/exynos4210-origen.dts | 6 +
> arch/arm/boot/dts/exynos4210-trats.dts | 6 +
> arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +
> arch/arm/boot/dts/exynos4210.dtsi | 35 ++
> arch/arm/boot/dts/exynos4212.dtsi | 18 +
> arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +
> arch/arm/boot/dts/exynos4412-origen.dts | 6 +
> arch/arm/boot/dts/exynos4412-trats2.dts | 6 +
> arch/arm/boot/dts/exynos4412.dtsi | 31 ++
> arch/arm/boot/dts/exynos4x12.dtsi | 36 ++
> arch/arm/boot/dts/exynos5250-arndale.dts | 6 +
> arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +
> arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +
> arch/arm/boot/dts/exynos5250.dtsi | 41 ++
> arch/arm/mach-exynos/exynos.c | 4 +-
> drivers/clk/samsung/Makefile | 2 +-
> drivers/clk/samsung/clk-cpu.c | 458 ++++++++++++++++++++
> drivers/clk/samsung/clk-exynos4.c | 25 +-
> drivers/clk/samsung/clk-exynos5250.c | 12 +-
> drivers/clk/samsung/clk.c | 13 +-
> drivers/clk/samsung/clk.h | 7 +
> drivers/cpufreq/Kconfig | 11 +
> drivers/cpufreq/Kconfig.arm | 52 ---
> drivers/cpufreq/Makefile | 4 -
> drivers/cpufreq/cpufreq-cpu0.c | 5 +
> drivers/cpufreq/exynos-cpufreq.c | 209 ---------
> drivers/cpufreq/exynos-cpufreq.h | 91 ----
> drivers/cpufreq/exynos4210-cpufreq.c | 157 -------
> drivers/cpufreq/exynos4x12-cpufreq.c | 211 ---------
> drivers/cpufreq/exynos5250-cpufreq.c | 183 --------
> include/dt-bindings/clock/exynos5250.h | 1 +
> 34 files changed, 799 insertions(+), 936 deletions(-)
> create mode 100644 drivers/clk/samsung/clk-cpu.c
> delete mode 100644 drivers/cpufreq/exynos-cpufreq.c
> delete mode 100644 drivers/cpufreq/exynos-cpufreq.h
> delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c
> delete mode 100644 drivers/cpufreq/exynos4x12-cpufreq.c
> delete mode 100644 drivers/cpufreq/exynos5250-cpufreq.c
>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-16 17:17 ` Tomasz Figa
@ 2014-05-23 14:41 ` Thomas Abraham
2014-05-23 14:50 ` Tomasz Figa
0 siblings, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-23 14:41 UTC (permalink / raw)
To: Tomasz Figa
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
rjw@rjwysocki.net, linux-samsung-soc@vger.kernel.org, Kukjin Kim,
Lukasz Majewski, Viresh Kumar, Heiko Stübner
Hi Tomasz,
On Fri, May 16, 2014 at 10:47 PM, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Thomas,
>
> On 14.05.2014 03:11, Thomas Abraham wrote:
>> From: Thomas Abraham <thomas.ab@samsung.com>
>>
>> The CPU clock provider supplies the clock to the CPU clock domain. The
>> composition and organization of the CPU clock provider could vary among
>> Exynos SoCs. A CPU clock provider can be composed of clock mux, dividers
>> and gates. This patch defines a new clock type for CPU clock provider and
>> adds infrastructure to register the CPU clock providers for Samsung
>> platforms.
>>
>> Cc: Tomasz Figa <t.figa@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> ---
>> drivers/clk/samsung/Makefile | 2 +-
>> drivers/clk/samsung/clk-cpu.c | 458 +++++++++++++++++++++++++++++++++++++++++
>> drivers/clk/samsung/clk.h | 5 +
>> 3 files changed, 464 insertions(+), 1 deletions(-)
>> create mode 100644 drivers/clk/samsung/clk-cpu.c
>>
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> index 8eb4799..e2b453f 100644
>> --- a/drivers/clk/samsung/Makefile
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -2,7 +2,7 @@
>> # Samsung Clock specific Makefile
>> #
>>
>> -obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
>> +obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o
>> obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
>> obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
>> obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
>> diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
>> new file mode 100644
>> index 0000000..6a40862
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-cpu.c
>> @@ -0,0 +1,458 @@
>> +/*
>> + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
>> + * Author: Thomas Abraham <thomas.ab@samsung.com>
>> + *
>> + * 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.
>> + *
>> + * This file contains the utility functions to register the cpu clocks
>> + * for samsung platforms.
>
> s/cpu/CPU/
> s/samsung/Samsung/
>
>> +*/
>> +
>> +#include <linux/errno.h>
>> +#include "clk.h"
>> +
>> +#define SRC_CPU 0x0
>> +#define STAT_CPU 0x200
>> +#define DIV_CPU0 0x300
>> +#define DIV_CPU1 0x304
>> +#define DIV_STAT_CPU0 0x400
>> +#define DIV_STAT_CPU1 0x404
>> +
>> +#define MAX_DIV 8
>> +
>> +#define EXYNOS4210_ARM_DIV1(div) ((div & 0x7) + 1)
>> +#define EXYNOS4210_ARM_DIV2(div) (((div >> 28) & 0x7) + 1)
>> +
>> +#define EXYNOS4210_DIV_CPU0(d5, d4, d3, d2, d1, d0) \
>> + ((d5 << 24) | (d4 << 20) | (d3 << 16) | (d2 << 12) | \
>> + (d1 << 8) | (d0 << 4))
>> +#define EXYNOS4210_DIV_CPU1(d2, d1, d0) \
>> + ((d2 << 8) | (d1 << 4) | (d0 << 0))
>
> Macro arguments should be put into parentheses to make sure that whole
> argument is subject to further arithmetic operations.
>
>> +
>> +#define EXYNOS4210_DIV1_HPM_MASK ((0x7 << 0) | (0x7 << 4))
>> +#define EXYNOS4210_MUX_HPM_MASK (1 << 20)
>> +
>> +/**
>> + * struct exynos4210_armclk_data: config data to setup exynos4210 cpu clocks.
>> + * @prate: frequency of the parent clock.
>> + * @div0: value to be programmed in the div_cpu0 register.
>> + * @div1: value to be programmed in the div_cpu1 register.
>> + *
>> + * This structure holds the divider configuration data for divider clocks
>> + * belonging to the CMU_CPU clock domain. The parent frequency at which these
>> + * divider values are vaild is specified in @prate.
>
> s/vaild/valid/
>
>> + */
>> +struct exynos4210_armclk_data {
>> + unsigned long prate;
>> + unsigned int div0;
>> + unsigned int div1;
>> +};
>> +
>> +/**
>> + * struct exynos_cpuclk: information about clock supplied to a CPU core.
>> + * @hw: handle between ccf and cpu clock.
>
> s/ccf/CCF/
> s/cpu/CPU/
>
>> + * @alt_parent: alternate parent clock to use when switching the speed
>> + * of the primary parent clock.
>> + * @ctrl_base: base address of the clock controller.
>> + * @offset: offset from the ctrl_base address where the cpu clock div/mux
>
> s/cpu/CPU/
>
>> + * registers can be accessed.
>> + * @clk_nb: clock notifier registered for changes in clock speed of the
>> + * primary parent clock.
>> + * @lock: register access lock.
>> + * @data: optional data which the acutal instantiation of this clock
>> + * can use.
>
> s/acutal/actual/
>
>> + */
>> +struct exynos_cpuclk {
>> + struct clk_hw hw;
>> + struct clk *alt_parent;
>> + void __iomem *ctrl_base;
>> + unsigned long offset;
>> + struct notifier_block clk_nb;
>> + spinlock_t *lock;
>> + void *data;
>> +};
>> +
>> +#define to_exynos_cpuclk_hw(hw) container_of(hw, struct exynos_cpuclk, hw)
>> +#define to_exynos_cpuclk_nb(nb) container_of(nb, struct exynos_cpuclk, clk_nb)
>> +
>> +/**
>> + * struct exynos_cpuclk_soc_data: soc specific data for cpu clocks.
>> + * @parser: pointer to a function that can parse SoC specific data.
>> + * @ops: clock operations to be used for this clock.
>> + * @offset: optional offset from base of clock controller register base, to
>> + * be used when accessing clock controller registers related to the
>> + * cpu clock.
>
> s/cpu/CPU/
>
>> + * @clk_cb: the clock notifier callback to be called for changes in the
>> + * clock rate of the primary parent clock.
>> + *
>> + * This structure provides SoC specific data for ARM clocks. Based on
>> + * the compatible value of the clock controller node, the value of the
>> + * fields in this structure can be populated.
>> + */
>> +struct exynos_cpuclk_soc_data {
>> + int (*parser)(struct device_node *, void **);
>
> Here you don't have argument names, but...
>
>> + const struct clk_ops *ops;
>> + unsigned int offset;
>> + int (*clk_cb)(struct notifier_block *nb, unsigned long evt, void *data);
>
> ...here you have. Please keep some consistency.
>
>> +};
>> +
>> +/* common round rate callback useable for all types of cpu clocks */
>
> s/cpu/CPU/
>
>> +static long exynos_cpuclk_round_rate(struct clk_hw *hw,
>> + unsigned long drate, unsigned long *prate)
>
> Hmm, the long return type will overflow with *prate > INT_MAX and
> best_div == 1, I wonder why it is defined so in CCF, even though it
> shouldn't return error codes...
>
>> +{
>> + struct clk *parent = __clk_get_parent(hw->clk);
>> + unsigned long max_prate = __clk_round_rate(parent, UINT_MAX);
>> + unsigned long t_prate, div = 1, best_div = 1;
>> + unsigned long delta, min_delta = UINT_MAX;
>
> By the way, shouldn't this function take into account the list of
> available CPU rates and round drate to a less or equal supported one?
> Otherwise, in further code you might hit cases where an unsupported rate
> is requested, which is against the CCF semantics, if .round_rate()
> operation is provided.
>
>> +
>> + do {
>> + t_prate = __clk_round_rate(parent, drate * div);
>> + delta = drate - (t_prate / div);
>> + if (delta < min_delta) {
>> + *prate = t_prate;
>> + best_div = div;
>> + min_delta = delta;
>> + }
>> + if (!delta)
>> + break;
>> + div++;
>> + } while ((drate * div) < max_prate && div <= MAX_DIV);
>> +
>> + return *prate / best_div;
>> +}
>> +
>> +static unsigned long _calc_div(unsigned long prate, unsigned long drate)
>> +{
>> + unsigned long div = prate / drate;
>> +
>> + WARN_ON(div >= MAX_DIV);
>> + return (!(prate % drate)) ? div-- : div;
>
> Could you explain what is the purpose of this check and adjustment?
>
> If my assumption that this is essentially DIV_ROUND_UP(prate, drate) - 1
> is true then this probably used to obtain a divisor value to get less or
> equal rate than drate. Is it right?
>
>> +}
>> +
>> +/* helper function to register a cpu clock */
>> +static int __init exynos_cpuclk_register(unsigned int lookup_id,
>> + const char *name, const char **parents,
>> + unsigned int num_parents, void __iomem *base,
>
> The num_parents argument doesn't seem to be used in the code. Maybe
> instead you should simply replace it and parents arguments with (const
> char *parent) and (const char *alt_parent)?
>
>> + const struct exynos_cpuclk_soc_data *soc_data,
>> + struct device_node *np, const struct clk_ops *ops,
>> + spinlock_t *lock)
>> +{
>> + struct exynos_cpuclk *cpuclk;
>> + struct clk_init_data init;
>> + struct clk *clk;
>> + int ret;
>> +
>> + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
>> + if (!cpuclk) {
>> + pr_err("%s: could not allocate memory for %s clock\n",
>> + __func__, name);
>> + return -ENOMEM;
>> + }
>> +
>> + init.name = name;
>> + init.flags = CLK_SET_RATE_PARENT;
>> + init.parent_names = parents;
>> + init.num_parents = 1;
>> + init.ops = ops;
>> +
>> + cpuclk->hw.init = &init;
>> + cpuclk->ctrl_base = base;
>> + cpuclk->lock = lock;
>> +
>> + ret = soc_data->parser(np, &cpuclk->data);
>> + if (ret) {
>> + pr_err("%s: error %d in parsing %s clock data",
>> + __func__, ret, name);
>> + ret = -EINVAL;
>> + goto free_cpuclk;
>> + }
>> + cpuclk->offset = soc_data->offset;
>> + init.ops = soc_data->ops;
>> +
>> + cpuclk->clk_nb.notifier_call = soc_data->clk_cb;
>> + if (clk_notifier_register(__clk_lookup(parents[0]), &cpuclk->clk_nb)) {
>> + pr_err("%s: failed to register clock notifier for %s\n",
>> + __func__, name);
>> + goto free_cpuclk_data;
>> + }
>> +
>> + cpuclk->alt_parent = __clk_lookup(parents[1]);
>> + if (!cpuclk->alt_parent) {
>> + pr_err("%s: could not lookup alternate parent %s\n",
>> + __func__, parents[1]);
>> + ret = -EINVAL;
>> + goto free_cpuclk_data;
>
> Shouldn't it be goto unregister_notifier and the notifier unregistered
> there?
>
>> + }
>> +
>> + clk = clk_register(NULL, &cpuclk->hw);
>> + if (IS_ERR(clk)) {
>> + pr_err("%s: could not register cpuclk %s\n", __func__, name);
>> + ret = PTR_ERR(clk);
>> + goto free_cpuclk_data;
>
> Ditto.
>
>> + }
>> +
>> + samsung_clk_add_lookup(clk, lookup_id);
>> + return 0;
>> +
>> +free_cpuclk_data:
>> + kfree(cpuclk->data);
>> +free_cpuclk:
>> + kfree(cpuclk);
>> + return ret;
>> +}
>> +
>> +static void _exynos4210_set_armclk_div(void __iomem *base, unsigned long div)
>> +{
>> + unsigned long timeout = jiffies + msecs_to_jiffies(10);
>> +
>> + writel((readl(base + DIV_CPU0) & ~0x7) | div, base + DIV_CPU0);
>
> The 0x7 could be defined as a preprocessor macro. Also for increased
> readability, this could be split into separate read, modify and write.
>
>> + while (time_before(jiffies, timeout))
>> + if (!readl(base + DIV_STAT_CPU0))
>> + return;
>> + pr_err("%s: timeout in divider stablization\n", __func__);
>> +}
>> +
>> +static unsigned long exynos4210_armclk_recalc_rate(struct clk_hw *hw,
>> + unsigned long parent_rate)
>> +{
>> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
>> + void __iomem *base = armclk->ctrl_base + armclk->offset;
>> + unsigned long div0 = readl(base + DIV_CPU0);
>> +
>> + return parent_rate / EXYNOS4210_ARM_DIV1(div0) /
>> + EXYNOS4210_ARM_DIV2(div0);
>> +}
>> +
>> +static int exynos4210_armclk_pre_rate_change(struct clk_notifier_data *ndata,
>> + struct exynos_cpuclk *armclk, void __iomem *base)
>> +{
>> + struct exynos4210_armclk_data *armclk_data = armclk->data;
>> + unsigned long alt_prate = clk_get_rate(armclk->alt_parent);
>> + unsigned long alt_div, div0, div1, tdiv0, mux_reg;
>> + unsigned long cur_armclk_rate, timeout;
>> + unsigned long flags;
>> +
>> + /* find out the divider values to use for clock data */
>> + while (armclk_data->prate != ndata->new_rate) {
>
> I assume this code relies on the assumption that target DIV_CORE and
> DIV_CORE2 are always 0 (divide by 1)? Otherwise it should compare
> armclk_data->prate with new parent rate, not new target armclk rate,
> which would be parent rate divided by DIV_CORE and DIV_CORE2.
>
>> + if (armclk_data->prate == 0)
>> + return -EINVAL;
>> + armclk_data++;
>> + }
>> +
>> + div0 = armclk_data->div0;
>> + div1 = armclk_data->div1;
>
> A comment about the following if would be nice.
>
>> + if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
>> + div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
>> + div1 |= ((armclk_data->div1) & ~EXYNOS4210_DIV1_HPM_MASK);
>> + }
>> +
>> + /*
>> + * if the new and old parent clock speed is less than the clock speed
>> + * of the alternate parent, then it should be ensured that at no point
>> + * the armclk speed is more than the old_prate until the dividers are
>> + * set.
>> + */
>> + tdiv0 = readl(base + DIV_CPU0);
>> + cur_armclk_rate = ndata->old_rate / EXYNOS4210_ARM_DIV1(tdiv0) /
>> + EXYNOS4210_ARM_DIV2(tdiv0);
>> + if (alt_prate > cur_armclk_rate) {
>
> Shouldn't you compare two parent rates here, not alt parent rate with
> current armclk rate?
>
> Also, this condition compares only alt rate with current rate. Let's see:
>
> 1) old >= alt && new >= alt => alt < old X new
>
> The voltage will be always enough to handle the switch, so no division
> is needed.
>
> 2) old < alt && new >= alt => old < alt <= new
>
> The voltage will be switched to higher or equal necessary one for alt
> rate, so no division is needed.
>
> 3) old < alt && new < alt => old X new < alt
>
> The voltage won't be enough for alt rate so division is needed.
>
> 4) old >= alt && new < alt => new < alt <= old
>
> Current voltage is enough for alt rate and it will be lowered only after
> the switching finishes, so division is not needed.
>
> This means that division is necessary only if both new and old rates are
> lower than alt and this is what the comment above says, but not what the
> code does, which is slightly inefficient.
>
>> + alt_div = _calc_div(alt_prate, cur_armclk_rate);
>> + _exynos4210_set_armclk_div(base, alt_div);
>> + div0 |= alt_div;
>
> Hmm, this code is barely readable. It is not clear whether _calc_div()
> is returning a value ready to be written to the register or real divisor
> value. I'd make _calc_div() to simply return raw divisor value and then
> use a macro that calculates required bitfield value.
>
> Another thing is whether 8 is big enough maximum divisor. If not, both
> DIV_CORE and DIV_CORE2 should be used together to form a 6-bit divisor,
> which lets you divide by up to 64.
>
>> + }
>> +
>> + /* select sclk_mpll as the alternate parent */
>> + spin_lock_irqsave(armclk->lock, flags);
>
> Hmm, is the start of critical section really here? The big
> read-modify-write section seems to begin at
>
> if (readl(base + SRC_CPU) & EXYNOS4210_MUX_HPM_MASK) {
> div1 = readl(base + DIV_CPU1) & EXYNOS4210_DIV1_HPM_MASK;
>
>> + mux_reg = readl(base + SRC_CPU);
>> + writel(mux_reg | (1 << 16), base + SRC_CPU);
>> +
>> + timeout = jiffies + msecs_to_jiffies(10);
>> + while (time_before(jiffies, timeout))
>> + if (((readl(base + STAT_CPU) >> 16) & 0x7) == 2)
>> + break;
>> + spin_unlock_irqrestore(armclk->lock, flags);
>
> Is this really end of critical secion? More writes to registers are
> happening below. Keep in mind that APLL_RATIO field of CLK_DIV_CPU0
> register is used by generic divider clock - "sclk_apll".
>
>> +
>> + if (((readl(base + STAT_CPU) >> 16) & 0x7) != 2)
>> + pr_err("%s: re-parenting to sclk_mpll failed\n", __func__);
>> +
>> + /* alternate parent is active now. set the dividers */
>> + writel(div0, base + DIV_CPU0);
>> + timeout = jiffies + msecs_to_jiffies(10);
>> + while (time_before(jiffies, timeout))
>> + if (!readl(base + DIV_STAT_CPU0))
>> + break;
>> +
>> + if (readl(base + DIV_STAT_CPU0))
>> + pr_err("%s: timeout in divider0 stablization\n", __func__);
>> +
>> + writel(div1, base + DIV_CPU1);
>> + timeout = jiffies + msecs_to_jiffies(10);
>> + while (time_before(jiffies, timeout))
>> + if (!readl(base + DIV_STAT_CPU1))
>> + break;
>> + if (readl(base + DIV_STAT_CPU1))
>> + pr_err("%s: timeout in divider1 stablization\n", __func__);
>
> IMHO to be safe, the spin_unlock_irqrestore() should be called here.
>
>> +
>> + return 0;
>> +}
>> +
>> +static int exynos4210_armclk_post_rate_change(struct exynos_cpuclk *armclk,
>> + void __iomem *base)
>> +{
>> + unsigned long mux_reg, flags;
>> + unsigned long timeout = jiffies + msecs_to_jiffies(10);
>> +
>> + spin_lock_irqsave(armclk->lock, flags);
>> + mux_reg = readl(base + SRC_CPU);
>> + writel(mux_reg & ~(1 << 16), base + SRC_CPU);
>
> Please replace (1 << 16) with appropriate macro.
>
>> + while (time_before(jiffies, timeout))
>> + if (((readl(base + STAT_CPU) >> 16) & 0x7) == 1)
>> + break;
>> + spin_unlock_irqrestore(armclk->lock, flags);
>> +
>> + if (((readl(base + STAT_CPU) >> 16) & 0x7) != 1)
>> + pr_err("%s: re-parenting to mout_apll failed\n", __func__);
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * This clock notifier is called when the frequency of the parent clock
>> + * of armclk is to be changed. This notifier handles the setting up all
>> + * the divider clocks, remux to temporary parent and handling the safe
>> + * frequency levels when using temporary parent.
>> + */
>> +static int exynos4210_armclk_notifier_cb(struct notifier_block *nb,
>> + unsigned long event, void *data)
>> +{
>> + struct clk_notifier_data *ndata = data;
>> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_nb(nb);
>> + void __iomem *base = armclk->ctrl_base + armclk->offset;
>> + int err = 0;
>> +
>> + if (event == PRE_RATE_CHANGE)
>> + err = exynos4210_armclk_pre_rate_change(ndata, armclk, base);
>> + else if (event == POST_RATE_CHANGE)
>> + err = exynos4210_armclk_post_rate_change(armclk, base);
>> +
>> + return notifier_from_errno(err);
>> +}
>> +
>> +static int exynos4210_armclk_set_rate(struct clk_hw *hw, unsigned long drate,
>> + unsigned long prate)
>> +{
>> + struct exynos_cpuclk *armclk = to_exynos_cpuclk_hw(hw);
>> + void __iomem *base = armclk->ctrl_base + armclk->offset;
>> + unsigned long div;
>> +
>> + div = drate < prate ? _calc_div(prate, drate) : 0;
>> + _exynos4210_set_armclk_div(base, div);
>
> Hmm, the code above in pre_rate_change() assumed that both DIV_CORE and
> DIV_CORE2 are 0, but here it sets DIV_CORE to a potentially non-zero
> value. It doesn't look correct.
>
>> + return 0;
>> +}
>> +
>> +static const struct clk_ops exynos4210_armclk_clk_ops = {
>> + .recalc_rate = exynos4210_armclk_recalc_rate,
>> + .round_rate = exynos_cpuclk_round_rate,
>> + .set_rate = exynos4210_armclk_set_rate,
>> +};
>> +
>> +/*
>> + * parse divider configuration data from dt for all the cpu clock domain
>> + * clocks in exynos4210 and compatible SoC's.
>> + */
>> +static int __init exynos4210_armclk_parser(struct device_node *np, void **data)
>> +{
>> + struct exynos4210_armclk_data *tdata;
>> + u32 cfg[10], num_rows, row, col;
>> + struct property *prop;
>> + const __be32 *ptr = NULL;
>> + u32 cells;
>> + int ret;
>> +
>> + if (of_property_read_u32(np, "samsung,armclk-cells", &cells))
>> + return -EINVAL;
>> + prop = of_find_property(np, "samsung,armclk-divider-table", NULL);
>
> You should rather use the *lenp argument of of_find_property(), instead
> of dereferencing the struct.
>
>> + if (!prop)
>> + return -EINVAL;
>> + if (!prop->value)
>> + return -EINVAL;
>
> You can skip the check above, as the calculation below will give you
> num_rows equal 0 in this case.
>
>> + if ((prop->length / sizeof(u32)) % cells)
>> + return -EINVAL;
>> + num_rows = (prop->length / sizeof(u32)) / cells;
>> +
>> + /* allocate a zero terminated table */
>> + *data = kzalloc(sizeof(*tdata) * (num_rows + 1), GFP_KERNEL);
>> + if (!*data)
>> + ret = -ENOMEM;
>
> Shouldn't you just return -ENOMEM here?
>
> Best regards,
> Tomasz
Thanks for your detailed review. I have made all the changes that you
have suggested.
Regards,
Thomas.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks
2014-05-23 14:41 ` Thomas Abraham
@ 2014-05-23 14:50 ` Tomasz Figa
0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-23 14:50 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
rjw@rjwysocki.net, linux-samsung-soc@vger.kernel.org, Kukjin Kim,
Lukasz Majewski, Viresh Kumar, Heiko Stübner
Hi Thomas,
On 23.05.2014 16:41, Thomas Abraham wrote:
[snip]
> Thanks for your detailed review. I have made all the changes that you
> have suggested.
Unfortunately it seems like you have missed quite a lot of my comments,
especially those regarding patch 4/8, which adds DT binding.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
2014-05-16 23:24 ` Tomasz Figa
2014-05-17 0:00 ` Tomasz Figa
@ 2014-05-26 6:05 ` Thomas Abraham
2014-05-26 11:02 ` Tomasz Figa
1 sibling, 1 reply; 58+ messages in thread
From: Thomas Abraham @ 2014-05-26 6:05 UTC (permalink / raw)
To: Tomasz Figa
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
rjw@rjwysocki.net, linux-samsung-soc@vger.kernel.org, Kukjin Kim,
Tomasz Figa, Lukasz Majewski, Viresh Kumar, Heiko Stübner,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
Hi Tomasz,
Thanks for your comments. Please see inline reply.
On Sat, May 17, 2014 at 4:54 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Thomas,
>
> Please see my comments inline.
>
> On 14.05.2014 03:11, Thomas Abraham wrote:
>> From; Thomas Abraham <thomas.ab@samsung.com>
>>
>> The clock blocks within the CMU_CPU clock domain are put together into a
>> new composite clock type called the cpu clock. This clock type requires
>> configuration data that will be atomically programmed in the multiple
>> clock blocks encapsulated within the cpu clock type when the parent clock
>> frequency is changed. This configuration data is held in the clock controller
>> node. Update clock binding documentation about this configuration data format
>> for Samsung Exynos4 and Exynos5 platforms.
>>
>> Cc: Tomasz Figa <t.figa@samsung.com>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Pawel Moll <pawel.moll@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
>> Cc: Kumar Gala <galak@codeaurora.org>
>> Cc: <devicetree@vger.kernel.org>
>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>> ---
>> .../devicetree/bindings/clock/exynos4-clock.txt | 37 ++++++++++++++++++++
>> .../devicetree/bindings/clock/exynos5250-clock.txt | 36 +++++++++++++++++++
>> 2 files changed, 73 insertions(+), 0 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>> index f5a5b19..0934e02 100644
>> --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>> +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>> @@ -15,6 +15,35 @@ Required Properties:
>>
>> - #clock-cells: should be 1.
>>
>> +- samsung,armclk-divider-table: when the frequency of the APLL is changed
>> + the divider clocks in CMU_CPU clock domain also need to be updated. These
>> + divider clocks have SoC specific divider clock output requirements for a
>> + specific APLL clock speeds. When APLL clock rate is changed, these divider
>> + clocks are reprogrammed with pre-determined values in order to maintain the
>> + SoC specific divider clock outputs. This property lists the divider values
>> + for divider clocks in the CMU_CPU block for supported APLL clock speeds.
>> + The format of each entry included in the arm-frequency-table should be
>> + as defined below
>
> As far as I understand, the relation is not between the APLL frequency
> and particular clocks in CPU domain, but rather between the latter and
> input clock to CPU domain, which is _after_ the two dividers (called
> DIV_CORE and DIV_CORE2 or ARM_DIV1 and ARM_DIV2), which is also exactly
> the output frequency of ARMCLK.
>
>> +
>> + - for Exynos4210 and Exynos4212 based platforms:
>> + cell #1: arm clock parent frequency
>
> Considering my comment above, this should be rather ARMCLK frequency.
The clocks SCLK_APLL, SCLK_HPM, ATCLK and PCLK_DBG have no relation to
the ARMCLK frequency. These clocks are directly derived from the PLL
clock and so it would not be correct to have them related to ARMCLK.
So, I see two solutions to this, first being preferred solution.
[A] Cell #1 should define PLL (parent of armclk) clock speed. Cell #2
and Cell #3 should define divider values for ARMCLK clock speed. The
hardware does support PLL frequency != ARMCLK frequency and so DT
binding should allow that (even though implementation in the linux
kernel does not use this feature). BTW, this was what was done in v2
of this series.
[B] Embedded this data with the code and don't get this from DT. The
reason for doing this is, these are SoC specific values and not board
specific. And when we are clear about what we want to put in DT, have
a provision to lookup DT first and if DT values are not found,
fallback on data embedded with the code.
Thanks,
Thomas.
>
>> + cell #2 ~ cell 9#: value of clock divider in the following order
>> + corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
>> + pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio.
>> +
>> + - for Exynos4412 based platforms:
>> + cell #1: expected arm clock parent frequency
>
> Ditto.
>
>> + cell #2 ~ cell #10: value of clock divider in the following order
>> + corem0_ratio, corem1_ratio, periph_ratio, atb_ratio,
>> + pclk_dbg_ratio, apll_ratio, copy_ratio, hpm_ratio, cores_ratio
>> +
>> +- samsung,armclk-cells: defines the number of cells in
>> + samsung,armclk-divider-table property. The value of this property depends on
>> + the SoC type.
>
> To follow conventions used by all other bindings with variable number of
> cells, the property should be called "#samsung,armclk-cells". AFAIK the
> "#" should be interpreted as "number of" and so accents the meaning of
> the property.
>
>> +
>> + - for Exynos4210 and Exynos4212: the value should be 9.
>> + - for Exynos4412: the value should be 10.
>> +
>> Each clock is assigned an identifier and client nodes can use this identifier
>> to specify the clock which they consume.
>>
>> @@ -28,6 +57,14 @@ Example 1: An example of a clock controller node is listed below.
>> compatible = "samsung,exynos4210-clock";
>> reg = <0x10030000 0x20000>;
>> #clock-cells = <1>;
>> +
>> + samsung,armclk-cells = <9>;
>> + samsung,armclk-divider-table = <1200000 3 7 3 4 1 7 5 0>,
>> + <1000000 3 7 3 4 1 7 4 0>,
>> + < 800000 3 7 3 3 1 7 3 0>,
>> + < 500000 3 7 3 3 1 7 3 0>,
>> + < 400000 3 7 3 3 1 7 3 0>,
>> + < 200000 1 3 1 1 1 0 3 0>;
>> };
>>
>> Example 2: UART controller node that consumes the clock generated by the clock
>> diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
>> index 536eacd..3d63d09 100644
>> --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
>> +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
>> @@ -13,6 +13,24 @@ Required Properties:
>
> Same comments apply to this file as well.
>
> Also, shouldn't you also extend exynos5420-clock.txt in the same way?
>
> Best regards,
> Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5
2014-05-26 6:05 ` Thomas Abraham
@ 2014-05-26 11:02 ` Tomasz Figa
0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2014-05-26 11:02 UTC (permalink / raw)
To: Thomas Abraham
Cc: cpufreq@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Mike Turquette, Shawn Guo, devicetree@vger.kernel.org,
rjw@rjwysocki.net, linux-samsung-soc@vger.kernel.org, Kukjin Kim,
Tomasz Figa, Lukasz Majewski, Viresh Kumar, Heiko Stübner,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
Thomas,
On 26.05.2014 08:05, Thomas Abraham wrote:
> Hi Tomasz,
>
> Thanks for your comments. Please see inline reply.
>
> On Sat, May 17, 2014 at 4:54 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> Hi Thomas,
>>
>> Please see my comments inline.
>>
>> On 14.05.2014 03:11, Thomas Abraham wrote:
>>> From; Thomas Abraham <thomas.ab@samsung.com>
>>>
>>> The clock blocks within the CMU_CPU clock domain are put together into a
>>> new composite clock type called the cpu clock. This clock type requires
>>> configuration data that will be atomically programmed in the multiple
>>> clock blocks encapsulated within the cpu clock type when the parent clock
>>> frequency is changed. This configuration data is held in the clock controller
>>> node. Update clock binding documentation about this configuration data format
>>> for Samsung Exynos4 and Exynos5 platforms.
>>>
>>> Cc: Tomasz Figa <t.figa@samsung.com>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>> Cc: Pawel Moll <pawel.moll@arm.com>
>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
>>> Cc: Kumar Gala <galak@codeaurora.org>
>>> Cc: <devicetree@vger.kernel.org>
>>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>>> ---
>>> .../devicetree/bindings/clock/exynos4-clock.txt | 37 ++++++++++++++++++++
>>> .../devicetree/bindings/clock/exynos5250-clock.txt | 36 +++++++++++++++++++
>>> 2 files changed, 73 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>>> index f5a5b19..0934e02 100644
>>> --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>>> +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
>>> @@ -15,6 +15,35 @@ Required Properties:
>>>
>>> - #clock-cells: should be 1.
>>>
>>> +- samsung,armclk-divider-table: when the frequency of the APLL is changed
>>> + the divider clocks in CMU_CPU clock domain also need to be updated. These
>>> + divider clocks have SoC specific divider clock output requirements for a
>>> + specific APLL clock speeds. When APLL clock rate is changed, these divider
>>> + clocks are reprogrammed with pre-determined values in order to maintain the
>>> + SoC specific divider clock outputs. This property lists the divider values
>>> + for divider clocks in the CMU_CPU block for supported APLL clock speeds.
>>> + The format of each entry included in the arm-frequency-table should be
>>> + as defined below
>>
>> As far as I understand, the relation is not between the APLL frequency
>> and particular clocks in CPU domain, but rather between the latter and
>> input clock to CPU domain, which is _after_ the two dividers (called
>> DIV_CORE and DIV_CORE2 or ARM_DIV1 and ARM_DIV2), which is also exactly
>> the output frequency of ARMCLK.
>>
>>> +
>>> + - for Exynos4210 and Exynos4212 based platforms:
>>> + cell #1: arm clock parent frequency
>>
>> Considering my comment above, this should be rather ARMCLK frequency.
>
> The clocks SCLK_APLL, SCLK_HPM, ATCLK and PCLK_DBG have no relation to
> the ARMCLK frequency. These clocks are directly derived from the PLL
> clock and so it would not be correct to have them related to ARMCLK.
Oh, right, the old driver was changing DIV_APLL, DIV_ATB and
DIV_PCLK_DBG as well. Somehow I was under an impression that we need to
care only about those dividers on the path after DIV_CORE and DIV_CORE2.
In this case the parent rate is the key here, although I'd call it "CPU
block parent rate (usually APLL)".
However this means that the trick with using DIV_CORE and DIV_CORE2 to
divide the rate of temporary parent clock is not enough, because DIV_ATB
is sourced directly from MOUT_CORE.
>
> So, I see two solutions to this, first being preferred solution.
>
> [A] Cell #1 should define PLL (parent of armclk) clock speed. Cell #2
> and Cell #3 should define divider values for ARMCLK clock speed. The
> hardware does support PLL frequency != ARMCLK frequency and so DT
> binding should allow that (even though implementation in the linux
> kernel does not use this feature). BTW, this was what was done in v2
> of this series.
>
> [B] Embedded this data with the code and don't get this from DT. The
> reason for doing this is, these are SoC specific values and not board
> specific. And when we are clear about what we want to put in DT, have
> a provision to lookup DT first and if DT values are not found,
> fallback on data embedded with the code.
Well, they are not that generic as they might appear. I've seen
different values for the same SoC in different vendor kernels, depending
on device the kernel was targeted for. Also they will likely differ
between SoC revisions.
However it might be a good idea indeed to keep the table in the code as
a first step to get the driver running without creating new DT bindings.
By the way, I'm not fully convinced if there is really a need for such
hardcoded look-up tables at all. Those divisors certainly look like they
are calculated based on some upper bounds for certain clocks and the
driver could simply find them out itself if those limits were provided.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
2014-05-14 14:33 ` Arnd Bergmann
@ 2014-07-08 5:15 ` Viresh Kumar
0 siblings, 0 replies; 58+ messages in thread
From: Viresh Kumar @ 2014-07-08 5:15 UTC (permalink / raw)
To: Arnd Bergmann, Rob Herring, Mike Turquette, Stephen Boyd
Cc: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
Lukasz Majewski, Kukjin Kim, Thomas Abraham, Heiko Stübner,
Rob Herring, Tomasz Figa, Rafael J. Wysocki,
cpufreq@vger.kernel.org, linux-samsung-soc, Thomas P Abraham,
Grant Likely, Shawn Guo
Hi Arnd/Rob/Mike et al,
We didn't conclude anything out of this thread and so kicking it
again as we need to close bindings to support cpufreq-cpu0
better for platforms not sharing clock lines across all CPUs.
https://lkml.org/lkml/2014/7/1/358
On 14 May 2014 20:03, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 14 May 2014 08:45:23 Rob Herring wrote:
>> We already have properties which indicate this driver can be used by a
>> platform: opp table and a clock for the cpu. If this information is
There can be platform drivers which also depend on these properties
and picking cpufreq-cpu0 on this basis doesn't look correct.
>> not sufficient to determine whether you can use this driver or not,
>> then you simply need to match against the platform. Perhaps the match
>> list should be a blacklist rather than a whitelist, so new platforms
>> work without a kernel change.
>
> We'd not only need a blacklist, but also a way to tell whether we
> want to use the cpu0 or the big/little implementation, which currently
> have indistinguishable bindings.
Correct and there can be other platform drivers which cannot use
cpufreq-cpu0 (though I am trying to force people to use cpufreq-cpu0
instead of a new driver).
Is something terribly wrong with having a property at 'cpus' node
which can point to the driver we want to use? Like:
cpus {
#address-cells = <1>;
#size-cells = <0>;
scaling-method = "cpufreq-cpu0"
cpu@0 {
....
};
....
};
Or if we can reuse compatibility string some way.
[Copying mail from Mike]
On 15 May 2014 02:46, Mike Turquette <mturquette@linaro.org> wrote:
> The hardware property that matters for cpufreq-cpu0 users is that a
> multi-core CPU uses a single clock input to scale frequency across all
> of the cores in that cluster. So an accurate description is:
>
> scaling-method = "clock-ganged"; //hardware-people-speak
>
> Or,
>
> scaling-method = "clock-shared"; //software-people-speak
>
> Versus independently scalable CPUs in an SMP cluster:
>
> scaling-method = "independent"; //x86, Krait, etc.
>
> Or perhaps instead of "independent" at the parent "cpus" node we would
> put the following in each cpu@N node:
>
> scaling-method = "clock";
>
> Or "psci" or "acpi" or whatever.
>
> Thought exercise: for Hyperthreaded(tm) CPUs with 2 virtual cores for
> every hard CPU (and multiple CPUs in a cluster):
>
> scaling-method = "paired";
>
> Or more simply, "hyperthreaded".
Probably we have mixed both the problems. We have two problems to
solve:
- Identifying which driver to probe for a platform, earlier explanation
I tried to gave were around that..
- Identifying if clocks are shared between CPUs? If yes which ones?
Probably Mike's suggestions were around this second problem, but
I still couldn't make out which CPUs share clock line from his
examples.
Please see if we can close this thread soon... Few platforms are waiting
to reuse cpufreq-cpu0 :)
--
viresh
^ permalink raw reply [flat|nested] 58+ messages in thread
end of thread, other threads:[~2014-07-08 5:15 UTC | newest]
Thread overview: 58+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-14 1:11 [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Thomas Abraham
2014-05-14 1:11 ` [PATCH v4 1/8] cpufreq: cpufreq-cpu0: allow use of optional boost mode frequencies Thomas Abraham
2014-05-14 3:46 ` Viresh Kumar
2014-05-14 6:17 ` Lukasz Majewski
2014-05-14 6:20 ` Viresh Kumar
2014-05-14 13:43 ` Thomas Abraham
2014-05-14 13:50 ` Viresh Kumar
2014-05-14 14:18 ` Thomas Abraham
2014-05-14 14:20 ` Viresh Kumar
2014-05-14 1:11 ` [PATCH v4 2/8] clk: samsung: change scope of samsung clock lock to global Thomas Abraham
2014-05-14 3:50 ` Viresh Kumar
2014-05-14 13:26 ` Thomas Abraham
2014-05-16 12:30 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 3/8] clk: samsung: add infrastructure to register cpu clocks Thomas Abraham
2014-05-15 18:18 ` Doug Anderson
2014-05-15 19:17 ` Heiko Stübner
2014-05-15 19:36 ` Doug Anderson
2014-05-15 20:12 ` Heiko Stübner
2014-05-15 20:26 ` Doug Anderson
2014-05-16 4:55 ` Thomas Abraham
2014-05-16 17:17 ` Tomasz Figa
2014-05-23 14:41 ` Thomas Abraham
2014-05-23 14:50 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 4/8] Documentation: devicetree: add cpu clock configuration data binding for Exynos4/5 Thomas Abraham
2014-05-16 23:24 ` Tomasz Figa
2014-05-17 0:00 ` Tomasz Figa
2014-05-26 6:05 ` Thomas Abraham
2014-05-26 11:02 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 5/8] clk: exynos: use cpu-clock provider type to represent arm clock Thomas Abraham
2014-05-14 21:37 ` Mike Turquette
2014-05-15 7:48 ` Thomas Abraham
2014-05-15 8:10 ` Lukasz Majewski
2014-05-15 9:59 ` Thomas Abraham
2014-05-16 5:14 ` Thomas Abraham
2014-05-16 23:57 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 6/8] ARM: dts: Exynos: add cpu nodes, opp and cpu clock configuration data Thomas Abraham
2014-05-16 23:16 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 7/8] ARM: Exynos: switch to using generic cpufreq-cpu0 driver Thomas Abraham
2014-05-14 12:50 ` Arnd Bergmann
2014-05-14 13:05 ` Viresh Kumar
2014-05-14 13:11 ` Heiko Stübner
2014-05-14 13:14 ` Viresh Kumar
2014-05-14 13:18 ` Arnd Bergmann
2014-05-14 13:45 ` Rob Herring
2014-05-14 14:33 ` Arnd Bergmann
2014-07-08 5:15 ` Viresh Kumar
2014-05-14 14:03 ` Thomas Abraham
2014-05-14 14:09 ` Sudeep Holla
2014-05-14 14:09 ` Thomas Abraham
2014-05-17 0:04 ` Tomasz Figa
2014-05-14 1:11 ` [PATCH v4 8/8] cpufreq: exynos: remove all exynos specific cpufreq driver support Thomas Abraham
2014-05-14 3:57 ` Viresh Kumar
2014-05-14 7:20 ` Lukasz Majewski
2014-05-14 13:53 ` Thomas Abraham
2014-05-14 12:51 ` [PATCH v4 0/8] cpufreq: use cpufreq-cpu0 driver for exynos based platforms Arnd Bergmann
2014-05-14 13:07 ` Viresh Kumar
2014-05-14 13:16 ` Arnd Bergmann
2014-05-17 0:14 ` Tomasz Figa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).