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