1 /*
2  * Copyright (c) 2023 TOKITA Hiroshi <tokita.hiroshi@fujitsu.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 #define DT_DRV_COMPAT renesas_ra_clock_generation_circuit
10 
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/kernel.h>
13 #include <soc.h>
14 #include <zephyr/dt-bindings/clock/renesas-ra-cgc.h>
15 
16 #if DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, pll))
17 #define SYSCLK_SRC pll
18 #elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, mosc))
19 #define SYSCLK_SRC mosc
20 #elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, sosc))
21 #define SYSCLK_SRC sosc
22 #elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, hoco))
23 #define SYSCLK_SRC hoco
24 #elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, moco))
25 #define SYSCLK_SRC moco
26 #elif DT_SAME_NODE(DT_INST_PROP(0, clock_source), DT_PATH(clocks, loco))
27 #define SYSCLK_SRC loco
28 #else
29 #error Unknown clock source
30 #endif
31 
32 #define FREQ_iclk  (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, iclk_div))
33 #define FREQ_pclka (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclka_div))
34 #define FREQ_pclkb (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkb_div))
35 #define FREQ_pclkc (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkc_div))
36 #define FREQ_pclkd (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, pclkd_div))
37 #define FREQ_fclk  (clock_freqs[_CONCAT(SCRSCK_, SYSCLK_SRC)] / DT_INST_PROP(0, fclk_div))
38 
39 #define CLKSRC_FREQ(clk) DT_PROP(DT_PATH(clocks, clk), clock_frequency)
40 
41 #define IS_CLKSRC_ENABLED(clk) DT_NODE_HAS_STATUS(DT_PATH(clocks, clk), okay)
42 
43 #define SCKSCR_INIT_VALUE _CONCAT(CLKSRC_, SYSCLK_SRC)
44 
45 #define SCKDIV_ENABLED(clk) DT_INST_NODE_HAS_PROP(0, clk##_div)
46 #define SCKDIV_VAL(clk)     _CONCAT(SCKDIV_, DT_INST_PROP(0, clk##_div))
47 #define SCKDIV_POS(clk)     _CONCAT(SCKDIV_POS_, clk)
48 
49 #define SCKDIVCR_BITS(clk)                                                                         \
50 	COND_CODE_1(SCKDIV_ENABLED(clk), ((SCKDIV_VAL(clk) & 0xFU) << SCKDIV_POS(clk)), (0U))
51 
52 #define SCKDIVCR_INIT_VALUE                                                                        \
53 	(SCKDIVCR_BITS(iclk) | SCKDIVCR_BITS(pclka) | SCKDIVCR_BITS(pclkb) |                       \
54 	 SCKDIVCR_BITS(pclkc) | SCKDIVCR_BITS(pclkd) | SCKDIVCR_BITS(bclk) | SCKDIVCR_BITS(fclk))
55 
56 #define HOCOWTCR_INIT_VALUE (6)
57 
58 /*
59  * Required cycles for sub-clokc stabilizing.
60  */
61 #define SUBCLK_STABILIZE_CYCLES 5
62 
63 extern int z_clock_hw_cycles_per_sec;
64 
65 enum {
66 	CLKSRC_hoco = 0,
67 	CLKSRC_moco,
68 	CLKSRC_loco,
69 	CLKSRC_mosc,
70 	CLKSRC_sosc,
71 	CLKSRC_pll,
72 };
73 
74 enum {
75 	SCKDIV_1 = 0,
76 	SCKDIV_2,
77 	SCKDIV_4,
78 	SCKDIV_8,
79 	SCKDIV_16,
80 	SCKDIV_32,
81 	SCKDIV_64,
82 	SCKDIV_128,
83 	SCKDIV_3,
84 	SCKDIV_6,
85 	SCKDIV_12
86 };
87 
88 enum {
89 	SCKDIV_POS_pclkd = 0x0U,
90 	SCKDIV_POS_pclkc = 0x4U,
91 	SCKDIV_POS_pclkb = 0x8U,
92 	SCKDIV_POS_pclka = 0xcU,
93 	SCKDIV_POS_bclk = 0x10U,
94 	SCKDIV_POS_pclke = 0x14U,
95 	SCKDIV_POS_iclk = 0x18U,
96 	SCKDIV_POS_fclk = 0x1cU
97 };
98 
99 enum {
100 	OSCSF_HOCOSF_POS = 0,
101 	OSCSF_MOSCSF_POS = 3,
102 	OSCSF_PLLSF_POS = 5,
103 };
104 
105 enum {
106 	OPCCR_OPCMTSF_POS = 4,
107 };
108 
109 static const uint32_t PRCR_KEY = 0xA500U;
110 static const uint32_t PRCR_CLOCKS = 0x1U;
111 static const uint32_t PRCR_LOW_POWER = 0x2U;
112 
113 enum {
114 #if DT_INST_REG_SIZE_BY_NAME(0, mstp) == 16
115 	MSTPCRA_OFFSET = -0x4,
116 #else
117 	MSTPCRA_OFFSET = 0x0,
118 #endif
119 	MSTPCRB_OFFSET = (MSTPCRA_OFFSET + 0x4),
120 	MSTPCRC_OFFSET = (MSTPCRB_OFFSET + 0x4),
121 	MSTPCRD_OFFSET = (MSTPCRC_OFFSET + 0x4),
122 	MSTPCRE_OFFSET = (MSTPCRD_OFFSET + 0x4),
123 };
124 
125 enum {
126 	SCKDIVCR_OFFSET = 0x020,
127 	SCKSCR_OFFSET = 0x026,
128 	MEMWAIT_OFFSET = 0x031,
129 	MOSCCR_OFFSET = 0x032,
130 	HOCOCR_OFFSET = 0x036,
131 	OSCSF_OFFSET = 0x03C,
132 	CKOCR_OFFSET = 0x03E,
133 	OPCCR_OFFSET = 0x0A0,
134 	HOCOWTCR_OFFSET = 0x0A5,
135 	PRCR_OFFSET = 0x3FE,
136 	SOSCCR_OFFSET = 0x480,
137 };
138 
139 enum {
140 	SCRSCK_hoco,
141 	SCRSCK_moco,
142 	SCRSCK_loco,
143 	SCRSCK_mosc,
144 	SCRSCK_sosc,
145 	SCRSCK_pll,
146 };
147 
148 static const int clock_freqs[] = {
149 	COND_CODE_1(IS_CLKSRC_ENABLED(hoco), (CLKSRC_FREQ(hoco)), (0)),
150 	COND_CODE_1(IS_CLKSRC_ENABLED(moco), (CLKSRC_FREQ(moco)), (0)),
151 	COND_CODE_1(IS_CLKSRC_ENABLED(loco), (CLKSRC_FREQ(loco)), (0)),
152 	COND_CODE_1(IS_CLKSRC_ENABLED(mosc), (CLKSRC_FREQ(mosc)), (0)),
153 	COND_CODE_1(IS_CLKSRC_ENABLED(sosc), (CLKSRC_FREQ(sosc)), (0)),
154 	COND_CODE_1(IS_CLKSRC_ENABLED(pll),
155 		    (DT_PROP(DT_PHANDLE_BY_IDX(DT_PATH(clocks, pll), clocks, 0), clock_frequency) *
156 		     DT_PROP(DT_PATH(clocks, pll), clock_mult) /
157 		     DT_PROP(DT_PATH(clocks, pll), clock_div)),
158 		    (0)),
159 };
160 
MSTP_read(size_t offset)161 static uint32_t MSTP_read(size_t offset)
162 {
163 	return sys_read32(DT_INST_REG_ADDR_BY_NAME(0, mstp) + offset);
164 }
165 
MSTP_write(size_t offset,uint32_t value)166 static void MSTP_write(size_t offset, uint32_t value)
167 {
168 	sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, mstp) + offset);
169 }
170 
SYSTEM_read8(size_t offset)171 static uint8_t SYSTEM_read8(size_t offset)
172 {
173 	return sys_read8(DT_INST_REG_ADDR_BY_NAME(0, system) + offset);
174 }
175 
SYSTEM_write8(size_t offset,uint8_t value)176 static void SYSTEM_write8(size_t offset, uint8_t value)
177 {
178 	sys_write8(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset);
179 }
180 
SYSTEM_write16(size_t offset,uint16_t value)181 static void SYSTEM_write16(size_t offset, uint16_t value)
182 {
183 	sys_write16(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset);
184 }
185 
SYSTEM_write32(size_t offset,uint32_t value)186 static void SYSTEM_write32(size_t offset, uint32_t value)
187 {
188 	sys_write32(value, DT_INST_REG_ADDR_BY_NAME(0, system) + offset);
189 }
190 
clock_control_ra_on(const struct device * dev,clock_control_subsys_t subsys)191 static int clock_control_ra_on(const struct device *dev, clock_control_subsys_t subsys)
192 {
193 	uint32_t clkid = (uint32_t)subsys;
194 	int lock = irq_lock();
195 
196 	MSTP_write(MSTPCRA_OFFSET + RA_CLOCK_GROUP(clkid),
197 		   MSTP_read(MSTPCRB_OFFSET) & ~RA_CLOCK_BIT(clkid));
198 	irq_unlock(lock);
199 
200 	return 0;
201 }
202 
clock_control_ra_off(const struct device * dev,clock_control_subsys_t subsys)203 static int clock_control_ra_off(const struct device *dev, clock_control_subsys_t subsys)
204 {
205 	uint32_t clkid = (uint32_t)subsys;
206 	int lock = irq_lock();
207 
208 	MSTP_write(MSTPCRA_OFFSET + RA_CLOCK_GROUP(clkid),
209 		   MSTP_read(MSTPCRB_OFFSET) | RA_CLOCK_BIT(clkid));
210 	irq_unlock(lock);
211 
212 	return 0;
213 }
214 
clock_control_ra_get_rate(const struct device * dev,clock_control_subsys_t subsys,uint32_t * rate)215 static int clock_control_ra_get_rate(const struct device *dev, clock_control_subsys_t subsys,
216 				     uint32_t *rate)
217 {
218 	uint32_t clkid = (uint32_t)subsys;
219 
220 	switch (clkid & 0xFFFFFF00) {
221 	case RA_CLOCK_SCI(0):
222 		*rate = FREQ_pclka;
223 		break;
224 	default:
225 		return -EINVAL;
226 	}
227 
228 	return 0;
229 }
230 
231 static const struct clock_control_driver_api ra_clock_control_driver_api = {
232 	.on = clock_control_ra_on,
233 	.off = clock_control_ra_off,
234 	.get_rate = clock_control_ra_get_rate,
235 };
236 
crude_busy_loop_impl(uint32_t cycles)237 static void crude_busy_loop_impl(uint32_t cycles)
238 {
239 	__asm__ volatile(".align 8\n"
240 			 "busy_loop:\n"
241 			 "	sub	r0, r0, #1\n"
242 			 "	cmp	r0, #0\n"
243 			 "	bne.n	busy_loop\n");
244 }
245 
crude_busy_loop(uint32_t wait_us)246 static inline void crude_busy_loop(uint32_t wait_us)
247 {
248 	static const uint64_t cycles_per_loop = 4;
249 
250 	crude_busy_loop_impl(sys_clock_hw_cycles_per_sec() * wait_us / USEC_PER_SEC /
251 			     cycles_per_loop);
252 }
253 
clock_control_ra_init(const struct device * dev)254 static int clock_control_ra_init(const struct device *dev)
255 {
256 	uint8_t sysclk = SYSTEM_read8(SCKSCR_OFFSET);
257 
258 	z_clock_hw_cycles_per_sec = clock_freqs[sysclk];
259 
260 	SYSTEM_write16(PRCR_OFFSET, PRCR_KEY | PRCR_CLOCKS | PRCR_LOW_POWER);
261 
262 	if (clock_freqs[SCRSCK_hoco] == 64000000) {
263 		SYSTEM_write8(HOCOWTCR_OFFSET, HOCOWTCR_INIT_VALUE);
264 	}
265 
266 	SYSTEM_write8(SOSCCR_OFFSET, !IS_CLKSRC_ENABLED(sosc));
267 	SYSTEM_write8(MOSCCR_OFFSET, !IS_CLKSRC_ENABLED(mosc));
268 	SYSTEM_write8(HOCOCR_OFFSET, !IS_CLKSRC_ENABLED(hoco));
269 
270 	if (IS_CLKSRC_ENABLED(sosc)) {
271 		crude_busy_loop(z_clock_hw_cycles_per_sec / clock_freqs[CLKSRC_sosc] *
272 				SUBCLK_STABILIZE_CYCLES);
273 	}
274 
275 	if (IS_CLKSRC_ENABLED(mosc)) {
276 		while ((SYSTEM_read8(OSCSF_OFFSET) & BIT(OSCSF_MOSCSF_POS)) !=
277 		       BIT(OSCSF_MOSCSF_POS)) {
278 			;
279 		}
280 	}
281 
282 	if (IS_CLKSRC_ENABLED(hoco)) {
283 		while ((SYSTEM_read8(OSCSF_OFFSET) & BIT(OSCSF_HOCOSF_POS)) !=
284 		       BIT(OSCSF_HOCOSF_POS)) {
285 			;
286 		}
287 	}
288 
289 	SYSTEM_write32(SCKDIVCR_OFFSET, SCKDIVCR_INIT_VALUE);
290 	SYSTEM_write8(SCKSCR_OFFSET, SCKSCR_INIT_VALUE);
291 
292 	/* re-read system clock setting and apply to hw_cycles */
293 	sysclk = SYSTEM_read8(SCKSCR_OFFSET);
294 	z_clock_hw_cycles_per_sec = clock_freqs[sysclk];
295 
296 	SYSTEM_write8(OPCCR_OFFSET, 0);
297 	while ((SYSTEM_read8(OPCCR_OFFSET) & BIT(OPCCR_OPCMTSF_POS)) != 0) {
298 		;
299 	}
300 
301 	SYSTEM_write8(MEMWAIT_OFFSET, 1);
302 	SYSTEM_write16(PRCR_OFFSET, PRCR_KEY);
303 
304 	return 0;
305 }
306 
307 DEVICE_DT_INST_DEFINE(0, &clock_control_ra_init, NULL, NULL, NULL, PRE_KERNEL_1,
308 		      CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &ra_clock_control_driver_api);
309