11 #include "sw/device/lib/base/multibits.h"
14 #include "clkmgr_regs.h"
20 CLKMGR_PARAM_NUM_SW_GATEABLE_CLOCKS <= CLKMGR_PARAM_REG_WIDTH,
21 "Expected the number of gateable clocks to be <= the width of a CSR.");
27 CLKMGR_PARAM_NUM_HINTABLE_CLOCKS <= CLKMGR_PARAM_REG_WIDTH,
28 "Expected the number of hintable clocks to be <= the width of a CSR.");
31 return clock < CLKMGR_PARAM_NUM_SW_GATEABLE_CLOCKS;
35 return clock < CLKMGR_PARAM_NUM_HINTABLE_CLOCKS;
38 static bool clkmgr_measure_ctrl_regwen(
const dif_clkmgr_t *clkmgr) {
39 uint32_t measure_ctrl_regwen_val = mmio_region_read32(
40 clkmgr->base_addr, CLKMGR_MEASURE_CTRL_REGWEN_REG_OFFSET);
42 CLKMGR_MEASURE_CTRL_REGWEN_EN_BIT);
51 static bool jitter_enable_register_is_locked(
const dif_clkmgr_t *clkmgr) {
55 mmio_region_read32(clkmgr->base_addr, CLKMGR_JITTER_REGWEN_REG_OFFSET),
56 CLKMGR_JITTER_REGWEN_EN_BIT);
65 static bool extclk_control_register_is_locked(
const dif_clkmgr_t *clkmgr) {
69 mmio_region_read32(clkmgr->base_addr,
70 CLKMGR_EXTCLK_CTRL_REGWEN_REG_OFFSET),
71 CLKMGR_EXTCLK_CTRL_REGWEN_EN_BIT);
76 if (clkmgr == NULL ||
status == NULL) {
79 uint32_t extclk_status_val =
80 mmio_region_read32(clkmgr->base_addr, CLKMGR_EXTCLK_STATUS_REG_OFFSET);
82 CLKMGR_EXTCLK_STATUS_ACK_FIELD) ==
90 if (clkmgr == NULL || is_locked == NULL) {
94 *is_locked = jitter_enable_register_is_locked(clkmgr);
100 if (clkmgr == NULL) {
103 mmio_region_write32(clkmgr->base_addr, CLKMGR_JITTER_REGWEN_REG_OFFSET, 0);
109 if (clkmgr == NULL || state == NULL) {
113 multi_bit_bool_t clk_jitter_val =
114 mmio_region_read32(clkmgr->base_addr, CLKMGR_JITTER_ENABLE_REG_OFFSET);
125 multi_bit_bool_t new_jitter_enable_val;
126 if (clkmgr == NULL) {
129 if (jitter_enable_register_is_locked(clkmgr)) {
135 new_jitter_enable_val = kMultiBitBool4True;
138 new_jitter_enable_val = kMultiBitBool4False;
143 mmio_region_write32(clkmgr->base_addr, CLKMGR_JITTER_ENABLE_REG_OFFSET,
144 new_jitter_enable_val);
150 const dif_clkmgr_t *clkmgr, dt_instance_id_t inst_id,
152 if (clkmgr == NULL || clock == NULL) {
161 for (
size_t i = 0; i < dt_clkmgr_gateable_clock_count(dt); i++) {
162 if (dt_clkmgr_gateable_clock(dt, i) == inst_id) {
173 if (clkmgr == NULL || state == NULL || !clkmgr_valid_gateable_clock(clock)) {
177 uint32_t clk_enables_val =
178 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET);
187 if (clkmgr == NULL || !clkmgr_valid_gateable_clock(clock) ||
193 uint32_t clk_enables_val =
194 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET);
197 mmio_region_write32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET,
205 const dif_clkmgr_t *clkmgr, dt_instance_id_t inst_id,
207 if (clkmgr == NULL || clock == NULL) {
216 for (
size_t i = 0; i < dt_clkmgr_hintable_clock_count(dt); i++) {
217 if (dt_clkmgr_hintable_clock(dt, i) == inst_id) {
228 if (clkmgr == NULL || state == NULL || !clkmgr_valid_hintable_clock(clock)) {
232 uint32_t clk_hints_val =
233 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_STATUS_REG_OFFSET);
242 if (clkmgr == NULL || !clkmgr_valid_hintable_clock(clock) ||
248 uint32_t clk_hints_val =
249 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET);
251 mmio_region_write32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET,
260 if (clkmgr == NULL || state == NULL || !clkmgr_valid_hintable_clock(clock)) {
264 uint32_t clk_hints_val =
265 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET);
272 const dif_clkmgr_t *clkmgr,
bool *is_locked) {
273 if (clkmgr == NULL || is_locked == NULL) {
277 *is_locked = extclk_control_register_is_locked(clkmgr);
283 const dif_clkmgr_t *clkmgr) {
284 if (clkmgr == NULL) {
287 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REGWEN_REG_OFFSET,
294 uint32_t extclk_ctrl_reg = 0;
296 if (clkmgr == NULL) {
300 if (extclk_control_register_is_locked(clkmgr)) {
305 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_SEL_FIELD, kMultiBitBool4True);
307 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_HI_SPEED_SEL_FIELD,
308 is_low_speed ? kMultiBitBool4False : kMultiBitBool4True);
309 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REG_OFFSET,
315 const dif_clkmgr_t *clkmgr) {
316 uint32_t extclk_ctrl_reg = 0;
318 if (clkmgr == NULL) {
322 if (extclk_control_register_is_locked(clkmgr)) {
327 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_SEL_FIELD, kMultiBitBool4False);
330 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_HI_SPEED_SEL_FIELD,
332 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REG_OFFSET,
338 if (clkmgr == NULL) {
341 mmio_region_write32(clkmgr->base_addr, CLKMGR_MEASURE_CTRL_REGWEN_REG_OFFSET,
348 if (clkmgr == NULL || state == NULL) {
376 #define CNCAT_IMPL(a_, b_) a_##b_
377 #define CNCAT(a_, b_) CNCAT_IMPL(a_, b_)
378 #define CHECK_CLKMGR_IO_MEAS_CTRL_EN_REG_OFFSET ~, ~
379 #define CHECK_CLKMGR_IO_DIV2_MEAS_CTRL_EN_REG_OFFSET ~, ~
380 #define CHECK_CLKMGR_IO_DIV4_MEAS_CTRL_EN_REG_OFFSET ~, ~
381 #define CHECK_CLKMGR_MAIN_MEAS_CTRL_EN_REG_OFFSET ~, ~
382 #define CHECK_CLKMGR_USB_MEAS_CTRL_EN_REG_OFFSET ~, ~
383 #define CHECK_IMPL(a_, b_, c_, ...) c_
384 #define CHECK(tup_) CHECK_IMPL tup_
386 #define IS_KIND_DEFINED(kind_) \
387 CHECK((CNCAT(CHECK_, CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET), 0, 1))
389 #define IIF_0(true_exp_, false_exp_) false_exp_
390 #define IIF_1(true_exp_, false_exp_) true_exp_
391 #define IIF(condition_, true_exp_, false_exp_) \
392 CNCAT(IIF_, condition_)(true_exp_, false_exp_)
395 dif_clkmgr_measure_clock_t clock,
396 uint32_t lo_threshold,
397 uint32_t hi_threshold) {
398 if (clkmgr == NULL) {
401 if (!clkmgr_measure_ctrl_regwen(clkmgr)) {
405 uint32_t en_offset = 0;
406 uint32_t reg_offset = 0;
411 #define PICK_COUNT_CTRL_FIELDS(kind_) \
412 IIF(IS_KIND_DEFINED(kind_), \
413 en_offset = CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET; \
414 reg_offset = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_REG_OFFSET; \
415 en_field = CLKMGR_##kind_##_MEAS_CTRL_EN_EN_FIELD; \
416 lo_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_LO_FIELD; \
417 hi_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_HI_FIELD; break, break)
419 #if defined(OPENTITAN_IS_EARLGREY)
420 case kDifClkmgrMeasureClockIo:
421 PICK_COUNT_CTRL_FIELDS(IO);
422 case kDifClkmgrMeasureClockIoDiv2:
423 PICK_COUNT_CTRL_FIELDS(IO_DIV2);
424 #elif defined(OPENTITAN_IS_DARJEELING)
427 #error "dif_clkmgr does not support this top"
430 PICK_COUNT_CTRL_FIELDS(IO_DIV4);
432 PICK_COUNT_CTRL_FIELDS(MAIN);
434 PICK_COUNT_CTRL_FIELDS(USB);
437 #undef PICK_COUNT_CTRL_FIELDS
440 uint32_t measure_ctrl_reg = 0;
446 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)reg_offset,
448 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)reg_offset,
451 uint32_t measure_en_reg = 0;
454 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)en_offset, measure_en_reg);
460 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock) {
461 if (clkmgr == NULL) {
464 if (!clkmgr_measure_ctrl_regwen(clkmgr)) {
468 uint32_t en_offset = 0;
470 #define PICK_EN_OFFSET(kind_) \
471 IIF(IS_KIND_DEFINED(kind_), \
472 en_offset = CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET; \
475 #if defined(OPENTITAN_IS_EARLGREY)
476 case kDifClkmgrMeasureClockIo:
479 case kDifClkmgrMeasureClockIoDiv2:
480 PICK_EN_OFFSET(IO_DIV2);
482 #elif defined(OPENTITAN_IS_DARJEELING)
485 #error "dif_clkmgr does not support this top"
488 PICK_EN_OFFSET(IO_DIV4);
491 PICK_EN_OFFSET(MAIN);
498 #undef PICK_EN_OFFSET
500 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)en_offset,
501 kMultiBitBool4False);
506 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
508 if (clkmgr == NULL || state == NULL) {
512 uint32_t en_offset = 0;
514 #define PICK_EN_OFFSET(kind_) \
515 IIF(IS_KIND_DEFINED(kind_), \
516 en_offset = CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET; \
519 #if defined(OPENTITAN_IS_EARLGREY)
520 case kDifClkmgrMeasureClockIo:
522 case kDifClkmgrMeasureClockIoDiv2:
523 PICK_EN_OFFSET(IO_DIV2);
524 #elif defined(OPENTITAN_IS_DARJEELING)
527 #error "dif_clkmgr does not support this top"
530 PICK_EN_OFFSET(IO_DIV4);
532 PICK_EN_OFFSET(MAIN);
537 #undef PICK_EN_OFFSET
539 multi_bit_bool_t en_val =
540 mmio_region_read32(clkmgr->base_addr, (ptrdiff_t)en_offset);
547 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
548 uint32_t *min_threshold, uint32_t *max_threshold) {
549 if (clkmgr == NULL || min_threshold == NULL || max_threshold == NULL) {
553 uint32_t reg_offset = 0;
557 #define PICK_THRESHOLD_FIELDS(kind_) \
558 IIF(IS_KIND_DEFINED(kind_), \
559 reg_offset = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_REG_OFFSET; \
560 lo_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_LO_FIELD; \
561 hi_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_HI_FIELD; break, break)
562 #if defined(OPENTITAN_IS_EARLGREY)
563 case kDifClkmgrMeasureClockIo:
564 PICK_THRESHOLD_FIELDS(IO);
565 case kDifClkmgrMeasureClockIoDiv2:
566 PICK_THRESHOLD_FIELDS(IO_DIV2);
567 #elif defined(OPENTITAN_IS_DARJEELING)
570 #error "dif_clkmgr does not support this top"
573 PICK_THRESHOLD_FIELDS(IO_DIV4);
575 PICK_THRESHOLD_FIELDS(MAIN);
577 PICK_THRESHOLD_FIELDS(USB);
580 #undef PICK_THRESHOLD_FIELDS
582 uint32_t thresholds_val =
583 mmio_region_read32(clkmgr->base_addr, (ptrdiff_t)reg_offset);
592 #undef CHECK_CLKMGR_IO_MEAS_CTRL_EN_REG_OFFSET
593 #undef CHECK_CLKMGR_IO_DIV2_MEAS_CTRL_EN_REG_OFFSET
594 #undef CHECK_CLKMGR_IO_DIV4_MEAS_CTRL_EN_REG_OFFSET
595 #undef CHECK_CLKMGR_MAIN_MEAS_CTRL_EN_REG_OFFSET
596 #undef CHECK_CLKMGR_USB_MEAS_CTRL_EN_REG_OFFSET
599 #undef IS_KIND_DEFINED
606 if (clkmgr == NULL || codes == NULL) {
610 mmio_region_read32(clkmgr->base_addr, CLKMGR_RECOV_ERR_CODE_REG_OFFSET);
616 if (clkmgr == NULL) {
619 mmio_region_write32(clkmgr->base_addr, CLKMGR_RECOV_ERR_CODE_REG_OFFSET,
626 if (clkmgr == NULL || codes == NULL) {
630 mmio_region_read32(clkmgr->base_addr, CLKMGR_FATAL_ERR_CODE_REG_OFFSET);
635 if (clkmgr == NULL) {
641 mmio_region_read32(clkmgr->base_addr, CLKMGR_EXTCLK_STATUS_REG_OFFSET);
642 }
while (ext_status != kMultiBitBool4True);