xref: /linux/drivers/clk/renesas/r9a09g077-cpg.c (revision 09d50e09fab65f42d4656e9b01f225db7d311348)
1065fe720SThierry Bultel // SPDX-License-Identifier: GPL-2.0
2065fe720SThierry Bultel /*
3065fe720SThierry Bultel  * r9a09g077 Clock Pulse Generator / Module Standby and Software Reset
4065fe720SThierry Bultel  *
5065fe720SThierry Bultel  * Copyright (C) 2025 Renesas Electronics Corp.
6065fe720SThierry Bultel  *
7065fe720SThierry Bultel  */
8065fe720SThierry Bultel 
9065fe720SThierry Bultel #include <linux/bitfield.h>
10065fe720SThierry Bultel #include <linux/clk-provider.h>
11065fe720SThierry Bultel #include <linux/device.h>
12065fe720SThierry Bultel #include <linux/init.h>
13065fe720SThierry Bultel #include <linux/kernel.h>
14065fe720SThierry Bultel 
15065fe720SThierry Bultel #include <dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h>
168b8ca279SLad Prabhakar #include <dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h>
17065fe720SThierry Bultel #include "renesas-cpg-mssr.h"
18065fe720SThierry Bultel 
19065fe720SThierry Bultel #define RZT2H_REG_BLOCK_SHIFT	11
20065fe720SThierry Bultel #define RZT2H_REG_OFFSET_MASK	GENMASK(10, 0)
21065fe720SThierry Bultel #define RZT2H_REG_CONF(block, offset)	(((block) << RZT2H_REG_BLOCK_SHIFT) | \
22065fe720SThierry Bultel 					((offset) & RZT2H_REG_OFFSET_MASK))
23065fe720SThierry Bultel 
24065fe720SThierry Bultel #define RZT2H_REG_BLOCK(x)		((x) >> RZT2H_REG_BLOCK_SHIFT)
25065fe720SThierry Bultel #define RZT2H_REG_OFFSET(x)		((x) & RZT2H_REG_OFFSET_MASK)
26065fe720SThierry Bultel 
27065fe720SThierry Bultel #define SCKCR		RZT2H_REG_CONF(0, 0x00)
28065fe720SThierry Bultel #define SCKCR2		RZT2H_REG_CONF(1, 0x04)
29065fe720SThierry Bultel #define SCKCR3		RZT2H_REG_CONF(0, 0x08)
30065fe720SThierry Bultel 
31065fe720SThierry Bultel #define OFFSET_MASK	GENMASK(31, 20)
32065fe720SThierry Bultel #define SHIFT_MASK	GENMASK(19, 12)
33065fe720SThierry Bultel #define WIDTH_MASK	GENMASK(11, 8)
34065fe720SThierry Bultel 
35065fe720SThierry Bultel #define CONF_PACK(offset, shift, width)  \
36065fe720SThierry Bultel 	(FIELD_PREP_CONST(OFFSET_MASK, (offset)) | \
37065fe720SThierry Bultel 	FIELD_PREP_CONST(SHIFT_MASK, (shift)) | \
38065fe720SThierry Bultel 	FIELD_PREP_CONST(WIDTH_MASK, (width)))
39065fe720SThierry Bultel 
40065fe720SThierry Bultel #define GET_SHIFT(val)         FIELD_GET(SHIFT_MASK, val)
41065fe720SThierry Bultel #define GET_WIDTH(val)         FIELD_GET(WIDTH_MASK, val)
42065fe720SThierry Bultel #define GET_REG_OFFSET(val)    FIELD_GET(OFFSET_MASK, val)
43065fe720SThierry Bultel 
44065fe720SThierry Bultel #define DIVCA55C0	CONF_PACK(SCKCR2, 8, 1)
45065fe720SThierry Bultel #define DIVCA55C1	CONF_PACK(SCKCR2, 9, 1)
46065fe720SThierry Bultel #define DIVCA55C2	CONF_PACK(SCKCR2, 10, 1)
47065fe720SThierry Bultel #define DIVCA55C3	CONF_PACK(SCKCR2, 11, 1)
48065fe720SThierry Bultel #define DIVCA55S	CONF_PACK(SCKCR2, 12, 1)
49065fe720SThierry Bultel 
50065fe720SThierry Bultel #define DIVSCI0ASYNC	CONF_PACK(SCKCR3, 6, 2)
51065fe720SThierry Bultel 
52065fe720SThierry Bultel #define SEL_PLL		CONF_PACK(SCKCR, 22, 1)
53065fe720SThierry Bultel 
54065fe720SThierry Bultel 
55065fe720SThierry Bultel enum rzt2h_clk_types {
56065fe720SThierry Bultel 	CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM,	/* Clock with divider */
57065fe720SThierry Bultel 	CLK_TYPE_RZT2H_MUX,			/* Clock with clock source selector */
58065fe720SThierry Bultel };
59065fe720SThierry Bultel 
60065fe720SThierry Bultel #define DEF_DIV(_name, _id, _parent, _conf, _dtable) \
61065fe720SThierry Bultel 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_DIV, .conf = _conf, \
62065fe720SThierry Bultel 		 .parent = _parent, .dtable = _dtable, .flag = 0)
63065fe720SThierry Bultel #define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _mux_flags) \
64065fe720SThierry Bultel 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_MUX, .conf = _conf, \
65065fe720SThierry Bultel 		 .parent_names = _parent_names, .num_parents = _num_parents, \
66065fe720SThierry Bultel 		 .flag = 0, .mux_flags = _mux_flags)
67065fe720SThierry Bultel 
68065fe720SThierry Bultel enum clk_ids {
69065fe720SThierry Bultel 	/* Core Clock Outputs exported to DT */
70*09d50e09SLad Prabhakar 	LAST_DT_CORE_CLK = R9A09G077_SDHI_CLKHS,
71065fe720SThierry Bultel 
72065fe720SThierry Bultel 	/* External Input Clocks */
73065fe720SThierry Bultel 	CLK_EXTAL,
74065fe720SThierry Bultel 
75065fe720SThierry Bultel 	/* Internal Core Clocks */
76065fe720SThierry Bultel 	CLK_LOCO,
77065fe720SThierry Bultel 	CLK_PLL0,
78065fe720SThierry Bultel 	CLK_PLL1,
79*09d50e09SLad Prabhakar 	CLK_PLL2,
80065fe720SThierry Bultel 	CLK_PLL4,
81065fe720SThierry Bultel 	CLK_SEL_CLK_PLL0,
82065fe720SThierry Bultel 	CLK_SEL_CLK_PLL1,
83*09d50e09SLad Prabhakar 	CLK_SEL_CLK_PLL2,
84065fe720SThierry Bultel 	CLK_SEL_CLK_PLL4,
85065fe720SThierry Bultel 	CLK_PLL4D1,
86065fe720SThierry Bultel 	CLK_SCI0ASYNC,
87065fe720SThierry Bultel 
88065fe720SThierry Bultel 	/* Module Clocks */
89065fe720SThierry Bultel 	MOD_CLK_BASE,
90065fe720SThierry Bultel };
91065fe720SThierry Bultel 
92065fe720SThierry Bultel static const struct clk_div_table dtable_1_2[] = {
93065fe720SThierry Bultel 	{0, 2},
94065fe720SThierry Bultel 	{1, 1},
95065fe720SThierry Bultel 	{0, 0},
96065fe720SThierry Bultel };
97065fe720SThierry Bultel 
98065fe720SThierry Bultel static const struct clk_div_table dtable_24_25_30_32[] = {
99065fe720SThierry Bultel 	{0, 32},
100065fe720SThierry Bultel 	{1, 30},
101065fe720SThierry Bultel 	{2, 25},
102065fe720SThierry Bultel 	{3, 24},
103065fe720SThierry Bultel 	{0, 0},
104065fe720SThierry Bultel };
105065fe720SThierry Bultel 
106065fe720SThierry Bultel /* Mux clock tables */
107065fe720SThierry Bultel 
108065fe720SThierry Bultel static const char * const sel_clk_pll0[] = { ".loco", ".pll0" };
109065fe720SThierry Bultel static const char * const sel_clk_pll1[] = { ".loco", ".pll1" };
110*09d50e09SLad Prabhakar static const char * const sel_clk_pll2[] = { ".loco", ".pll2" };
111065fe720SThierry Bultel static const char * const sel_clk_pll4[] = { ".loco", ".pll4" };
112065fe720SThierry Bultel 
113065fe720SThierry Bultel static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = {
114065fe720SThierry Bultel 	/* External Clock Inputs */
115065fe720SThierry Bultel 	DEF_INPUT("extal", CLK_EXTAL),
116065fe720SThierry Bultel 
117065fe720SThierry Bultel 	/* Internal Core Clocks */
118065fe720SThierry Bultel 	DEF_RATE(".loco", CLK_LOCO, 1000 * 1000),
119065fe720SThierry Bultel 	DEF_FIXED(".pll0", CLK_PLL0, CLK_EXTAL, 1, 48),
120065fe720SThierry Bultel 	DEF_FIXED(".pll1", CLK_PLL1, CLK_EXTAL, 1, 40),
121*09d50e09SLad Prabhakar 	DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 1, 32),
122065fe720SThierry Bultel 	DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 1, 96),
123065fe720SThierry Bultel 
124065fe720SThierry Bultel 	DEF_MUX(".sel_clk_pll0", CLK_SEL_CLK_PLL0, SEL_PLL,
125065fe720SThierry Bultel 		sel_clk_pll0, ARRAY_SIZE(sel_clk_pll0), CLK_MUX_READ_ONLY),
126065fe720SThierry Bultel 	DEF_MUX(".sel_clk_pll1", CLK_SEL_CLK_PLL1, SEL_PLL,
127065fe720SThierry Bultel 		sel_clk_pll1, ARRAY_SIZE(sel_clk_pll1), CLK_MUX_READ_ONLY),
128*09d50e09SLad Prabhakar 	DEF_MUX(".sel_clk_pll2", CLK_SEL_CLK_PLL2, SEL_PLL,
129*09d50e09SLad Prabhakar 		sel_clk_pll2, ARRAY_SIZE(sel_clk_pll2), CLK_MUX_READ_ONLY),
130065fe720SThierry Bultel 	DEF_MUX(".sel_clk_pll4", CLK_SEL_CLK_PLL4, SEL_PLL,
131065fe720SThierry Bultel 		sel_clk_pll4, ARRAY_SIZE(sel_clk_pll4), CLK_MUX_READ_ONLY),
132065fe720SThierry Bultel 
133065fe720SThierry Bultel 	DEF_FIXED(".pll4d1", CLK_PLL4D1, CLK_SEL_CLK_PLL4, 1, 1),
134065fe720SThierry Bultel 	DEF_DIV(".sci0async", CLK_SCI0ASYNC, CLK_PLL4D1, DIVSCI0ASYNC,
135065fe720SThierry Bultel 		dtable_24_25_30_32),
136065fe720SThierry Bultel 
137065fe720SThierry Bultel 	/* Core output clk */
138065fe720SThierry Bultel 	DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0,
139065fe720SThierry Bultel 		dtable_1_2),
140065fe720SThierry Bultel 	DEF_DIV("CA55C1", R9A09G077_CLK_CA55C1, CLK_SEL_CLK_PLL0, DIVCA55C1,
141065fe720SThierry Bultel 		dtable_1_2),
142065fe720SThierry Bultel 	DEF_DIV("CA55C2", R9A09G077_CLK_CA55C2, CLK_SEL_CLK_PLL0, DIVCA55C2,
143065fe720SThierry Bultel 		dtable_1_2),
144065fe720SThierry Bultel 	DEF_DIV("CA55C3", R9A09G077_CLK_CA55C3, CLK_SEL_CLK_PLL0, DIVCA55C3,
145065fe720SThierry Bultel 		dtable_1_2),
146065fe720SThierry Bultel 	DEF_DIV("CA55S", R9A09G077_CLK_CA55S, CLK_SEL_CLK_PLL0, DIVCA55S,
147065fe720SThierry Bultel 		dtable_1_2),
148065fe720SThierry Bultel 	DEF_FIXED("PCLKGPTL", R9A09G077_CLK_PCLKGPTL, CLK_SEL_CLK_PLL1, 2, 1),
149065fe720SThierry Bultel 	DEF_FIXED("PCLKM", R9A09G077_CLK_PCLKM, CLK_SEL_CLK_PLL1, 8, 1),
150275e2b54SLad Prabhakar 	DEF_FIXED("PCLKL", R9A09G077_CLK_PCLKL, CLK_SEL_CLK_PLL1, 16, 1),
151*09d50e09SLad Prabhakar 	DEF_FIXED("PCLKAM", R9A09G077_CLK_PCLKAM, CLK_PLL4D1, 12, 1),
152*09d50e09SLad Prabhakar 	DEF_FIXED("SDHI_CLKHS", R9A09G077_SDHI_CLKHS, CLK_SEL_CLK_PLL2, 1, 1),
153065fe720SThierry Bultel };
154065fe720SThierry Bultel 
155065fe720SThierry Bultel static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = {
156065fe720SThierry Bultel 	DEF_MOD("sci0fck", 8, CLK_SCI0ASYNC),
157*09d50e09SLad Prabhakar 	DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM),
158*09d50e09SLad Prabhakar 	DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM),
159065fe720SThierry Bultel };
160065fe720SThierry Bultel 
161065fe720SThierry Bultel static struct clk * __init
162065fe720SThierry Bultel r9a09g077_cpg_div_clk_register(struct device *dev,
163065fe720SThierry Bultel 			       const struct cpg_core_clk *core,
164065fe720SThierry Bultel 			       void __iomem *addr, struct cpg_mssr_pub *pub)
165065fe720SThierry Bultel {
166065fe720SThierry Bultel 	const struct clk *parent;
167065fe720SThierry Bultel 	const char *parent_name;
168065fe720SThierry Bultel 	struct clk_hw *clk_hw;
169065fe720SThierry Bultel 
170065fe720SThierry Bultel 	parent = pub->clks[core->parent];
171065fe720SThierry Bultel 	if (IS_ERR(parent))
172065fe720SThierry Bultel 		return ERR_CAST(parent);
173065fe720SThierry Bultel 
174065fe720SThierry Bultel 	parent_name = __clk_get_name(parent);
175065fe720SThierry Bultel 
176065fe720SThierry Bultel 	if (core->dtable)
177065fe720SThierry Bultel 		clk_hw = clk_hw_register_divider_table(dev, core->name,
178065fe720SThierry Bultel 						       parent_name, 0,
179065fe720SThierry Bultel 						       addr,
180065fe720SThierry Bultel 						       GET_SHIFT(core->conf),
181065fe720SThierry Bultel 						       GET_WIDTH(core->conf),
182065fe720SThierry Bultel 						       core->flag,
183065fe720SThierry Bultel 						       core->dtable,
184065fe720SThierry Bultel 						       &pub->rmw_lock);
185065fe720SThierry Bultel 	else
186065fe720SThierry Bultel 		clk_hw = clk_hw_register_divider(dev, core->name,
187065fe720SThierry Bultel 						 parent_name, 0,
188065fe720SThierry Bultel 						 addr,
189065fe720SThierry Bultel 						 GET_SHIFT(core->conf),
190065fe720SThierry Bultel 						 GET_WIDTH(core->conf),
191065fe720SThierry Bultel 						 core->flag, &pub->rmw_lock);
192065fe720SThierry Bultel 
193065fe720SThierry Bultel 	if (IS_ERR(clk_hw))
194065fe720SThierry Bultel 		return ERR_CAST(clk_hw);
195065fe720SThierry Bultel 
196065fe720SThierry Bultel 	return clk_hw->clk;
197065fe720SThierry Bultel 
198065fe720SThierry Bultel }
199065fe720SThierry Bultel 
200065fe720SThierry Bultel static struct clk * __init
201065fe720SThierry Bultel r9a09g077_cpg_mux_clk_register(struct device *dev,
202065fe720SThierry Bultel 			       const struct cpg_core_clk *core,
203065fe720SThierry Bultel 			       void __iomem *addr, struct cpg_mssr_pub *pub)
204065fe720SThierry Bultel {
205065fe720SThierry Bultel 	struct clk_hw *clk_hw;
206065fe720SThierry Bultel 
207065fe720SThierry Bultel 	clk_hw = devm_clk_hw_register_mux(dev, core->name,
208065fe720SThierry Bultel 					  core->parent_names, core->num_parents,
209065fe720SThierry Bultel 					  core->flag,
210065fe720SThierry Bultel 					  addr,
211065fe720SThierry Bultel 					  GET_SHIFT(core->conf),
212065fe720SThierry Bultel 					  GET_WIDTH(core->conf),
213065fe720SThierry Bultel 					  core->mux_flags, &pub->rmw_lock);
214065fe720SThierry Bultel 	if (IS_ERR(clk_hw))
215065fe720SThierry Bultel 		return ERR_CAST(clk_hw);
216065fe720SThierry Bultel 
217065fe720SThierry Bultel 	return clk_hw->clk;
218065fe720SThierry Bultel }
219065fe720SThierry Bultel 
220065fe720SThierry Bultel static struct clk * __init
221065fe720SThierry Bultel r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core,
222065fe720SThierry Bultel 			   const struct cpg_mssr_info *info,
223065fe720SThierry Bultel 			   struct cpg_mssr_pub *pub)
224065fe720SThierry Bultel {
225065fe720SThierry Bultel 	u32 offset = GET_REG_OFFSET(core->conf);
226065fe720SThierry Bultel 	void __iomem *base = RZT2H_REG_BLOCK(offset) ? pub->base1 : pub->base0;
227065fe720SThierry Bultel 	void __iomem *addr = base + RZT2H_REG_OFFSET(offset);
228065fe720SThierry Bultel 
229065fe720SThierry Bultel 	switch (core->type) {
230065fe720SThierry Bultel 	case CLK_TYPE_RZT2H_DIV:
231065fe720SThierry Bultel 		return r9a09g077_cpg_div_clk_register(dev, core, addr, pub);
232065fe720SThierry Bultel 	case CLK_TYPE_RZT2H_MUX:
233065fe720SThierry Bultel 		return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub);
234065fe720SThierry Bultel 	default:
235065fe720SThierry Bultel 		return ERR_PTR(-EINVAL);
236065fe720SThierry Bultel 	}
237065fe720SThierry Bultel }
238065fe720SThierry Bultel 
239065fe720SThierry Bultel const struct cpg_mssr_info r9a09g077_cpg_mssr_info = {
240065fe720SThierry Bultel 	/* Core Clocks */
241065fe720SThierry Bultel 	.core_clks = r9a09g077_core_clks,
242065fe720SThierry Bultel 	.num_core_clks = ARRAY_SIZE(r9a09g077_core_clks),
243065fe720SThierry Bultel 	.last_dt_core_clk = LAST_DT_CORE_CLK,
244065fe720SThierry Bultel 	.num_total_core_clks = MOD_CLK_BASE,
245065fe720SThierry Bultel 
246065fe720SThierry Bultel 	/* Module Clocks */
247065fe720SThierry Bultel 	.mod_clks = r9a09g077_mod_clks,
248065fe720SThierry Bultel 	.num_mod_clks = ARRAY_SIZE(r9a09g077_mod_clks),
249065fe720SThierry Bultel 	.num_hw_mod_clks = 14 * 32,
250065fe720SThierry Bultel 
251065fe720SThierry Bultel 	.reg_layout = CLK_REG_LAYOUT_RZ_T2H,
252065fe720SThierry Bultel 	.cpg_clk_register = r9a09g077_cpg_clk_register,
253065fe720SThierry Bultel };
254