* [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx
@ 2017-11-30 13:40 Gregory CLEMENT
2017-11-30 13:40 ` [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes Gregory CLEMENT
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Gregory CLEMENT @ 2017-11-30 13:40 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette, linux-clk, linux-kernel
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Thomas Petazzoni, linux-arm-kernel,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits
Hi,
This small series is needed to use DVFS on Armada 37xx. When DVFS is
enabled the CPU clock setting is done using an other set of registers
from the North Bridge Power Management block.
The series adds the possibility to modify the CPU frequency using the
associate load level matching the target frequency. However
configuring the frequencies for each load is done by the cpufreq
driver submitted in a separate series.
Obviously having both series (cpufreq and clk) is needed to support
DVFS on Armada 37xx, but there is no dependencies between the series
(for building or at runtime).
Thanks,
Gregory
Gregory CLEMENT (3):
clk: mvebu: armada-37xx-periph: cosmetic changes
clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS
clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
drivers/clk/mvebu/armada-37xx-periph.c | 310 +++++++++++++++++++++++++++++++--
1 file changed, 293 insertions(+), 17 deletions(-)
--
2.15.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
@ 2017-11-30 13:40 ` Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-11-30 13:40 ` [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS Gregory CLEMENT
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Gregory CLEMENT @ 2017-11-30 13:40 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette, linux-clk, linux-kernel
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Thomas Petazzoni, linux-arm-kernel,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits
This patches fixes few cosmetic issues such as alignment, blank lines
and required space.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c
index cecb0fdfaef6..6dae21ced18a 100644
--- a/drivers/clk/mvebu/armada-37xx-periph.c
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
@@ -79,6 +79,7 @@ static const struct clk_div_table clk_table2[] = {
{ .val = 1, .div = 4, },
{ .val = 0, .div = 0, }, /* last entry */
};
+
static const struct clk_ops clk_double_div_ops;
#define PERIPH_GATE(_name, _bit) \
@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
-static struct clk_periph_data data_nb[] ={
+static struct clk_periph_data data_nb[] = {
REF_CLK_FULL_DD(mmc),
REF_CLK_FULL_DD(sata_host),
REF_CLK_FULL_DD(sec_at),
@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem *reg, int shift)
}
static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+ unsigned long parent_rate)
{
struct clk_double_div *double_div = to_clk_double_div(hw);
unsigned int div;
@@ -303,6 +304,7 @@ static const struct of_device_id armada_3700_periph_clock_of_match[] = {
.data = data_sb, },
{ }
};
+
static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
void __iomem *reg, spinlock_t *lock,
struct device *dev, struct clk_hw **hw)
@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
}
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
- data->num_parents, mux_hw,
- mux_ops, rate_hw, rate_ops,
- gate_hw, gate_ops, CLK_IGNORE_UNUSED);
+ data->num_parents, mux_hw,
+ mux_ops, rate_hw, rate_ops,
+ gate_hw, gate_ops, CLK_IGNORE_UNUSED);
if (IS_ERR(*hw))
return PTR_ERR(*hw);
@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
if (armada_3700_add_composite_clk(&data[i], reg,
&driver_data->lock, dev, hw))
dev_err(dev, "Can't register periph clock %s\n",
- data[i].name);
-
+ data[i].name);
}
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
- driver_data->hw_data);
+ driver_data->hw_data);
if (ret) {
for (i = 0; i < num_periph; i++)
clk_hw_unregister(driver_data->hw_data->hws[i]);
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
2017-11-30 13:40 ` [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes Gregory CLEMENT
@ 2017-11-30 13:40 ` Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-11-30 13:40 ` [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks Gregory CLEMENT
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Gregory CLEMENT @ 2017-11-30 13:40 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette, linux-clk, linux-kernel
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Thomas Petazzoni, linux-arm-kernel,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits
When DVFS will be enabled then the cpu clk will use a different set of
register at run time. That means that we won't be able to use the common
callback and need to use our own ones.
This patch prepares this change by switching on our own set of callbacks
without modifying the behavior of the clocks.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++----
1 file changed, 73 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c
index 6dae21ced18a..ef725ec73c93 100644
--- a/drivers/clk/mvebu/armada-37xx-periph.c
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
@@ -46,7 +46,17 @@ struct clk_double_div {
u8 shift2;
};
+struct clk_pm_cpu {
+ struct clk_hw hw;
+ void __iomem *reg_mux;
+ u8 shift_mux;
+ u32 mask_mux;
+ void __iomem *reg_div;
+ u8 shift_div;
+};
+
#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
+#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
struct clk_periph_data {
const char *name;
@@ -55,6 +65,7 @@ struct clk_periph_data {
struct clk_hw *mux_hw;
struct clk_hw *rate_hw;
struct clk_hw *gate_hw;
+ struct clk_hw *muxrate_hw;
bool is_double_div;
};
@@ -81,6 +92,7 @@ static const struct clk_div_table clk_table2[] = {
};
static const struct clk_ops clk_double_div_ops;
+static const struct clk_ops clk_pm_cpu_ops;
#define PERIPH_GATE(_name, _bit) \
struct clk_gate gate_##_name = { \
@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \
} \
};
+#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \
+struct clk_pm_cpu muxrate_##_name = { \
+ .reg_mux = (void *)TBG_SEL, \
+ .mask_mux = 3, \
+ .shift_mux = _shift1, \
+ .reg_div = (void *)_reg, \
+ .shift_div = _shift2, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_pm_cpu_ops, \
+ } \
+};
+
#define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
static PERIPH_GATE(_name, _bit); \
static PERIPH_MUX(_name, _shift); \
@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1, _table);
static PERIPH_GATE(_name, _bit); \
static PERIPH_DIV(_name, _reg, _shift, _table);
-#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \
-static PERIPH_MUX(_name, _shift); \
-static PERIPH_DIV(_name, _reg, _shift_div, _table);
-
#define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
static PERIPH_MUX(_name, _shift); \
static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
.rate_hw = &rate_##_name.hw, \
}
-#define REF_CLK_MUX_DIV(_name) \
+#define REF_CLK_PM_CPU(_name) \
{ .name = #_name, \
.parent_names = (const char *[]){ "TBG-A-P", \
"TBG-B-P", "TBG-A-S", "TBG-B-S"}, \
.num_parents = 4, \
- .mux_hw = &mux_##_name.hw, \
- .rate_hw = &rate_##_name.hw, \
+ .muxrate_hw = &muxrate_##_name.hw, \
}
#define REF_CLK_MUX_DD(_name) \
@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12);
PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
-PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
+static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
static struct clk_periph_data data_nb[] = {
REF_CLK_FULL_DD(mmc),
@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[] = {
REF_CLK_FULL(trace),
REF_CLK_FULL(counter),
REF_CLK_FULL_DD(eip97),
- REF_CLK_MUX_DIV(cpu),
+ REF_CLK_PM_CPU(cpu),
{ },
};
@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_div_ops = {
.recalc_rate = clk_double_div_recalc_rate,
};
+static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
+{
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ int num_parents = clk_hw_get_num_parents(hw);
+ u32 val;
+
+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
+ val &= pm_cpu->mask_mux;
+
+ if (val >= num_parents)
+ return -EINVAL;
+
+ return val;
+}
+
+static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ unsigned int div;
+
+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
+
+ return DIV_ROUND_UP_ULL((u64)parent_rate, div);
+}
+
+static const struct clk_ops clk_pm_cpu_ops = {
+ .get_parent = clk_pm_cpu_get_parent,
+ .recalc_rate = clk_pm_cpu_recalc_rate,
+};
+
static const struct of_device_id armada_3700_periph_clock_of_match[] = {
{ .compatible = "marvell,armada-3700-periph-clock-nb",
.data = data_nb, },
@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
}
}
+ if (data->muxrate_hw) {
+ struct clk_pm_cpu *pmcpu_clk;
+ struct clk_hw *muxrate_hw = data->muxrate_hw;
+
+ pmcpu_clk = to_clk_pm_cpu(muxrate_hw);
+ pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
+ pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
+
+ mux_hw = muxrate_hw;
+ rate_hw = muxrate_hw;
+ mux_ops = muxrate_hw->init->ops;
+ rate_ops = muxrate_hw->init->ops;
+ }
+
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
data->num_parents, mux_hw,
mux_ops, rate_hw, rate_ops,
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
2017-11-30 13:40 ` [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes Gregory CLEMENT
2017-11-30 13:40 ` [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS Gregory CLEMENT
@ 2017-11-30 13:40 ` Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-12-21 10:53 ` [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
2017-12-21 23:13 ` Stephen Boyd
4 siblings, 1 reply; 10+ messages in thread
From: Gregory CLEMENT @ 2017-11-30 13:40 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette, linux-clk, linux-kernel
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Thomas Petazzoni, linux-arm-kernel,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits
When DVFS is enabled the CPU clock setting is done using an other set of
registers.
These Power Management registers are exposed through a syscon as they
will also be used by other drivers such as the cpufreq.
This patch add the possibility to modify the CPU frequency using the
associate load level matching the target frequency. Then all the
frequency switch is handle by the hardware.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/clk/mvebu/armada-37xx-periph.c | 219 ++++++++++++++++++++++++++++++++-
1 file changed, 215 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c
index ef725ec73c93..0fd7a671a76d 100644
--- a/drivers/clk/mvebu/armada-37xx-periph.c
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
@@ -21,9 +21,11 @@
*/
#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#define TBG_SEL 0x0
@@ -33,6 +35,26 @@
#define CLK_SEL 0x10
#define CLK_DIS 0x14
+#define LOAD_LEVEL_NR 4
+
+#define ARMADA_37XX_NB_L0L1 0x18
+#define ARMADA_37XX_NB_L2L3 0x1C
+#define ARMADA_37XX_NB_TBG_DIV_OFF 13
+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
+#define ARMADA_37XX_NB_CLK_SEL_OFF 11
+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
+#define ARMADA_37XX_NB_TBG_SEL_OFF 9
+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
+#define ARMADA_37XX_NB_CONFIG_SHIFT 16
+#define ARMADA_37XX_NB_DYN_MOD 0x24
+#define ARMADA_37XX_NB_DFS_EN 31
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
+#define ARMADA_37XX_DVFS_LOAD_0 0
+#define ARMADA_37XX_DVFS_LOAD_1 1
+#define ARMADA_37XX_DVFS_LOAD_2 2
+#define ARMADA_37XX_DVFS_LOAD_3 3
+
struct clk_periph_driver_data {
struct clk_hw_onecell_data *hw_data;
spinlock_t lock;
@@ -53,6 +75,7 @@ struct clk_pm_cpu {
u32 mask_mux;
void __iomem *reg_div;
u8 shift_div;
+ struct regmap *nb_pm_base;
};
#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_div_ops = {
.recalc_rate = clk_double_div_recalc_rate,
};
+static void armada_3700_pm_dvfs_update_regs(unsigned int load_level,
+ unsigned int *reg,
+ unsigned int *offset)
+{
+ if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
+ *reg = ARMADA_37XX_NB_L0L1;
+ else
+ *reg = ARMADA_37XX_NB_L2L3;
+
+ if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
+ load_level == ARMADA_37XX_DVFS_LOAD_2)
+ *offset += ARMADA_37XX_NB_CONFIG_SHIFT;
+}
+
+static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base)
+{
+ unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD;
+
+ if (IS_ERR(base))
+ return false;
+
+ regmap_read(base, reg, &val);
+
+ return !!(val & BIT(ARMADA_37XX_NB_DFS_EN));
+}
+
+static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base)
+{
+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
+ unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF;
+ unsigned int load_level, div;
+
+ /*
+ * This function is always called after the function
+ * armada_3700_pm_dvfs_is_enabled, so no need to check again
+ * if the base is valid.
+ */
+ regmap_read(base, reg, &load_level);
+
+ /*
+ * The register and the offset inside this register accessed to
+ * read the current divider depend on the load level
+ */
+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
+
+ regmap_read(base, reg, &div);
+
+ return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK;
+}
+
+static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base)
+{
+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
+ unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF;
+ unsigned int load_level, sel;
+
+ /*
+ * This function is always called after the function
+ * armada_3700_pm_dvfs_is_enabled, so no need to check again
+ * if the base is valid
+ */
+ regmap_read(base, reg, &load_level);
+
+ /*
+ * The register and the offset inside this register accessed to
+ * read the current divider depend on the load level
+ */
+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
+
+ regmap_read(base, reg, &sel);
+
+ return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK;
+}
+
static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
- val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
- val &= pm_cpu->mask_mux;
+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
+ val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base);
+ } else {
+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
+ val &= pm_cpu->mask_mux;
+ }
if (val >= num_parents)
return -EINVAL;
@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
return val;
}
+static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ struct regmap *base = pm_cpu->nb_pm_base;
+ int load_level;
+
+ /*
+ * We set the clock parent only if the DVFS is available but
+ * not enabled.
+ */
+ if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
+ return -EINVAL;
+
+ /* Set the parent clock for all the load level */
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
+ unsigned int reg, mask, val,
+ offset = ARMADA_37XX_NB_TBG_SEL_OFF;
+
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
+
+ val = index << offset;
+ mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
+ regmap_update_bits(base, reg, mask, val);
+ }
+ return 0;
+}
+
static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
unsigned int div;
- div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
-
+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base))
+ div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base);
+ else
+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
}
+static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ struct regmap *base = pm_cpu->nb_pm_base;
+ unsigned int div = *parent_rate / rate;
+ unsigned int load_level;
+ /* only available when DVFS is enabled */
+ if (!armada_3700_pm_dvfs_is_enabled(base))
+ return -EINVAL;
+
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
+ unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF;
+
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
+
+ regmap_read(base, reg, &val);
+
+ val >>= offset;
+ val &= ARMADA_37XX_NB_TBG_DIV_MASK;
+ if (val == div)
+ /*
+ * We found a load level matching the target
+ * divider, switch to this load level and
+ * return.
+ */
+ return *parent_rate / div;
+ }
+
+ /* We didn't find any valid divider */
+ return -EINVAL;
+}
+
+static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ struct regmap *base = pm_cpu->nb_pm_base;
+ unsigned int div = parent_rate / rate;
+ unsigned int load_level;
+
+ /* only available when DVFS is enabled */
+ if (!armada_3700_pm_dvfs_is_enabled(base))
+ return -EINVAL;
+
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
+ unsigned int reg, mask, val,
+ offset = ARMADA_37XX_NB_TBG_DIV_OFF;
+
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
+
+ regmap_read(base, reg, &val);
+ val >>= offset;
+ val &= ARMADA_37XX_NB_TBG_DIV_MASK;
+
+ if (val == div) {
+ /*
+ * We found a load level matching the target
+ * divider, switch to this load level and
+ * return.
+ */
+ reg = ARMADA_37XX_NB_CPU_LOAD;
+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
+ regmap_update_bits(base, reg, mask, load_level);
+
+ return rate;
+ }
+ }
+
+ /* We didn't find any valid divider */
+ return -EINVAL;
+}
+
static const struct clk_ops clk_pm_cpu_ops = {
.get_parent = clk_pm_cpu_get_parent,
+ .set_parent = clk_pm_cpu_set_parent,
+ .round_rate = clk_pm_cpu_round_rate,
+ .set_rate = clk_pm_cpu_set_rate,
.recalc_rate = clk_pm_cpu_recalc_rate,
};
@@ -418,6 +626,9 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
rate_hw = muxrate_hw;
mux_ops = muxrate_hw->init->ops;
rate_ops = muxrate_hw->init->ops;
+
+ pmcpu_clk->nb_pm_base =
+ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
}
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
--
2.15.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
` (2 preceding siblings ...)
2017-11-30 13:40 ` [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks Gregory CLEMENT
@ 2017-12-21 10:53 ` Gregory CLEMENT
2017-12-21 23:13 ` Stephen Boyd
4 siblings, 0 replies; 10+ messages in thread
From: Gregory CLEMENT @ 2017-12-21 10:53 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette
Cc: linux-clk, linux-kernel, Thomas Petazzoni, Andrew Lunn,
Jason Cooper, Hua Jing, Antoine Tenart, Nadav Haklai, Victor Gu,
Neta Zur Hershkovits, Miquèl Raynal, Marcin Wojtas,
Wilson Ding, linux-arm-kernel, Sebastian Hesselbarth
Hello,
On jeu., nov. 30 2017, Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi,
>
> This small series is needed to use DVFS on Armada 37xx. When DVFS is
> enabled the CPU clock setting is done using an other set of registers
> from the North Bridge Power Management block.
>
> The series adds the possibility to modify the CPU frequency using the
> associate load level matching the target frequency. However
> configuring the frequencies for each load is done by the cpufreq
> driver submitted in a separate series.
>
> Obviously having both series (cpufreq and clk) is needed to support
> DVFS on Armada 37xx, but there is no dependencies between the series
> (for building or at runtime).
I sent this series 3 weeks ago and I didn't have any feedback on
it. Does it mean that the series is OK for you and that you wait for a
PR for it?
Thanks,
Gregory
>
> Gregory CLEMENT (3):
> clk: mvebu: armada-37xx-periph: cosmetic changes
> clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS
> clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
>
> drivers/clk/mvebu/armada-37xx-periph.c | 310 +++++++++++++++++++++++++++++++--
> 1 file changed, 293 insertions(+), 17 deletions(-)
>
> --
> 2.15.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes
2017-11-30 13:40 ` [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes Gregory CLEMENT
@ 2017-12-21 23:12 ` Stephen Boyd
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2017-12-21 23:12 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Mike Turquette, linux-clk, linux-kernel, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits
On 11/30, Gregory CLEMENT wrote:
> This patches fixes few cosmetic issues such as alignment, blank lines
> and required space.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS
2017-11-30 13:40 ` [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS Gregory CLEMENT
@ 2017-12-21 23:12 ` Stephen Boyd
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2017-12-21 23:12 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Mike Turquette, linux-clk, linux-kernel, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits
On 11/30, Gregory CLEMENT wrote:
> When DVFS will be enabled then the cpu clk will use a different set of
> register at run time. That means that we won't be able to use the common
> callback and need to use our own ones.
>
> This patch prepares this change by switching on our own set of callbacks
> without modifying the behavior of the clocks.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
2017-11-30 13:40 ` [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks Gregory CLEMENT
@ 2017-12-21 23:12 ` Stephen Boyd
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2017-12-21 23:12 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Mike Turquette, linux-clk, linux-kernel, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits
On 11/30, Gregory CLEMENT wrote:
> When DVFS is enabled the CPU clock setting is done using an other set of
> registers.
>
> These Power Management registers are exposed through a syscon as they
> will also be used by other drivers such as the cpufreq.
>
> This patch add the possibility to modify the CPU frequency using the
> associate load level matching the target frequency. Then all the
> frequency switch is handle by the hardware.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
Applied to clk-next + a small fix to regmap getting to make it
shorter.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
` (3 preceding siblings ...)
2017-12-21 10:53 ` [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
@ 2017-12-21 23:13 ` Stephen Boyd
2017-12-22 10:02 ` Gregory CLEMENT
4 siblings, 1 reply; 10+ messages in thread
From: Stephen Boyd @ 2017-12-21 23:13 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Mike Turquette, linux-clk, linux-kernel, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits
On 11/30, Gregory CLEMENT wrote:
> Hi,
>
> This small series is needed to use DVFS on Armada 37xx. When DVFS is
> enabled the CPU clock setting is done using an other set of registers
> from the North Bridge Power Management block.
>
> The series adds the possibility to modify the CPU frequency using the
> associate load level matching the target frequency. However
> configuring the frequencies for each load is done by the cpufreq
> driver submitted in a separate series.
>
> Obviously having both series (cpufreq and clk) is needed to support
> DVFS on Armada 37xx, but there is no dependencies between the series
> (for building or at runtime).
>
Are you relying on the clk API returning an error to detect if
DVFS is present or not? Just curious why that part of the code
was there.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx
2017-12-21 23:13 ` Stephen Boyd
@ 2017-12-22 10:02 ` Gregory CLEMENT
0 siblings, 0 replies; 10+ messages in thread
From: Gregory CLEMENT @ 2017-12-22 10:02 UTC (permalink / raw)
To: Stephen Boyd
Cc: Mike Turquette, linux-clk, linux-kernel, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits
Hi Stephen,
On jeu., déc. 21 2017, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 11/30, Gregory CLEMENT wrote:
>> Hi,
>>
>> This small series is needed to use DVFS on Armada 37xx. When DVFS is
>> enabled the CPU clock setting is done using an other set of registers
>> from the North Bridge Power Management block.
>>
>> The series adds the possibility to modify the CPU frequency using the
>> associate load level matching the target frequency. However
>> configuring the frequencies for each load is done by the cpufreq
>> driver submitted in a separate series.
>>
>> Obviously having both series (cpufreq and clk) is needed to support
>> DVFS on Armada 37xx, but there is no dependencies between the series
>> (for building or at runtime).
>>
>
> Are you relying on the clk API returning an error to detect if
> DVFS is present or not? Just curious why that part of the code
> was there.
The cpufreq framework rely on the clk framwork to setup the clk
frequency of the CPU. For this hardware when DVFS is enabled the we
don't directly control the frequency of the CPUs but the "load
level". And it is during the initialization that we associate CPU
frequency to a load level.
The clk part is there to setup this load level for the hardware but by
still using the frequency as an entry point as it was what is expected
by the kernel. So cpufreq will ask a frequency depending of its policy,
then the clk driver will setup the load level matching this frequency.
And to answer your specific question we don't rely on the clk API
returning an error to detect if DVFS is present or not. For this we
directly read the DVFS bit exposed through the syscon.
Gregory
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2017-12-22 10:02 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-30 13:40 [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
2017-11-30 13:40 ` [PATCH 1/3] clk: mvebu: armada-37xx-periph: cosmetic changes Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-11-30 13:40 ` [PATCH 2/3] clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-11-30 13:40 ` [PATCH 3/3] clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks Gregory CLEMENT
2017-12-21 23:12 ` Stephen Boyd
2017-12-21 10:53 ` [PATCH 0/3] Add DVFS support on CPU clock for Armada 37xx Gregory CLEMENT
2017-12-21 23:13 ` Stephen Boyd
2017-12-22 10:02 ` Gregory CLEMENT
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).