* [PATCH 0/3] Renesas R8A7743 CPG/MSSR clock support
@ 2016-10-05 20:50 ` Sergei Shtylyov
0 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-05 20:50 UTC (permalink / raw)
To: mturquette-rdvid1DuHRBWk0Htik3J/w,
linux-clk-u79uwXL29TY76Z2rM5mHXA, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA
Hello.
Here's the set of 3 patches against the 'clk-next' branch of CLK group's
'linux.git' repo. The R8A7743 SoC support will be posted separately later --
this series depend on the Kconfig variable introduced there, however, the DTs
in that series will depend on the patch #2 of this series...
[1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
[2/3] ARM: shmobile: r8a7743: add CPG clock index macros
[3/3] clk: renesas: cpg-mssr: add R8A7743 support
MBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 0/3] Renesas R8A7743 CPG/MSSR clock support
@ 2016-10-05 20:50 ` Sergei Shtylyov
0 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-05 20:50 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd, robh+dt, mark.rutland, devicetree
Cc: linux-renesas-soc
Hello.
Here's the set of 3 patches against the 'clk-next' branch of CLK group's
'linux.git' repo. The R8A7743 SoC support will be posted separately later --
this series depend on the Kconfig variable introduced there, however, the DTs
in that series will depend on the patch #2 of this series...
[1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
[2/3] ARM: shmobile: r8a7743: add CPG clock index macros
[3/3] clk: renesas: cpg-mssr: add R8A7743 support
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:50 ` Sergei Shtylyov
(?)
@ 2016-10-05 20:52 ` Sergei Shtylyov
2016-10-19 8:57 ` Geert Uytterhoeven
2016-10-26 12:17 ` Geert Uytterhoeven
-1 siblings, 2 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-05 20:52 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
and Software Reset support code, using the CPG/MSSR driver core.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
drivers/clk/renesas/rcar-gen2-cpg.c | 377 ++++++++++++++++++++++++++++++++++++
drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
2 files changed, 419 insertions(+)
Index: renesas/drivers/clk/renesas/rcar-gen2-cpg.c
===================================================================
--- /dev/null
+++ renesas/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,377 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_MASK (0x1f << 8)
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+ u32 value;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock. Register it as a
+ * fixed factor clock for now as there's no generic multiplier
+ * clock implementation and we currently have no need to change
+ * the multiplier value.
+ */
+ value = readl(base + CPG_PLL0CR);
+ mult = (((value >> 24) & 0x7f) + 1);
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+/*
+ * Reset register definitions.
+ */
+#define MODEMR 0xe6160060
+
+u32 __init rcar_gen2_read_modemr(void)
+{
+ void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+ u32 mode;
+
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+
+ return mode;
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config)
+{
+ cpg_pll_config = config;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
Index: renesas/drivers/clk/renesas/rcar-gen2-cpg.h
===================================================================
--- /dev/null
+++ renesas/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,42 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+};
+
+u32 rcar_gen2_read_modemr(void);
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config);
+
+#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros
2016-10-05 20:50 ` Sergei Shtylyov
(?)
(?)
@ 2016-10-05 20:54 ` Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
-1 siblings, 2 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-05 20:54 UTC (permalink / raw)
To: mturquette, sboyd, robh+dt, mark.rutland, devicetree, linux-renesas-soc
Cc: linux-clk
Add macros usable by the device tree sources to reference the R8A7743 CPG
clocks by index.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
include/dt-bindings/clock/r8a7743-cpg-mssr.h | 43 +++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
Index: renesas/include/dt-bindings/clock/r8a7743-cpg-mssr.h
===================================================================
--- /dev/null
+++ renesas/include/dt-bindings/clock/r8a7743-cpg-mssr.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a7743 CPG Core Clocks */
+#define R8A7743_CLK_Z 0
+#define R8A7743_CLK_ZG 1
+#define R8A7743_CLK_ZTR 2
+#define R8A7743_CLK_ZTRD2 3
+#define R8A7743_CLK_ZT 4
+#define R8A7743_CLK_ZX 5
+#define R8A7743_CLK_ZS 6
+#define R8A7743_CLK_HP 7
+#define R8A7743_CLK_B 8
+#define R8A7743_CLK_LB 9
+#define R8A7743_CLK_P 10
+#define R8A7743_CLK_CL 11
+#define R8A7743_CLK_M2 12
+#define R8A7743_CLK_ZB3 13
+#define R8A7743_CLK_ZB3D2 14
+#define R8A7743_CLK_DDR 15
+#define R8A7743_CLK_SDH 16
+#define R8A7743_CLK_SD0 17
+#define R8A7743_CLK_SD2 18
+#define R8A7743_CLK_SD3 19
+#define R8A7743_CLK_MMC0 20
+#define R8A7743_CLK_MP 21
+#define R8A7743_CLK_QSPI 22
+#define R8A7743_CLK_CP 23
+#define R8A7743_CLK_RCAN 24
+#define R8A7743_CLK_R 25
+#define R8A7743_CLK_OSC 26
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7743_CPG_MSSR_H__ */
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 3/3] clk: renesas: cpg-mssr: add R8A7743 support
2016-10-05 20:50 ` Sergei Shtylyov
` (2 preceding siblings ...)
(?)
@ 2016-10-05 20:55 ` Sergei Shtylyov
-1 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-05 20:55 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add RZ/G1M (R8A7743) Clock Pulse Generator / Module Standby and Software
Reset support, using the CPG/MSSR driver core and the common R-Car Gen2
(and RZ/G) code.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
drivers/clk/renesas/Kconfig | 1
drivers/clk/renesas/Makefile | 1
drivers/clk/renesas/r8a7743-cpg-mssr.c | 268 +++++++++++++++++++++++++++++++++
drivers/clk/renesas/renesas-cpg-mssr.c | 6
drivers/clk/renesas/renesas-cpg-mssr.h | 1
5 files changed, 277 insertions(+)
Index: renesas/drivers/clk/renesas/Kconfig
===================================================================
--- renesas.orig/drivers/clk/renesas/Kconfig
+++ renesas/drivers/clk/renesas/Kconfig
@@ -1,5 +1,6 @@
config CLK_RENESAS_CPG_MSSR
bool
+ default y if ARCH_R8A7743
default y if ARCH_R8A7795
default y if ARCH_R8A7796
Index: renesas/drivers/clk/renesas/Makefile
===================================================================
--- renesas.orig/drivers/clk/renesas/Makefile
+++ renesas/drivers/clk/renesas/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7743) += r8a7743-cpg-mssr.o rcar-gen2-cpg.o
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o
Index: renesas/drivers/clk/renesas/r8a7743-cpg-mssr.c
===================================================================
--- /dev/null
+++ renesas/drivers/clk/renesas/r8a7743-cpg-mssr.c
@@ -0,0 +1,268 @@
+/*
+ * r8a7743 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7743_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7743_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7743_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("lb", R8A7743_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
+ DEF_BASE("sdh", R8A7743_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7743_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7743_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("zg", R8A7743_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7743_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7743_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7743_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7743_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("p", R8A7743_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7743_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7743_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7743_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7743_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7743_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7743_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7743_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7743_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7743_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7743_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7743_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7743_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7743_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7743_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7743_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7743_CLK_P),
+ DEF_MOD("3dg", 112, R8A7743_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7743_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7743_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7743_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7743_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7743_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7743_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7743_CLK_ZS),
+ DEF_MOD("vsp1-sy", 131, R8A7743_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7743_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7743_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7743_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7743_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7743_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7743_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7743_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7743_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7743_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7743_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7743_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7743_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7743_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7743_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7743_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7743_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7743_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7743_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7743_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7743_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7743_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7743_CLK_HP),
+ DEF_MOD("irqc", 407, R8A7743_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7743_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A7743_CLK_HP),
+ DEF_MOD("audio-dmac1", 501, R8A7743_CLK_HP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7743_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7743_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7743_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7743_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7743_CLK_P),
+ DEF_MOD("scif4", 715, R8A7743_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7743_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7743_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7743_CLK_P),
+ DEF_MOD("scif2", 719, R8A7743_CLK_P),
+ DEF_MOD("scif1", 720, R8A7743_CLK_P),
+ DEF_MOD("scif0", 721, R8A7743_CLK_P),
+ DEF_MOD("du1", 723, R8A7743_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7743_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7743_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7743_CLK_ZX),
+ DEF_MOD("vin2", 809, R8A7743_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7743_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7743_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7743_CLK_HP),
+ DEF_MOD("ether", 813, R8A7743_CLK_P),
+ DEF_MOD("sata1", 814, R8A7743_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7743_CLK_ZS),
+ DEF_MOD("gpio7", 904, R8A7743_CLK_CP),
+ DEF_MOD("gpio6", 905, R8A7743_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7743_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7743_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7743_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7743_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7743_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7743_CLK_CP),
+ DEF_MOD("can1", 915, R8A7743_CLK_P),
+ DEF_MOD("can0", 916, R8A7743_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7743_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7743_CLK_HP),
+ DEF_MOD("i2c6", 926, R8A7743_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7743_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7743_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7743_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7743_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7743_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7743_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7743_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7743_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7743_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7743_CLK_MP),
+};
+
+static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL2
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x 1 x172/2 x208/2 x106
+ * 0 0 1 15 x 1 x172/2 x208/2 x88
+ * 0 1 0 20 x 1 x130/2 x156/2 x80
+ * 0 1 1 20 x 1 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.6 indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult */
+ { 1, 208, 106, },
+ { 1, 208, 88, },
+ { 1, 156, 80, },
+ { 1, 156, 66, },
+ { 2, 240, 122, },
+ { 2, 240, 102, },
+ { 2, 208, 106, },
+ { 2, 208, 88, },
+};
+
+static int __init r8a7743_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode = rcar_gen2_read_modemr();
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen2_cpg_init(cpg_pll_config);
+}
+
+const struct cpg_mssr_info r8a7743_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7743_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7743_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7743_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7743_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7743_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7743_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7743_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
Index: renesas/drivers/clk/renesas/renesas-cpg-mssr.c
===================================================================
--- renesas.orig/drivers/clk/renesas/renesas-cpg-mssr.c
+++ renesas/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -503,6 +503,12 @@ static int __init cpg_mssr_add_clk_domai
}
static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_ARCH_R8A7743
+ {
+ .compatible = "renesas,r8a7743-cpg-mssr",
+ .data = &r8a7743_cpg_mssr_info,
+ },
+#endif
#ifdef CONFIG_ARCH_R8A7795
{
.compatible = "renesas,r8a7795-cpg-mssr",
Index: renesas/drivers/clk/renesas/renesas-cpg-mssr.h
===================================================================
--- renesas.orig/drivers/clk/renesas/renesas-cpg-mssr.h
+++ renesas/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -130,6 +130,7 @@ struct cpg_mssr_info {
struct clk **clks, void __iomem *base);
};
+extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros
2016-10-05 20:54 ` [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros Sergei Shtylyov
@ 2016-10-07 19:06 ` Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
1 sibling, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-07 19:06 UTC (permalink / raw)
To: mturquette, sboyd, robh+dt, mark.rutland, devicetree,
linux-renesas-soc, Simon Horman
Cc: linux-clk
Hello.
On 10/05/2016 11:54 PM, Sergei Shtylyov wrote:
> Add macros usable by the device tree sources to reference the R8A7743 CPG
> clocks by index.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Probably makes ense to merge this patch to both the clk and renesas trees
in order to satisfy the dependencies both ways... what do you think, Simon?
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros
2016-10-05 20:54 ` [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
@ 2016-10-07 19:06 ` Sergei Shtylyov
2016-10-07 19:35 ` Geert Uytterhoeven
1 sibling, 1 reply; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-07 19:06 UTC (permalink / raw)
To: mturquette, sboyd, robh+dt, mark.rutland, devicetree,
linux-renesas-soc, Simon Horman
Cc: linux-clk
Hello.
On 10/05/2016 11:54 PM, Sergei Shtylyov wrote:
> Add macros usable by the device tree sources to reference the R8A7743 CPG
> clocks by index.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Probably makes sense to merge this patch to both the clk and renesas trees
in order to satisfy the dependencies both ways... what do you think, Simon?
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros
2016-10-07 19:06 ` Sergei Shtylyov
@ 2016-10-07 19:35 ` Geert Uytterhoeven
0 siblings, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-10-07 19:35 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Mark Rutland,
devicetree, Linux-Renesas, Simon Horman, linux-clk
Hi Sergei,
On Fri, Oct 7, 2016 at 9:06 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> On 10/05/2016 11:54 PM, Sergei Shtylyov wrote:
>> Add macros usable by the device tree sources to reference the R8A7743 CPG
>> clocks by index.
>>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> Probably makes sense to merge this patch to both the clk and renesas
> trees in order to satisfy the dependencies both ways... what do you think,
> Simon?
Yes, this is another case where both the clock maintainers and Simon
should merge my clk-renesas-for-v4.10 tree, when It has received (a future
version of) this series.
But that's to be handled after v4.9-rc1...
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/3] Renesas R8A7743 CPG/MSSR clock support
2016-10-05 20:50 ` Sergei Shtylyov
` (3 preceding siblings ...)
(?)
@ 2016-10-07 20:35 ` Sergei Shtylyov
-1 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-07 20:35 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd, robh+dt, mark.rutland, devicetree
Cc: linux-renesas-soc
Hello.
On 10/05/2016 11:50 PM, Sergei Shtylyov wrote:
> Here's the set of 3 patches against the 'clk-next' branch of CLK group's
> 'linux.git' repo. The R8A7743 SoC support will be posted separately later --
> this series depend on the Kconfig variable introduced there, however, the DTs
> in that series will depend on the patch #2 of this series...
>
> [1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
This will probably have to be fixed up to handle the absence of the PLL0CR
register oin the low end SoC (like RZ/G1E)...
> [2/3] ARM: shmobile: r8a7743: add CPG clock index macros
> [3/3] clk: renesas: cpg-mssr: add R8A7743 support
I'm splitting the above 2 patches into a new series and will repost it RSN.
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:52 ` [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support Sergei Shtylyov
@ 2016-10-19 8:57 ` Geert Uytterhoeven
2016-10-26 12:17 ` Geert Uytterhoeven
1 sibling, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-10-19 8:57 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
On Wed, Oct 5, 2016 at 10:52 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
> and Software Reset support code, using the CPG/MSSR driver core.
>
> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
> <geert+renesas@glider.be>.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:52 ` [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support Sergei Shtylyov
2016-10-19 8:57 ` Geert Uytterhoeven
@ 2016-10-26 12:17 ` Geert Uytterhoeven
1 sibling, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-10-26 12:17 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
On Wed, Oct 5, 2016 at 10:52 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
> and Software Reset support code, using the CPG/MSSR driver core.
>
> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
> <geert+renesas@glider.be>.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> --- /dev/null
> +++ renesas/drivers/clk/renesas/rcar-gen2-cpg.c
> +
> +/*
> + * Reset register definitions.
> + */
> +#define MODEMR 0xe6160060
> +
> +u32 __init rcar_gen2_read_modemr(void)
> +{
> + void __iomem *modemr = ioremap_nocache(MODEMR, 4);
> + u32 mode;
> +
> + BUG_ON(!modemr);
> + mode = ioread32(modemr);
> + iounmap(modemr);
> +
> + return mode;
> +}
Once we have "[PATCH v4 00/23] soc: renesas: Add R-Car RST driver for obtaining
mode pin state" in place, we can make the RST node in DT mandatory
for SoCs using CPG/MSSR, and drop this helper function.
> --- /dev/null
> +++ renesas/drivers/clk/renesas/rcar-gen2-cpg.h
> @@ -0,0 +1,42 @@
> +u32 rcar_gen2_read_modemr(void);
Likewise.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:50 ` Sergei Shtylyov
` (4 preceding siblings ...)
(?)
@ 2016-10-27 19:53 ` Sergei Shtylyov
2016-11-02 11:08 ` Geert Uytterhoeven
-1 siblings, 1 reply; 23+ messages in thread
From: Sergei Shtylyov @ 2016-10-27 19:53 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
and Software Reset support code, using the CPG/MSSR driver core.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
Changes in version 2:
- added support for non-existing PLL0CR;
- removed the function reading the mode pins;
- added/used the #define's for PLL0CR.STC;
- used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
- removed rcar_gen2_read_modemr();
- added Geert's tag.
drivers/clk/renesas/rcar-gen2-cpg.c | 369 ++++++++++++++++++++++++++++++++++++
drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
2 files changed, 411 insertions(+)
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,369 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car E2.
+ * Register the PLL0 clock as a fixed factor clock for now as
+ * there's no generic multiplier clock implementation and we
+ * currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ if (mult) {
+ /* PLL0 is VCO/3 on R-Car E2 */
+ div = 3;
+ } else {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = ((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config)
+{
+ cpg_pll_config = config;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.h
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,42 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+ unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config);
+
+#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-27 19:53 ` [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support Sergei Shtylyov
@ 2016-11-02 11:08 ` Geert Uytterhoeven
2016-11-02 11:38 ` Geert Uytterhoeven
2016-11-02 13:30 ` Sergei Shtylyov
0 siblings, 2 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-11-02 11:08 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hi Sergei,
On Thu, Oct 27, 2016 at 9:53 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
> and Software Reset support code, using the CPG/MSSR driver core.
>
> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
> <geert+renesas@glider.be>.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> ---
> This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
>
> Changes in version 2:
> - added support for non-existing PLL0CR;
> - removed the function reading the mode pins;
> - added/used the #define's for PLL0CR.STC;
> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
> - removed rcar_gen2_read_modemr();
> - added Geert's tag.
>
> drivers/clk/renesas/rcar-gen2-cpg.c | 369 ++++++++++++++++++++++++++++++++++++
> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
> 2 files changed, 411 insertions(+)
>
> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
> ===================================================================
> --- /dev/null
> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
> @@ -0,0 +1,369 @@
> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
> + const struct cpg_core_clk *core,
> + const struct cpg_mssr_info *info,
> + struct clk **clks,
> + void __iomem *base)
> +{
> + case CLK_TYPE_GEN2_PLL0:
> + /*
> + * PLL0 is a configurable multiplier clock except on R-Car E2.
... and V2H.
> + * Register the PLL0 clock as a fixed factor clock for now as
> + * there's no generic multiplier clock implementation and we
> + * currently have no need to change the multiplier value.
> + */
> + mult = cpg_pll_config->pll0_mult;
> + if (mult) {
> + /* PLL0 is VCO/3 on R-Car E2 */
... and V2H.
> + div = 3;
> + } else {
> + u32 pll0cr = readl(base + CPG_PLL0CR);
> +
> + mult = ((pll0cr & CPG_PLL0CR_STC_MASK) >>
> + CPG_PLL0CR_STC_SHIFT) + 1;
> + }
Looks OK to me. I assume you've verified the Z2 clock frequency in
/sys/kernel/debug/clk/clk_summary?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-02 11:08 ` Geert Uytterhoeven
@ 2016-11-02 11:38 ` Geert Uytterhoeven
2016-11-02 18:11 ` Sergei Shtylyov
2016-11-02 13:30 ` Sergei Shtylyov
1 sibling, 1 reply; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-11-02 11:38 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hi Sergei,
On Wed, Nov 2, 2016 at 12:08 PM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Thu, Oct 27, 2016 at 9:53 PM, Sergei Shtylyov
> <sergei.shtylyov@cogentembedded.com> wrote:
>> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
>> and Software Reset support code, using the CPG/MSSR driver core.
>>
>> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
>> <geert+renesas@glider.be>.
>>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>>
>> ---
>> This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
>>
>> Changes in version 2:
>> - added support for non-existing PLL0CR;
>> - removed the function reading the mode pins;
>> - added/used the #define's for PLL0CR.STC;
>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>> - removed rcar_gen2_read_modemr();
>> - added Geert's tag.
>>
>> drivers/clk/renesas/rcar-gen2-cpg.c | 369 ++++++++++++++++++++++++++++++++++++
>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>> 2 files changed, 411 insertions(+)
>>
>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>> ===================================================================
>> --- /dev/null
>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>> @@ -0,0 +1,369 @@
>
>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>> + const struct cpg_core_clk *core,
>> + const struct cpg_mssr_info *info,
>> + struct clk **clks,
>> + void __iomem *base)
>> +{
>
>> + case CLK_TYPE_GEN2_PLL0:
>> + /*
>> + * PLL0 is a configurable multiplier clock except on R-Car E2.
>
> ... and V2H.
>
>> + * Register the PLL0 clock as a fixed factor clock for now as
>> + * there's no generic multiplier clock implementation and we
>> + * currently have no need to change the multiplier value.
>> + */
>> + mult = cpg_pll_config->pll0_mult;
>> + if (mult) {
>> + /* PLL0 is VCO/3 on R-Car E2 */
>
> ... and V2H.
>
>> + div = 3;
After seeing the r8a7745 driver, I think it would be better to use a divider
value of 1 here (dropping the need for this branch), and handle the /3 in the
SoC-specific driver.
This would make it more similar to the other SoCs here (div = 1 in the else
branch below), and to similar clocks in the SoC-specific driver
(e.g. DEF_FIXED("zg", ..., 3, 1) in r8a7743-cpg-mssr.c).
>> + } else {
>> + u32 pll0cr = readl(base + CPG_PLL0CR);
>> +
>> + mult = ((pll0cr & CPG_PLL0CR_STC_MASK) >>
>> + CPG_PLL0CR_STC_SHIFT) + 1;
>> + }
>
> Looks OK to me. I assume you've verified the Z2 clock frequency in
> /sys/kernel/debug/clk/clk_summary?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-02 11:08 ` Geert Uytterhoeven
2016-11-02 11:38 ` Geert Uytterhoeven
@ 2016-11-02 13:30 ` Sergei Shtylyov
1 sibling, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-02 13:30 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hello.
On 11/02/2016 02:08 PM, Geert Uytterhoeven wrote:
>> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
>> and Software Reset support code, using the CPG/MSSR driver core.
>>
>> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
>> <geert+renesas@glider.be>.
>>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>>
>> ---
>> This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
>>
>> Changes in version 2:
>> - added support for non-existing PLL0CR;
>> - removed the function reading the mode pins;
>> - added/used the #define's for PLL0CR.STC;
>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>> - removed rcar_gen2_read_modemr();
>> - added Geert's tag.
>>
>> drivers/clk/renesas/rcar-gen2-cpg.c | 369 ++++++++++++++++++++++++++++++++++++
>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>> 2 files changed, 411 insertions(+)
>>
>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>> ===================================================================
>> --- /dev/null
>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>> @@ -0,0 +1,369 @@
>
>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>> + const struct cpg_core_clk *core,
>> + const struct cpg_mssr_info *info,
>> + struct clk **clks,
>> + void __iomem *base)
>> +{
>
>> + case CLK_TYPE_GEN2_PLL0:
>> + /*
>> + * PLL0 is a configurable multiplier clock except on R-Car E2.
>
> ... and V2H.
Indeed. But at least on E2 PLL0CR.STC can be read...
>> + * Register the PLL0 clock as a fixed factor clock for now as
>> + * there's no generic multiplier clock implementation and we
>> + * currently have no need to change the multiplier value.
>> + */
>> + mult = cpg_pll_config->pll0_mult;
>> + if (mult) {
>> + /* PLL0 is VCO/3 on R-Car E2 */
>
> ... and V2H.
No, it's still VCO/2 on V2H, according to the manual. Perhaps I'll have to
store the PLL0 divisor separately (and maybe even instead of the PLL0 multiplier).
>> + div = 3;
>> + } else {
>> + u32 pll0cr = readl(base + CPG_PLL0CR);
>> +
>> + mult = ((pll0cr & CPG_PLL0CR_STC_MASK) >>
>> + CPG_PLL0CR_STC_SHIFT) + 1;
>> + }
>
> Looks OK to me. I assume you've verified the Z2 clock frequency in
> /sys/kernel/debug/clk/clk_summary?
Not yet. :-/
> Gr{oetje,eeting}s,
>
> Geert
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-02 11:38 ` Geert Uytterhoeven
@ 2016-11-02 18:11 ` Sergei Shtylyov
2016-11-02 18:19 ` Geert Uytterhoeven
0 siblings, 1 reply; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-02 18:11 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
On 11/02/2016 02:38 PM, Geert Uytterhoeven wrote:
>>> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
>>> and Software Reset support code, using the CPG/MSSR driver core.
>>>
>>> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
>>> <geert+renesas@glider.be>.
>>>
>>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>>> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>>>
>>> ---
>>> This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
>>>
>>> Changes in version 2:
>>> - added support for non-existing PLL0CR;
>>> - removed the function reading the mode pins;
>>> - added/used the #define's for PLL0CR.STC;
>>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>>> - removed rcar_gen2_read_modemr();
>>> - added Geert's tag.
>>>
>>> drivers/clk/renesas/rcar-gen2-cpg.c | 369 ++++++++++++++++++++++++++++++++++++
>>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>>> 2 files changed, 411 insertions(+)
>>>
>>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>> ===================================================================
>>> --- /dev/null
>>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>> @@ -0,0 +1,369 @@
>>
>>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>>> + const struct cpg_core_clk *core,
>>> + const struct cpg_mssr_info *info,
>>> + struct clk **clks,
>>> + void __iomem *base)
>>> +{
>>
>>> + case CLK_TYPE_GEN2_PLL0:
>>> + /*
>>> + * PLL0 is a configurable multiplier clock except on R-Car E2.
>>
>> ... and V2H.
>>
>>> + * Register the PLL0 clock as a fixed factor clock for now as
>>> + * there's no generic multiplier clock implementation and we
>>> + * currently have no need to change the multiplier value.
>>> + */
>>> + mult = cpg_pll_config->pll0_mult;
>>> + if (mult) {
>>> + /* PLL0 is VCO/3 on R-Car E2 */
>>
>> ... and V2H.
>>
>>> + div = 3;
>
> After seeing the r8a7745 driver, I think it would be better to use a divider
> value of 1 here (dropping the need for this branch), and handle the /3 in the
> SoC-specific driver.
> This would make it more similar to the other SoCs here (div = 1 in the else
> branch below), and to similar clocks in the SoC-specific driver
> (e.g. DEF_FIXED("zg", ..., 3, 1) in r8a7743-cpg-mssr.c).
We'll then have to lie about the PLL0 output freq? I don't like it...
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-02 18:11 ` Sergei Shtylyov
@ 2016-11-02 18:19 ` Geert Uytterhoeven
0 siblings, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-11-02 18:19 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hi Sergei,
On Wed, Nov 2, 2016 at 7:11 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> On 11/02/2016 02:38 PM, Geert Uytterhoeven wrote:
>>>> Changes in version 2:
>>>> - added support for non-existing PLL0CR;
>>>> - removed the function reading the mode pins;
>>>> - added/used the #define's for PLL0CR.STC;
>>>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>>>> - removed rcar_gen2_read_modemr();
>>>> - added Geert's tag.
>>>>
>>>> drivers/clk/renesas/rcar-gen2-cpg.c | 369
>>>> ++++++++++++++++++++++++++++++++++++
>>>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>>>> 2 files changed, 411 insertions(+)
>>>>
>>>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>> ===================================================================
>>>> --- /dev/null
>>>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>> @@ -0,0 +1,369 @@
>>>
>>>
>>>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>>>> + const struct cpg_core_clk
>>>> *core,
>>>> + const struct
>>>> cpg_mssr_info *info,
>>>> + struct clk **clks,
>>>> + void __iomem *base)
>>>> +{
>>>
>>>
>>>> + case CLK_TYPE_GEN2_PLL0:
>>>> + /*
>>>> + * PLL0 is a configurable multiplier clock except on
>>>> R-Car E2.
>>>
>>>
>>> ... and V2H.
>>>
>>>> + * Register the PLL0 clock as a fixed factor clock for
>>>> now as
>>>> + * there's no generic multiplier clock implementation
>>>> and we
>>>> + * currently have no need to change the multiplier
>>>> value.
>>>> + */
>>>> + mult = cpg_pll_config->pll0_mult;
>>>> + if (mult) {
>>>> + /* PLL0 is VCO/3 on R-Car E2 */
>>>
>>>
>>> ... and V2H.
>>>
>>>> + div = 3;
>>
>>
>> After seeing the r8a7745 driver, I think it would be better to use a
>> divider
>> value of 1 here (dropping the need for this branch), and handle the /3 in
>> the
>> SoC-specific driver.
>> This would make it more similar to the other SoCs here (div = 1 in the
>> else
>> branch below), and to similar clocks in the SoC-specific driver
>> (e.g. DEF_FIXED("zg", ..., 3, 1) in r8a7743-cpg-mssr.c).
>
> We'll then have to lie about the PLL0 output freq? I don't like it...
Do we? The divisor is not part of PLL0. The datasheet says:
- For V2H/E2:
"PLL circuit 0 multiplies EXTAL or EXTAL/2 clock."
- For the other SoCs:
"PLL circuit 0 multiplies EXTAL or EXTAL/2 clock. The
multiplication ratio is set by the PLL0CR."
Division is done _after_ PLL0, using the SYS-CPU clock divider.
- For e.g. E2:
"The SYS-CPU clock divider 1 divides PLL0 output clock. This
divider generates the AP-System core clocks (Z2φ)."
AFAIU, this SYS-CPU clock divider is "/3" on E2.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
@ 2016-11-02 18:19 ` Geert Uytterhoeven
0 siblings, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-11-02 18:19 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hi Sergei,
On Wed, Nov 2, 2016 at 7:11 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> On 11/02/2016 02:38 PM, Geert Uytterhoeven wrote:
>>>> Changes in version 2:
>>>> - added support for non-existing PLL0CR;
>>>> - removed the function reading the mode pins;
>>>> - added/used the #define's for PLL0CR.STC;
>>>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>>>> - removed rcar_gen2_read_modemr();
>>>> - added Geert's tag.
>>>>
>>>> drivers/clk/renesas/rcar-gen2-cpg.c | 369
>>>> ++++++++++++++++++++++++++++++++++++
>>>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>>>> 2 files changed, 411 insertions(+)
>>>>
>>>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>>> --- /dev/null
>>>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>> @@ -0,0 +1,369 @@
>>>
>>>
>>>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>>>> + const struct cpg_core_c=
lk
>>>> *core,
>>>> + const struct
>>>> cpg_mssr_info *info,
>>>> + struct clk **clks,
>>>> + void __iomem *base)
>>>> +{
>>>
>>>
>>>> + case CLK_TYPE_GEN2_PLL0:
>>>> + /*
>>>> + * PLL0 is a configurable multiplier clock except on
>>>> R-Car E2.
>>>
>>>
>>> ... and V2H.
>>>
>>>> + * Register the PLL0 clock as a fixed factor clock for
>>>> now as
>>>> + * there's no generic multiplier clock implementation
>>>> and we
>>>> + * currently have no need to change the multiplier
>>>> value.
>>>> + */
>>>> + mult =3D cpg_pll_config->pll0_mult;
>>>> + if (mult) {
>>>> + /* PLL0 is VCO/3 on R-Car E2 */
>>>
>>>
>>> ... and V2H.
>>>
>>>> + div =3D 3;
>>
>>
>> After seeing the r8a7745 driver, I think it would be better to use a
>> divider
>> value of 1 here (dropping the need for this branch), and handle the /3 i=
n
>> the
>> SoC-specific driver.
>> This would make it more similar to the other SoCs here (div =3D 1 in the
>> else
>> branch below), and to similar clocks in the SoC-specific driver
>> (e.g. DEF_FIXED("zg", ..., 3, 1) in r8a7743-cpg-mssr.c).
>
> We'll then have to lie about the PLL0 output freq? I don't like it...
Do we? The divisor is not part of PLL0. The datasheet says:
- For V2H/E2:
"PLL circuit 0 multiplies EXTAL or EXTAL/2 clock."
- For the other SoCs:
"PLL circuit 0 multiplies EXTAL or EXTAL/2 clock. The
multiplication ratio is set by the PLL0CR."
Division is done _after_ PLL0, using the SYS-CPU clock divider.
- For e.g. E2:
"The SYS-CPU clock divider 1 divides PLL0 output clock. This
divider generates the AP-System core clocks (Z2=CF=86)."
AFAIU, this SYS-CPU clock divider is "/3" on E2.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-02 18:19 ` Geert Uytterhoeven
(?)
@ 2016-11-02 18:26 ` Sergei Shtylyov
-1 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-02 18:26 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
On 11/02/2016 09:19 PM, Geert Uytterhoeven wrote:
>>>>> Changes in version 2:
>>>>> - added support for non-existing PLL0CR;
>>>>> - removed the function reading the mode pins;
>>>>> - added/used the #define's for PLL0CR.STC;
>>>>> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
>>>>> - removed rcar_gen2_read_modemr();
>>>>> - added Geert's tag.
>>>>>
>>>>> drivers/clk/renesas/rcar-gen2-cpg.c | 369
>>>>> ++++++++++++++++++++++++++++++++++++
>>>>> drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
>>>>> 2 files changed, 411 insertions(+)
>>>>>
>>>>> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>>> ===================================================================
>>>>> --- /dev/null
>>>>> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
>>>>> @@ -0,0 +1,369 @@
>>>>
>>>>
>>>>> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
>>>>> + const struct cpg_core_clk
>>>>> *core,
>>>>> + const struct
>>>>> cpg_mssr_info *info,
>>>>> + struct clk **clks,
>>>>> + void __iomem *base)
>>>>> +{
>>>>
>>>>
>>>>> + case CLK_TYPE_GEN2_PLL0:
>>>>> + /*
>>>>> + * PLL0 is a configurable multiplier clock except on
>>>>> R-Car E2.
>>>>
>>>>
>>>> ... and V2H.
>>>>
>>>>> + * Register the PLL0 clock as a fixed factor clock for
>>>>> now as
>>>>> + * there's no generic multiplier clock implementation
>>>>> and we
>>>>> + * currently have no need to change the multiplier
>>>>> value.
>>>>> + */
>>>>> + mult = cpg_pll_config->pll0_mult;
>>>>> + if (mult) {
>>>>> + /* PLL0 is VCO/3 on R-Car E2 */
>>>>
>>>>
>>>> ... and V2H.
>>>>
>>>>> + div = 3;
>>>
>>>
>>> After seeing the r8a7745 driver, I think it would be better to use a
>>> divider
>>> value of 1 here (dropping the need for this branch), and handle the /3 in
>>> the
>>> SoC-specific driver.
>>> This would make it more similar to the other SoCs here (div = 1 in the
>>> else
>>> branch below), and to similar clocks in the SoC-specific driver
>>> (e.g. DEF_FIXED("zg", ..., 3, 1) in r8a7743-cpg-mssr.c).
>>
>> We'll then have to lie about the PLL0 output freq? I don't like it...
>
> Do we? The divisor is not part of PLL0. The datasheet says:
>
> - For V2H/E2:
> "PLL circuit 0 multiplies EXTAL or EXTAL/2 clock."
> - For the other SoCs:
> "PLL circuit 0 multiplies EXTAL or EXTAL/2 clock. The
> multiplication ratio is set by the PLL0CR."
>
> Division is done _after_ PLL0, using the SYS-CPU clock divider.
>
> - For e.g. E2:
> "The SYS-CPU clock divider 1 divides PLL0 output clock. This
> divider generates the AP-System core clocks (Z2φ)."
>
> AFAIU, this SYS-CPU clock divider is "/3" on E2.
The figures 7.1* picture it the other way: PLL0/VCO*1/3 is the output of
PLL0, according to them. Quite the same way as PLL1 freq gets divided by 2
before being output. Maybe they're wrong tho...
> Gr{oetje,eeting}s,
>
> Geert
MBR, Sergei
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:50 ` Sergei Shtylyov
` (5 preceding siblings ...)
(?)
@ 2016-11-02 21:51 ` Sergei Shtylyov
-1 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-02 21:51 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
and Software Reset support code, using the CPG/MSSR driver core.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 3:
- remove the divisor logic from the PLL0 related code;
- also mention R-Car V2H as not having the PLL0CR register.
Changes in version 2:
- added support for non-existing PLL0CR;
- removed the function reading the mode pins;
- added/used the #define's for PLL0CR.STC;
- used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
- removed rcar_gen2_read_modemr();
- added Geert's tag.
drivers/clk/renesas/rcar-gen2-cpg.c | 366 ++++++++++++++++++++++++++++++++++++
drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
2 files changed, 408 insertions(+)
Index: renesas/drivers/clk/renesas/rcar-gen2-cpg.c
===================================================================
--- /dev/null
+++ renesas/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,366 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car
+ * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+ * now as there's no generic multiplier clock implementation and
+ * we currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ if (!mult) {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config)
+{
+ cpg_pll_config = config;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
Index: renesas/drivers/clk/renesas/rcar-gen2-cpg.h
===================================================================
--- /dev/null
+++ renesas/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,42 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+ unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config);
+
+#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 RESEND] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:50 ` Sergei Shtylyov
` (6 preceding siblings ...)
(?)
@ 2016-11-03 20:48 ` Sergei Shtylyov
-1 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-03 20:48 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
and Software Reset support code, using the CPG/MSSR driver core.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
Changes in version 3:
- remove the divisor logic from the PLL0 related code;
- also mention R-Car V2H as not having the PLL0CR register.
Changes in version 2:
- added support for non-existing PLL0CR;
- removed the function reading the mode pins;
- added/used the #define's for PLL0CR.STC;
- used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
- removed rcar_gen2_read_modemr();
- added Geert's tag.
drivers/clk/renesas/rcar-gen2-cpg.c | 366 ++++++++++++++++++++++++++++++++++++
drivers/clk/renesas/rcar-gen2-cpg.h | 42 ++++
2 files changed, 408 insertions(+)
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,366 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car
+ * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+ * now as there's no generic multiplier clock implementation and
+ * we currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ if (!mult) {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config)
+{
+ cpg_pll_config = config;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.h
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,42 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+ unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config);
+
+#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v4] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-10-05 20:50 ` Sergei Shtylyov
` (7 preceding siblings ...)
(?)
@ 2016-11-08 21:17 ` Sergei Shtylyov
2016-11-10 12:50 ` Geert Uytterhoeven
-1 siblings, 1 reply; 23+ messages in thread
From: Sergei Shtylyov @ 2016-11-08 21:17 UTC (permalink / raw)
To: mturquette, linux-clk, sboyd; +Cc: linux-renesas-soc
Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
and Software Reset support code, using the CPG/MSSR driver core.
Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
<geert+renesas@glider.be>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
Changes in version 4:
- added a static variable for the PLL0 divisor and a parameter of the same kind
to rcar_gen2_cpg_init(), used that variable in rcar_gen2_cpg_clk_register().
Changes in version 3:
- removed the divisor logic from the PLL0 related code;
- also mentioned R-Car V2H as not having the PLL0CR register.
Changes in version 2:
- added support for non-existing PLL0CR;
- removed the function reading the mode pins;
- added/used the #define's for PLL0CR.STC;
- used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
- removed rcar_gen2_read_modemr();
- added Geert's tag.
drivers/clk/renesas/rcar-gen2-cpg.c | 370 ++++++++++++++++++++++++++++++++++++
drivers/clk/renesas/rcar-gen2-cpg.h | 43 ++++
2 files changed, 413 insertions(+)
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,370 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long prate = *parent_rate;
+ unsigned int mult;
+
+ if (!prate)
+ prate = 1;
+
+ mult = div_u64((u64)rate * 32, prate);
+ mult = clamp(mult, 1U, 32U);
+
+ return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div_u64((u64)rate * 32, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .round_rate = cpg_z_clk_round_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_pll0_div __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks,
+ void __iomem *base)
+{
+ const struct clk_div_table *table = NULL;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car
+ * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+ * now as there's no generic multiplier clock implementation and
+ * we currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ div = cpg_pll0_div;
+ if (!mult) {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div)
+{
+ cpg_pll_config = config;
+ cpg_pll0_div = pll0_div;
+
+ spin_lock_init(&cpg_lock);
+
+ return 0;
+}
Index: linux/drivers/clk/renesas/rcar-gen2-cpg.h
===================================================================
--- /dev/null
+++ linux/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,43 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ unsigned int extal_div;
+ unsigned int pll1_mult;
+ unsigned int pll3_mult;
+ unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div);
+
+#endif
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v4] clk: renesas: cpg-mssr: add common R-Car Gen2 support
2016-11-08 21:17 ` [PATCH v4] " Sergei Shtylyov
@ 2016-11-10 12:50 ` Geert Uytterhoeven
0 siblings, 0 replies; 23+ messages in thread
From: Geert Uytterhoeven @ 2016-11-10 12:50 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Michael Turquette, linux-clk, Stephen Boyd, Linux-Renesas
Hi Sergei,
On Tue, Nov 8, 2016 at 10:17 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Add the common R-Car Gen2 (and RZ/G) Clock Pulse Generator / Module Standby
> and Software Reset support code, using the CPG/MSSR driver core.
>
> Based on the proof-of-concept R8A7791 CPG/MSSR patch by Geert Uytterhoeven
> <geert+renesas@glider.be>.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> ---
> This patch is against the 'clk-next' branch of CLK group's 'linux.git' repo.
>
> Changes in version 4:
> - added a static variable for the PLL0 divisor and a parameter of the same kind
> to rcar_gen2_cpg_init(), used that variable in rcar_gen2_cpg_clk_register().
Thanks, I've verified correct operation by using your r8a7743 driver on
r8a7791/koelsch, and comparing /sys/kernel/debug/clk/clk_summary.
> Changes in version 3:
> - removed the divisor logic from the PLL0 related code;
> - also mentioned R-Car V2H as not having the PLL0CR register.
>
> Changes in version 2:
> - added support for non-existing PLL0CR;
> - removed the function reading the mode pins;
> - added/used the #define's for PLL0CR.STC;
> - used CPG_FRQCRC_ZFC_SHIFT to #define CPG_FRQCRC_ZFC_MASK;
> - removed rcar_gen2_read_modemr();
> - added Geert's tag.
>
> drivers/clk/renesas/rcar-gen2-cpg.c | 370 ++++++++++++++++++++++++++++++++++++
> drivers/clk/renesas/rcar-gen2-cpg.h | 43 ++++
> 2 files changed, 413 insertions(+)
>
> Index: linux/drivers/clk/renesas/rcar-gen2-cpg.c
> ===================================================================
> --- /dev/null
> +++ linux/drivers/clk/renesas/rcar-gen2-cpg.c
> +static u32 cpg_mode __initdata;
cpg_mode is never set.
> +
> +struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
> + const struct cpg_core_clk *core,
> + const struct cpg_mssr_info *info,
> + struct clk **clks,
> + void __iomem *base)
> +{
> + switch (core->type) {
> + case CLK_TYPE_GEN2_LB:
> + div = cpg_mode & BIT(18) ? 36 : 24;
Hence div may be incorrect here (it wasn't for me)...
> + case CLK_TYPE_GEN2_QSPI:
> + div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
> + 8 : 10;
... and here (it was for me).
> +int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
> + unsigned int pll0_div)
I'll add a "u32 mode" parameter here, and pass it from
r8a774[35]_cpg_mssr_init().
> +{
> + cpg_pll_config = config;
> + cpg_pll0_div = pll0_div;
cpg_mode = mode;
No need to resend, fixing it up myself.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2016-11-10 12:50 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-05 20:50 [PATCH 0/3] Renesas R8A7743 CPG/MSSR clock support Sergei Shtylyov
2016-10-05 20:50 ` Sergei Shtylyov
2016-10-05 20:52 ` [PATCH 1/3] clk: renesas: cpg-mssr: add common R-Car Gen2 support Sergei Shtylyov
2016-10-19 8:57 ` Geert Uytterhoeven
2016-10-26 12:17 ` Geert Uytterhoeven
2016-10-05 20:54 ` [PATCH 2/3] ARM: shmobile: r8a7743: add CPG clock index macros Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
2016-10-07 19:06 ` Sergei Shtylyov
2016-10-07 19:35 ` Geert Uytterhoeven
2016-10-05 20:55 ` [PATCH 3/3] clk: renesas: cpg-mssr: add R8A7743 support Sergei Shtylyov
2016-10-07 20:35 ` [PATCH 0/3] Renesas R8A7743 CPG/MSSR clock support Sergei Shtylyov
2016-10-27 19:53 ` [PATCH v2] clk: renesas: cpg-mssr: add common R-Car Gen2 support Sergei Shtylyov
2016-11-02 11:08 ` Geert Uytterhoeven
2016-11-02 11:38 ` Geert Uytterhoeven
2016-11-02 18:11 ` Sergei Shtylyov
2016-11-02 18:19 ` Geert Uytterhoeven
2016-11-02 18:19 ` Geert Uytterhoeven
2016-11-02 18:26 ` Sergei Shtylyov
2016-11-02 13:30 ` Sergei Shtylyov
2016-11-02 21:51 ` [PATCH v3] " Sergei Shtylyov
2016-11-03 20:48 ` [PATCH v3 RESEND] " Sergei Shtylyov
2016-11-08 21:17 ` [PATCH v4] " Sergei Shtylyov
2016-11-10 12:50 ` Geert Uytterhoeven
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.