1 /*
2 * Copyright (c) 2022 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <assert.h>
8 #include <soc.h>
9 #include <zephyr/sys/onoff.h>
10 #include <zephyr/drivers/clock_control.h>
11 #include <zephyr/drivers/clock_control/smartbond_clock_control.h>
12 #include <zephyr/logging/log.h>
13 #include <da1469x_clock.h>
14
15 LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
16
17 #define DT_DRV_COMPAT smartbond_clock
18
19 struct lpc_clock_state {
20 uint8_t rcx_started : 1;
21 uint8_t rcx_ready : 1;
22 uint8_t rc32k_started : 1;
23 uint8_t rc32k_ready : 1;
24 uint8_t xtal32k_started : 1;
25 uint8_t xtal32k_ready : 1;
26 uint32_t rcx_freq;
27 uint32_t rc32k_freq;
28 } lpc_clock_state = {
29 .rcx_freq = DT_PROP(DT_NODELABEL(rcx), clock_frequency),
30 .rc32k_freq = DT_PROP(DT_NODELABEL(rc32k), clock_frequency),
31 };
32
33 #define CALIBRATION_INTERVAL (DT_NODE_HAS_STATUS(DT_NODELABEL(rcx), okay) ? \
34 DT_PROP(DT_NODELABEL(rcx), calibration_interval) : \
35 DT_PROP(DT_NODELABEL(rc32k), calibration_interval))
36
37 static void calibration_work_cb(struct k_work *work);
38 static void xtal32k_settle_work_cb(struct k_work *work);
39
40 static K_WORK_DELAYABLE_DEFINE(calibration_work, calibration_work_cb);
41 static K_WORK_DELAYABLE_DEFINE(xtal32k_settle_work, xtal32k_settle_work_cb);
42
calibration_work_cb(struct k_work * work)43 static void calibration_work_cb(struct k_work *work)
44 {
45 if (lpc_clock_state.rcx_started) {
46 da1469x_clock_lp_rcx_calibrate();
47 lpc_clock_state.rcx_ready = true;
48 lpc_clock_state.rcx_freq = da1469x_clock_lp_rcx_freq_get();
49 k_work_schedule(&calibration_work,
50 K_MSEC(1000 * CALIBRATION_INTERVAL));
51 LOG_DBG("RCX calibration done, RCX freq: %d",
52 (int)lpc_clock_state.rcx_freq);
53 } else if (lpc_clock_state.rc32k_started) {
54 da1469x_clock_lp_rc32k_calibrate();
55 lpc_clock_state.rc32k_ready = true;
56 lpc_clock_state.rc32k_freq = da1469x_clock_lp_rc32k_freq_get();
57 k_work_schedule(&calibration_work,
58 K_MSEC(1000 * CALIBRATION_INTERVAL));
59 LOG_DBG("RC32K calibration done, RC32K freq: %d",
60 (int)lpc_clock_state.rc32k_freq);
61 }
62 }
63
xtal32k_settle_work_cb(struct k_work * work)64 static void xtal32k_settle_work_cb(struct k_work *work)
65 {
66 if (lpc_clock_state.xtal32k_started && !lpc_clock_state.xtal32k_ready) {
67 LOG_DBG("XTAL32K settled.");
68 lpc_clock_state.xtal32k_ready = true;
69 }
70 }
71
smartbond_start_rc32k(void)72 static void smartbond_start_rc32k(void)
73 {
74 if ((CRG_TOP->CLK_RC32K_REG & CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk) == 0) {
75 CRG_TOP->CLK_RC32K_REG |= CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk;
76 }
77 lpc_clock_state.rc32k_started = true;
78 if (!lpc_clock_state.rc32k_ready && (CALIBRATION_INTERVAL > 0)) {
79 if (!k_work_is_pending(&calibration_work.work)) {
80 k_work_schedule(&calibration_work,
81 K_MSEC(1000 * CALIBRATION_INTERVAL));
82 }
83 }
84 }
85
smartbond_start_rcx(void)86 static void smartbond_start_rcx(void)
87 {
88 if (!lpc_clock_state.rcx_started) {
89 lpc_clock_state.rcx_ready = false;
90 da1469x_clock_lp_rcx_enable();
91 lpc_clock_state.rcx_started = true;
92 }
93 if (!lpc_clock_state.rcx_ready && (CALIBRATION_INTERVAL > 0)) {
94 if (!k_work_is_pending(&calibration_work.work)) {
95 k_work_schedule(&calibration_work,
96 K_MSEC(1000 * CALIBRATION_INTERVAL));
97 }
98 }
99 }
100
smartbond_start_xtal32k(void)101 static void smartbond_start_xtal32k(void)
102 {
103 if (!lpc_clock_state.xtal32k_started) {
104 lpc_clock_state.xtal32k_ready = false;
105 da1469x_clock_lp_xtal32k_enable();
106 lpc_clock_state.xtal32k_started = true;
107 k_work_schedule(&xtal32k_settle_work,
108 K_MSEC(DT_PROP(DT_NODELABEL(xtal32k),
109 settle_time)));
110 }
111 }
112
smartbond_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)113 static inline int smartbond_clock_control_on(const struct device *dev,
114 clock_control_subsys_t sub_system)
115 {
116 enum smartbond_clock clk = (enum smartbond_clock)(sub_system);
117
118 ARG_UNUSED(dev);
119
120 switch (clk) {
121 case SMARTBOND_CLK_RC32K:
122 smartbond_start_rc32k();
123 break;
124 case SMARTBOND_CLK_RCX:
125 smartbond_start_rcx();
126 break;
127 case SMARTBOND_CLK_XTAL32K:
128 smartbond_start_xtal32k();
129 break;
130 case SMARTBOND_CLK_RC32M:
131 CRG_TOP->CLK_RC32M_REG |= CRG_TOP_CLK_RC32M_REG_RC32M_ENABLE_Msk;
132 break;
133 case SMARTBOND_CLK_XTAL32M:
134 da1469x_clock_sys_xtal32m_init();
135 da1469x_clock_sys_xtal32m_enable();
136 break;
137 case SMARTBOND_CLK_PLL96M:
138 if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_PLL96M_Msk) == 0) {
139 if ((CRG_TOP->CLK_CTRL_REG &
140 CRG_TOP_CLK_CTRL_REG_RUNNING_AT_XTAL32M_Msk) == 0) {
141 da1469x_clock_sys_xtal32m_init();
142 da1469x_clock_sys_xtal32m_enable();
143 da1469x_clock_sys_xtal32m_wait_to_settle();
144 }
145 da1469x_clock_sys_pll_enable();
146 }
147 break;
148 default:
149 return -ENOTSUP;
150 }
151
152 return 0;
153 }
154
smartbond_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)155 static inline int smartbond_clock_control_off(const struct device *dev,
156 clock_control_subsys_t sub_system)
157 {
158 enum smartbond_clock clk = (enum smartbond_clock)(sub_system);
159
160 ARG_UNUSED(dev);
161
162 switch (clk) {
163 case SMARTBOND_CLK_RC32K:
164 if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
165 CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 0) {
166 CRG_TOP->CLK_RC32K_REG &= ~CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk;
167 lpc_clock_state.rc32k_ready = false;
168 lpc_clock_state.rc32k_started = false;
169 }
170 break;
171 case SMARTBOND_CLK_RCX:
172 if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
173 CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 1) {
174 CRG_TOP->CLK_RCX_REG &= ~CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk;
175 lpc_clock_state.rcx_ready = false;
176 lpc_clock_state.rcx_started = false;
177 }
178 break;
179 case SMARTBOND_CLK_XTAL32K:
180 if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
181 CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) > 1) {
182 CRG_TOP->CLK_XTAL32K_REG &= ~CRG_TOP_CLK_XTAL32K_REG_XTAL32K_ENABLE_Msk;
183 lpc_clock_state.xtal32k_ready = false;
184 lpc_clock_state.xtal32k_started = false;
185 }
186 break;
187 case SMARTBOND_CLK_RC32M:
188 /* Disable rc32m only if not used as system clock */
189 if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_RC32M_Msk) == 0) {
190 da1469x_clock_sys_rc32m_disable();
191 }
192 break;
193 case SMARTBOND_CLK_XTAL32M:
194 da1469x_clock_sys_xtal32m_init();
195 da1469x_clock_sys_xtal32m_enable();
196 break;
197 case SMARTBOND_CLK_PLL96M:
198 da1469x_clock_sys_pll_disable();
199 break;
200 default:
201 return -ENOTSUP;
202 }
203
204 return 0;
205 }
206
smartbond_source_clock(enum smartbond_clock clk)207 static enum smartbond_clock smartbond_source_clock(enum smartbond_clock clk)
208 {
209 static const enum smartbond_clock lp_clk_src[] = {
210 SMARTBOND_CLK_RC32K,
211 SMARTBOND_CLK_RCX,
212 SMARTBOND_CLK_XTAL32K,
213 SMARTBOND_CLK_XTAL32K,
214 };
215 static const enum smartbond_clock sys_clk_src[] = {
216 SMARTBOND_CLK_XTAL32M,
217 SMARTBOND_CLK_RC32M,
218 SMARTBOND_CLK_LP_CLK,
219 SMARTBOND_CLK_PLL96M,
220 };
221
222 if (clk == SMARTBOND_CLK_SYS_CLK) {
223 clk = sys_clk_src[CRG_TOP->CLK_CTRL_REG &
224 CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk];
225 }
226 /* System clock can be low power clock, so next check is not in else */
227 if (clk == SMARTBOND_CLK_LP_CLK) {
228 clk = lp_clk_src[(CRG_TOP->CLK_CTRL_REG &
229 CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
230 CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos];
231 }
232 return clk;
233 }
234
smartbond_clock_get_rate(enum smartbond_clock clk,uint32_t * rate)235 static int smartbond_clock_get_rate(enum smartbond_clock clk, uint32_t *rate)
236 {
237 clk = smartbond_source_clock(clk);
238 switch (clk) {
239 case SMARTBOND_CLK_RC32K:
240 *rate = lpc_clock_state.rc32k_freq;
241 break;
242 case SMARTBOND_CLK_RCX:
243 *rate = lpc_clock_state.rcx_freq;
244 break;
245 case SMARTBOND_CLK_XTAL32K:
246 *rate = DT_PROP(DT_NODELABEL(xtal32k), clock_frequency);
247 break;
248 case SMARTBOND_CLK_RC32M:
249 *rate = DT_PROP(DT_NODELABEL(rc32m), clock_frequency);
250 break;
251 case SMARTBOND_CLK_XTAL32M:
252 *rate = DT_PROP(DT_NODELABEL(xtal32m), clock_frequency);
253 break;
254 case SMARTBOND_CLK_PLL96M:
255 *rate = DT_PROP(DT_NODELABEL(pll), clock_frequency);
256 break;
257 default:
258 return -ENOTSUP;
259 }
260 return 0;
261 }
262
smartbond_clock_control_get_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)263 static int smartbond_clock_control_get_rate(const struct device *dev,
264 clock_control_subsys_t sub_system,
265 uint32_t *rate)
266 {
267 ARG_UNUSED(dev);
268
269 return smartbond_clock_get_rate((enum smartbond_clock)(sub_system), rate);
270 }
271
smartbond_dt_ord_to_clock(uint32_t dt_ord)272 static enum smartbond_clock smartbond_dt_ord_to_clock(uint32_t dt_ord)
273 {
274 switch (dt_ord) {
275 case DT_DEP_ORD(DT_NODELABEL(rc32k)):
276 return SMARTBOND_CLK_RC32K;
277 case DT_DEP_ORD(DT_NODELABEL(rcx)):
278 return SMARTBOND_CLK_RCX;
279 case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
280 return SMARTBOND_CLK_XTAL32K;
281 case DT_DEP_ORD(DT_NODELABEL(rc32m)):
282 return SMARTBOND_CLK_RC32M;
283 case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
284 return SMARTBOND_CLK_XTAL32M;
285 case DT_DEP_ORD(DT_NODELABEL(pll)):
286 return SMARTBOND_CLK_PLL96M;
287 default:
288 return SMARTBOND_CLK_NONE;
289 }
290 }
291
smartbond_clock_control_on_by_ord(const struct device * dev,uint32_t clock_id)292 static void smartbond_clock_control_on_by_ord(const struct device *dev,
293 uint32_t clock_id)
294 {
295 enum smartbond_clock clk = smartbond_dt_ord_to_clock(clock_id);
296
297 smartbond_clock_control_on(dev, (clock_control_subsys_rate_t)clk);
298 }
299
smartbond_clock_control_off_by_ord(const struct device * dev,uint32_t clock_id)300 static void smartbond_clock_control_off_by_ord(const struct device *dev,
301 uint32_t clock_id)
302 {
303 enum smartbond_clock clk = smartbond_dt_ord_to_clock(clock_id);
304
305 smartbond_clock_control_off(dev, (clock_control_subsys_rate_t)clk);
306 }
307
308 static void
qspi_set_read_pipe_delay(uint8_t delay)309 qspi_set_read_pipe_delay(uint8_t delay)
310 {
311 QSPIC->QSPIC_CTRLMODE_REG =
312 (QSPIC->QSPIC_CTRLMODE_REG & ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Msk) |
313 (delay << QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Pos) |
314 QSPIC_QSPIC_CTRLMODE_REG_QSPIC_RPIPE_EN_Msk;
315 }
316
317 static void
qspi_set_cs_delay(uint32_t sys_clock_freq,uint32_t read_delay_ns,uint32_t erase_delay_ns)318 qspi_set_cs_delay(uint32_t sys_clock_freq, uint32_t read_delay_ns, uint32_t erase_delay_ns)
319 {
320 sys_clock_freq /= 100000;
321 uint32_t read_delay_cyc = ((read_delay_ns * sys_clock_freq) + 9999) / 10000;
322 uint32_t erase_delay_cyc = ((erase_delay_ns * sys_clock_freq) + 9999) / 10000;
323
324 QSPIC->QSPIC_BURSTCMDB_REG =
325 (QSPIC->QSPIC_BURSTCMDB_REG & ~QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Msk) |
326 read_delay_cyc << QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Pos;
327 QSPIC->QSPIC_ERASECMDB_REG =
328 (QSPIC->QSPIC_ERASECMDB_REG & ~QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Msk) |
329 (erase_delay_cyc << QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Pos);
330 }
331
z_smartbond_select_lp_clk(enum smartbond_clock lp_clk)332 int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk)
333 {
334 int rc = 0;
335 uint32_t clk_sel = 0;
336 uint32_t clk_sel_msk = CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk;
337
338 switch (lp_clk) {
339 case SMARTBOND_CLK_RC32K:
340 clk_sel = 0;
341 break;
342 case SMARTBOND_CLK_RCX:
343 clk_sel = 1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
344 break;
345 case SMARTBOND_CLK_XTAL32K:
346 clk_sel = 2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
347 break;
348 default:
349 rc = -EINVAL;
350 }
351
352 if (rc == 0) {
353 CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel;
354 }
355
356 return rc;
357 }
358
z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)359 int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)
360 {
361 uint32_t sys_clock_freq;
362 uint32_t clk_sel;
363 uint32_t clk_sel_msk = CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
364 int res;
365
366 res = smartbond_clock_get_rate(sys_clk, &sys_clock_freq);
367 if (res != 0) {
368 return -EINVAL;
369 }
370
371 /* When PLL is selected as system clock qspi read pipe delay must be set to 7 */
372 if (sys_clock_freq > 32000000) {
373 qspi_set_read_pipe_delay(7);
374 qspi_set_cs_delay(SystemCoreClock,
375 DT_PROP(DT_NODELABEL(flash_controller),
376 read_cs_idle_delay),
377 DT_PROP(DT_NODELABEL(flash_controller),
378 erase_cs_idle_delay));
379 }
380
381 if (sys_clk == SMARTBOND_CLK_RC32M) {
382 clk_sel = 1 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos;
383 CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel;
384 SystemCoreClock = sys_clock_freq;
385 } else if (sys_clk == SMARTBOND_CLK_PLL96M) {
386 da1469x_clock_pll_wait_to_lock();
387 da1469x_clock_sys_pll_switch();
388 } else if (sys_clk == SMARTBOND_CLK_XTAL32M) {
389 da1469x_clock_sys_xtal32m_switch_safe();
390 }
391
392 /* When switching back from PLL to 32MHz read pipe delay may be set to 2 */
393 if (SystemCoreClock <= 32000000) {
394 qspi_set_read_pipe_delay(2);
395 qspi_set_cs_delay(SystemCoreClock,
396 DT_PROP(DT_NODELABEL(flash_controller),
397 read_cs_idle_delay),
398 DT_PROP(DT_NODELABEL(flash_controller),
399 erase_cs_idle_delay));
400 }
401
402 return 0;
403 }
404
405 /**
406 * @brief Initialize clocks for the Smartbond
407 *
408 * This routine is called to enable and configure the clocks and PLL
409 * of the soc on the board.
410 *
411 * @param dev clocks device struct
412 *
413 * @return 0
414 */
smartbond_clocks_init(const struct device * dev)415 int smartbond_clocks_init(const struct device *dev)
416 {
417 uint32_t clk_id;
418 enum smartbond_clock lp_clk;
419 enum smartbond_clock sys_clk;
420
421 ARG_UNUSED(dev);
422
423 #define ENABLE_OSC(clock) smartbond_clock_control_on_by_ord(dev, DT_DEP_ORD(clock))
424 #define DISABLE_OSC(clock) if (DT_NODE_HAS_STATUS(clock, disabled)) { \
425 smartbond_clock_control_off_by_ord(dev, DT_DEP_ORD(clock)); \
426 }
427
428 /* Enable all oscillators with status "okay" */
429 DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(crg, osc), ENABLE_OSC, (;));
430
431 /* Make sure that selected sysclock is enabled */
432 BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_PROP(DT_NODELABEL(sys_clk), clock_src), okay),
433 "Clock selected as system clock no enabled in DT");
434 BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_PROP(DT_NODELABEL(lp_clk), clock_src), okay),
435 "Clock selected as LP clock no enabled in DT");
436 BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(pll), disabled) ||
437 DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay),
438 "PLL enabled in DT but XTAL32M is disabled");
439
440 clk_id = DT_DEP_ORD(DT_PROP(DT_NODELABEL(lp_clk), clock_src));
441 lp_clk = smartbond_dt_ord_to_clock(clk_id);
442 z_smartbond_select_lp_clk(lp_clk);
443
444 clk_id = DT_DEP_ORD(DT_PROP(DT_NODELABEL(sys_clk), clock_src));
445 sys_clk = smartbond_dt_ord_to_clock(clk_id);
446 smartbond_clock_control_on(dev,
447 (clock_control_subsys_rate_t)smartbond_source_clock(sys_clk));
448 z_smartbond_select_sys_clk(sys_clk);
449
450 /* Disable unwanted oscillators */
451 DT_FOREACH_CHILD_SEP(DT_PATH(crg, osc), DISABLE_OSC, (;));
452
453 return 0;
454 }
455
456 static struct clock_control_driver_api smartbond_clock_control_api = {
457 .on = smartbond_clock_control_on,
458 .off = smartbond_clock_control_off,
459 .get_rate = smartbond_clock_control_get_rate,
460 };
461
462 DEVICE_DT_DEFINE(DT_NODELABEL(osc),
463 &smartbond_clocks_init,
464 NULL,
465 NULL, NULL,
466 PRE_KERNEL_1,
467 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
468 &smartbond_clock_control_api);
469