mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 0/2] sh: sh7305: add TMU0 clock support
@ 2026-11-11  1:07 Artem Novak
  2026-11-11  1:07 ` [PATCH v4 1/2] " Artem Novak
  2026-11-11  1:07 ` [PATCH v4 2/2] sh: sh7305: exclude from legacy CPG clock framework Artem Novak
  0 siblings, 2 replies; 3+ messages in thread
From: Artem Novak @ 2026-11-11  1:07 UTC (permalink / raw)
  To: ysato, dalias, glaubitz, geert+renesas
  Cc: linux-sh, linux-kernel, Artem Novak

This series adds Common Clock Framework support for the SH7305.

The existing SH7305 clock implementation is converted to CCF,
including the master clock, CPU, bus and peripheral divider clocks,
and the TMU0 module clock gate.
The legacy CPG clock framework is then excluded for SH7305
to avoid enabling both clock implementations.

The series consists of:

sh: sh7305: add TMU0 clock support
Convert the SH7305 clock implementation to CCF and
provide the TMU0 functional clock through clkdev.

sh: sh7305: exclude from legacy CPG clock framework
Exclude SH7305 from SH_CLK_CPG_LEGACY.

Changes since v3:
 - Split the legacy CPG exclusion into a separate second patch.
 - Keep the SH7305 CCF clock implementation and TMU0 gate
   together in the first patch.

Artem Novak (2):
  sh: sh7305: add TMU0 clock support
  sh: sh7305: exclude from legacy CPG clock framework

 arch/sh/Kconfig                        |   2 +-
 arch/sh/include/asm/clock-sh7305.h     |  11 ++
 arch/sh/kernel/cpu/sh4a/clock-sh7305.c | 262 +++++++++++++++++--------
 3 files changed, 196 insertions(+), 79 deletions(-)
 create mode 100644 arch/sh/include/asm/clock-sh7305.h

-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v4 1/2] sh: sh7305: add TMU0 clock support
  2026-11-11  1:07 [PATCH v4 0/2] sh: sh7305: add TMU0 clock support Artem Novak
@ 2026-11-11  1:07 ` Artem Novak
  2026-11-11  1:07 ` [PATCH v4 2/2] sh: sh7305: exclude from legacy CPG clock framework Artem Novak
  1 sibling, 0 replies; 3+ messages in thread
From: Artem Novak @ 2026-11-11  1:07 UTC (permalink / raw)
  To: ysato, dalias, glaubitz, geert+renesas
  Cc: linux-sh, linux-kernel, Artem Novak

Convert the SH7305 clock implementation to the Common Clock
Framework.

Register the master clock and the CPU, bus and peripheral
divider clocks, and add the TMU0 module clock gate.

Provide a clkdev mapping for the TMU0 functional clock so
the TMU driver can acquire it through its existing clock
lookup.

Signed-off-by: Artem Novak <artem122novak@gmail.com>
---
 arch/sh/include/asm/clock-sh7305.h     |  11 ++
 arch/sh/kernel/cpu/sh4a/clock-sh7305.c | 262 +++++++++++++++++--------
 2 files changed, 195 insertions(+), 78 deletions(-)
 create mode 100644 arch/sh/include/asm/clock-sh7305.h

diff --git a/arch/sh/include/asm/clock-sh7305.h b/arch/sh/include/asm/clock-sh7305.h
new file mode 100644
index 000000000000..2ef73845eacc
--- /dev/null
+++ b/arch/sh/include/asm/clock-sh7305.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_SH_CLOCK_SH7305_H
+#define __ASM_SH_CLOCK_SH7305_H
+
+#include <linux/init.h>
+
+int __init sh7305_clk_init(void);
+
+void __init sh7305_of_setup(char **cmdline_p);
+
+#endif /* __ASM_SH_CLOCK_SH7305_H */
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7305.c b/arch/sh/kernel/cpu/sh4a/clock-sh7305.c
index 0e683dd6de11..fc941524c268 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7305.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7305.c
@@ -4,12 +4,15 @@
  * Renesas SH7305 clock framework support
  */
 
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
 #include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/io.h>
-#include <linux/sh_clk.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
 
-#include <asm/clock.h>
+#include <asm/clock-sh7305.h>
 
 /*
  * SH7305 Clock Pulse Generator
@@ -17,6 +20,7 @@
 #define SH7305_FRQCR		0xa4150000
 #define SH7305_PLLCR		0xa4150024
 #define SH7305_FLLFRQ		0xa4150050
+#define SH7305_MSTPCR0		0xa4150030
 
 /*
  * FRQCR:
@@ -34,34 +38,28 @@
  *   FLF   bits 10..0
  */
 
+static void __iomem *sh7305_cpg_base;
+
 static unsigned long sh7305_base_rate(void)
 {
-	u32 frqcr  = __raw_readl(SH7305_FRQCR);
-	u32 pllcr  = __raw_readl(SH7305_PLLCR);
-	u32 fllfrq = __raw_readl(SH7305_FLLFRQ);
-
-	unsigned int pll;
-	unsigned int fll;
+	u32 frqcr = __raw_readl(sh7305_cpg_base);
+	u32 pllcr = __raw_readl(sh7305_cpg_base + (SH7305_PLLCR - SH7305_FRQCR));
+	u32 fllfrq = __raw_readl(sh7305_cpg_base + (SH7305_FLLFRQ - SH7305_FRQCR));
+	unsigned int pll, fll;
 	unsigned long rate = 32768;
 
-	/*
-	 * SH7305 PLL ratio is STC + 1.
-	 * Unlike SH7724 it must NOT be doubled.
-	 */
+	/* SH7305 PLL ratio is STC + 1; it is not doubled. */
 	pll = ((frqcr >> 24) & 0x3f) + 1;
 
-	/*
-	 * FLL ratio is FLF, halved when SELXM == 1.
-	 */
+	/* FLL ratio is FLF, halved when SELXM == 1. */
 	fll = fllfrq & 0x7ff;
-
 	if (((fllfrq >> 14) & 0x3) == 1)
 		fll >>= 1;
 
-	if (pllcr & (1 << 12))
+	if (pllcr & BIT(12))
 		rate *= fll;
 
-	if (pllcr & (1 << 14))
+	if (pllcr & BIT(14))
 		rate *= pll;
 
 	return rate;
@@ -69,98 +67,206 @@ static unsigned long sh7305_base_rate(void)
 
 static unsigned int sh7305_divisor(unsigned int shift)
 {
-	u32 frqcr = __raw_readl(SH7305_FRQCR);
+	u32 frqcr = __raw_readl(sh7305_cpg_base);
 	unsigned int field = (frqcr >> shift) & 0xf;
 
-	/*
-	 * SH7305 divider:
-	 *
-	 *     divisor = 2^(field + 1)
-	 */
 	return 1U << (field + 1);
 }
 
-
 /*
- * master_clk is the clock before the B/I/P divider stages.
+ * Master clock: the clock before the B/I/P divider stages.
  */
-static void master_clk_init(struct clk *clk)
+static unsigned long sh7305_master_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
 {
-	clk->rate = sh7305_base_rate();
+	return sh7305_base_rate();
 }
 
-static struct sh_clk_ops sh7305_master_clk_ops = {
-	.init = master_clk_init,
+static const struct clk_ops sh7305_master_clk_ops = {
+	.recalc_rate = sh7305_master_recalc_rate,
 };
 
+static const struct clk_init_data sh7305_master_clk_init = {
+	.name = "master_clk",
+	.ops = &sh7305_master_clk_ops,
+};
+
+static struct clk_hw sh7305_master_clk = {
+	.init = &sh7305_master_clk_init,
+};
 
 /*
- * Pphi - peripheral clock.
- *
- * P1FC occupies FRQCR bits 3..0.
+ * Peripheral, bus and CPU clocks share the master clock as parent.
  */
-static unsigned long peripheral_clk_recalc(struct clk *clk)
+struct sh7305_divider {
+	struct clk_hw hw;
+	unsigned int shift;
+};
+
+static unsigned long sh7305_divider_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
 {
-	return clk->parent->rate / sh7305_divisor(0);
+	struct sh7305_divider *divider =
+		container_of(hw, struct sh7305_divider, hw);
+
+	return parent_rate / sh7305_divisor(divider->shift);
 }
 
-static struct sh_clk_ops sh7305_peripheral_clk_ops = {
-	.recalc = peripheral_clk_recalc,
+static const struct clk_ops sh7305_divider_clk_ops = {
+	.recalc_rate = sh7305_divider_recalc_rate,
 };
 
+static const char * const sh7305_parent_names[] = {
+	"master_clk",
+};
 
-/*
- * Bphi - bus clock.
- *
- * BFC occupies FRQCR bits 11..8.
- */
-static unsigned long bus_clk_recalc(struct clk *clk)
-{
-	return clk->parent->rate / sh7305_divisor(8);
-}
+static const struct clk_init_data sh7305_peripheral_clk_init = {
+	.name = "peripheral_clk",
+	.ops = &sh7305_divider_clk_ops,
+	.parent_names = sh7305_parent_names,
+	.num_parents = ARRAY_SIZE(sh7305_parent_names),
+};
 
-static struct sh_clk_ops sh7305_bus_clk_ops = {
-	.recalc = bus_clk_recalc,
+static struct sh7305_divider sh7305_peripheral_clk = {
+	.hw.init = &sh7305_peripheral_clk_init,
+	.shift = 0,
 };
 
+static const struct clk_init_data sh7305_bus_clk_init = {
+	.name = "bus_clk",
+	.ops = &sh7305_divider_clk_ops,
+	.parent_names = sh7305_parent_names,
+	.num_parents = ARRAY_SIZE(sh7305_parent_names),
+};
 
-/*
- * Iphi - CPU/internal clock.
- *
- * IFC occupies FRQCR bits 23..20.
- */
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-	return clk->parent->rate / sh7305_divisor(20);
-}
+static struct sh7305_divider sh7305_bus_clk = {
+	.hw.init = &sh7305_bus_clk_init,
+	.shift = 8,
+};
 
-static struct sh_clk_ops sh7305_cpu_clk_ops = {
-	.recalc = cpu_clk_recalc,
+static const struct clk_init_data sh7305_cpu_clk_init = {
+	.name = "cpu_clk",
+	.ops = &sh7305_divider_clk_ops,
+	.parent_names = sh7305_parent_names,
+	.num_parents = ARRAY_SIZE(sh7305_parent_names),
 };
 
+static struct sh7305_divider sh7305_cpu_clk = {
+	.hw.init = &sh7305_cpu_clk_init,
+	.shift = 20,
+};
 
-/*
- * Ordering must match arch/sh/kernel/cpu/clock-cpg.c:
- *
- *   0 master
- *   1 peripheral
- *   2 bus
- *   3 cpu
- */
-static struct sh_clk_ops *sh7305_clk_ops[] = {
-	&sh7305_master_clk_ops,
-	&sh7305_peripheral_clk_ops,
-	&sh7305_bus_clk_ops,
-	&sh7305_cpu_clk_ops,
+static struct clk_hw *sh7305_main_clks[] = {
+	&sh7305_master_clk,
+	&sh7305_peripheral_clk.hw,
+	&sh7305_bus_clk.hw,
+	&sh7305_cpu_clk.hw,
 };
 
-void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
+static const struct {
+	struct clk_hw *hw;
+	const char *con_id;
+} sh7305_clk_lookups[] = {
+	{ &sh7305_master_clk, "master_clk" },
+	{ &sh7305_peripheral_clk.hw, "peripheral_clk" },
+	{ &sh7305_bus_clk.hw, "bus_clk" },
+	{ &sh7305_cpu_clk.hw, "cpu_clk" },
+};
+
+#define SH7305_MAIN_CLK_COUNT	ARRAY_SIZE(sh7305_main_clks)
+#define SH7305_LOOKUP_COUNT	(SH7305_MAIN_CLK_COUNT + 1)
+
+static struct clk_lookup *sh7305_lookups[SH7305_LOOKUP_COUNT];
+static struct clk_hw *sh7305_tmu0_clk;
+
+static DEFINE_SPINLOCK(sh7305_mstp_lock);
+
+static void sh7305_clk_unregister_lookups(void)
 {
-	if (idx < ARRAY_SIZE(sh7305_clk_ops))
-		*ops = sh7305_clk_ops[idx];
+	int i;
+
+	for (i = SH7305_LOOKUP_COUNT - 1; i >= 0; i--) {
+		if (sh7305_lookups[i]) {
+			clkdev_drop(sh7305_lookups[i]);
+			sh7305_lookups[i] = NULL;
+		}
+	}
 }
 
-int __init arch_clk_init(void)
+static void sh7305_clk_unregister_all(unsigned int registered)
 {
-	return cpg_clk_init();
+	/* Remove clkdev references before unregistering their clocks. */
+	sh7305_clk_unregister_lookups();
+
+	if (sh7305_tmu0_clk) {
+		clk_hw_unregister_gate(sh7305_tmu0_clk);
+		sh7305_tmu0_clk = NULL;
+	}
+
+	while (registered--)
+		clk_hw_unregister(sh7305_main_clks[registered]);
+
+	if (sh7305_cpg_base) {
+		iounmap(sh7305_cpg_base);
+		sh7305_cpg_base = NULL;
+	}
+}
+
+int __init sh7305_clk_init(void)
+{
+	unsigned int i, registered = 0;
+	int ret;
+
+	sh7305_cpg_base = ioremap(SH7305_FRQCR,
+				  SH7305_FLLFRQ - SH7305_FRQCR + sizeof(u32));
+	if (!sh7305_cpg_base)
+		return -ENOMEM;
+
+	for (i = 0; i < SH7305_MAIN_CLK_COUNT; i++) {
+		ret = clk_hw_register(NULL, sh7305_main_clks[i]);
+		if (ret)
+			goto err_unregister;
+
+		registered++;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sh7305_clk_lookups); i++) {
+		sh7305_lookups[i] =
+			clkdev_hw_create(sh7305_clk_lookups[i].hw,
+					 sh7305_clk_lookups[i].con_id, NULL);
+		if (!sh7305_lookups[i]) {
+			ret = -ENOMEM;
+			goto err_unregister;
+		}
+	}
+
+	/*
+	 * MSTPCR0 bit 15 is active-high stop control.
+	 * CLK_GATE_SET_TO_DISABLE describes this polarity without
+	 * changing the hardware state during registration.
+	 */
+	sh7305_tmu0_clk =
+		clk_hw_register_gate(NULL, "tmu0_fck", "peripheral_clk", 0,
+				     sh7305_cpg_base +
+				     (SH7305_MSTPCR0 - SH7305_FRQCR),
+				     15, CLK_GATE_SET_TO_DISABLE,
+				     &sh7305_mstp_lock);
+	if (IS_ERR(sh7305_tmu0_clk)) {
+		ret = PTR_ERR(sh7305_tmu0_clk);
+		sh7305_tmu0_clk = NULL;
+		goto err_unregister;
+	}
+
+	sh7305_lookups[SH7305_MAIN_CLK_COUNT] =
+		clkdev_hw_create(sh7305_tmu0_clk, "fck", "sh-tmu.0");
+	if (!sh7305_lookups[SH7305_MAIN_CLK_COUNT]) {
+		ret = -ENOMEM;
+		goto err_unregister;
+	}
+
+	return 0;
+
+err_unregister:
+	sh7305_clk_unregister_all(registered);
+	return ret;
 }
-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v4 2/2] sh: sh7305: exclude from legacy CPG clock framework
  2026-11-11  1:07 [PATCH v4 0/2] sh: sh7305: add TMU0 clock support Artem Novak
  2026-11-11  1:07 ` [PATCH v4 1/2] " Artem Novak
@ 2026-11-11  1:07 ` Artem Novak
  1 sibling, 0 replies; 3+ messages in thread
From: Artem Novak @ 2026-11-11  1:07 UTC (permalink / raw)
  To: ysato, dalias, glaubitz, geert+renesas
  Cc: linux-sh, linux-kernel, Artem Novak

SH7305 now uses its own Common Clock Framework clock
implementation.

Exclude SH7305 from SH_CLK_CPG_LEGACY to prevent the
legacy CPG clock framework from being enabled for this
CPU subtype.

Signed-off-by: Artem Novak <artem122novak@gmail.com>
---
 arch/sh/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 5ce7df11c3ec..c5cc486eb1a3 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -536,7 +536,7 @@ config SH_CLK_CPG_LEGACY
 	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
 		      !CPU_SHX3 && !CPU_SUBTYPE_SH7757 && \
 		      !CPU_SUBTYPE_SH7734 && !CPU_SUBTYPE_SH7264 && \
-		      !CPU_SUBTYPE_SH7269
+		      !CPU_SUBTYPE_SH7269 && !CPU_SUBTYPE_SH7305
 
 endmenu
 
-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-11  1:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11  1:07 [PATCH v4 0/2] sh: sh7305: add TMU0 clock support Artem Novak
2026-11-11  1:07 ` [PATCH v4 1/2] " Artem Novak
2026-11-11  1:07 ` [PATCH v4 2/2] sh: sh7305: exclude from legacy CPG clock framework Artem Novak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®