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);
151 if (clkmgr == NULL || state == NULL || !clkmgr_valid_gateable_clock(clock)) {
155 uint32_t clk_enables_val =
156 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET);
165 if (clkmgr == NULL || !clkmgr_valid_gateable_clock(clock) ||
171 uint32_t clk_enables_val =
172 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET);
175 mmio_region_write32(clkmgr->base_addr, CLKMGR_CLK_ENABLES_REG_OFFSET,
184 if (clkmgr == NULL || state == NULL || !clkmgr_valid_hintable_clock(clock)) {
188 uint32_t clk_hints_val =
189 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_STATUS_REG_OFFSET);
198 if (clkmgr == NULL || !clkmgr_valid_hintable_clock(clock) ||
204 uint32_t clk_hints_val =
205 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET);
207 mmio_region_write32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET,
216 if (clkmgr == NULL || state == NULL || !clkmgr_valid_hintable_clock(clock)) {
220 uint32_t clk_hints_val =
221 mmio_region_read32(clkmgr->base_addr, CLKMGR_CLK_HINTS_REG_OFFSET);
228 const dif_clkmgr_t *clkmgr,
bool *is_locked) {
229 if (clkmgr == NULL || is_locked == NULL) {
233 *is_locked = extclk_control_register_is_locked(clkmgr);
239 const dif_clkmgr_t *clkmgr) {
240 if (clkmgr == NULL) {
243 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REGWEN_REG_OFFSET,
250 uint32_t extclk_ctrl_reg = 0;
252 if (clkmgr == NULL) {
256 if (extclk_control_register_is_locked(clkmgr)) {
261 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_SEL_FIELD, kMultiBitBool4True);
263 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_HI_SPEED_SEL_FIELD,
264 is_low_speed ? kMultiBitBool4False : kMultiBitBool4True);
265 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REG_OFFSET,
271 const dif_clkmgr_t *clkmgr) {
272 uint32_t extclk_ctrl_reg = 0;
274 if (clkmgr == NULL) {
278 if (extclk_control_register_is_locked(clkmgr)) {
283 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_SEL_FIELD, kMultiBitBool4False);
286 extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_HI_SPEED_SEL_FIELD,
288 mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REG_OFFSET,
294 if (clkmgr == NULL) {
297 mmio_region_write32(clkmgr->base_addr, CLKMGR_MEASURE_CTRL_REGWEN_REG_OFFSET,
304 if (clkmgr == NULL || state == NULL) {
332 #define CNCAT_IMPL(a_, b_) a_##b_
333 #define CNCAT(a_, b_) CNCAT_IMPL(a_, b_)
334 #define CHECK_CLKMGR_IO_MEAS_CTRL_EN_REG_OFFSET ~, ~
335 #define CHECK_CLKMGR_IO_DIV2_MEAS_CTRL_EN_REG_OFFSET ~, ~
336 #define CHECK_CLKMGR_IO_DIV4_MEAS_CTRL_EN_REG_OFFSET ~, ~
337 #define CHECK_CLKMGR_MAIN_MEAS_CTRL_EN_REG_OFFSET ~, ~
338 #define CHECK_CLKMGR_USB_MEAS_CTRL_EN_REG_OFFSET ~, ~
339 #define CHECK_IMPL(a_, b_, c_, ...) c_
340 #define CHECK(tup_) CHECK_IMPL tup_
342 #define IS_KIND_DEFINED(kind_) \
343 CHECK((CNCAT(CHECK_, CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET), 0, 1))
345 #define IIF_0(true_exp_, false_exp_) false_exp_
346 #define IIF_1(true_exp_, false_exp_) true_exp_
347 #define IIF(condition_, true_exp_, false_exp_) \
348 CNCAT(IIF_, condition_)(true_exp_, false_exp_)
351 dif_clkmgr_measure_clock_t clock,
352 uint32_t lo_threshold,
353 uint32_t hi_threshold) {
354 if (clkmgr == NULL) {
357 if (!clkmgr_measure_ctrl_regwen(clkmgr)) {
361 uint32_t en_offset = 0;
362 uint32_t reg_offset = 0;
367 #define PICK_COUNT_CTRL_FIELDS(kind_) \
368 IIF(IS_KIND_DEFINED(kind_), \
369 en_offset = CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET; \
370 reg_offset = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_REG_OFFSET; \
371 en_field = CLKMGR_##kind_##_MEAS_CTRL_EN_EN_FIELD; \
372 lo_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_LO_FIELD; \
373 hi_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_HI_FIELD; break, break)
375 #if defined(OPENTITAN_IS_EARLGREY)
376 case kDifClkmgrMeasureClockIo:
377 PICK_COUNT_CTRL_FIELDS(IO);
378 case kDifClkmgrMeasureClockIoDiv2:
379 PICK_COUNT_CTRL_FIELDS(IO_DIV2);
380 #elif defined(OPENTITAN_IS_DARJEELING)
383 #error "dif_clkmgr does not support this top"
386 PICK_COUNT_CTRL_FIELDS(IO_DIV4);
388 PICK_COUNT_CTRL_FIELDS(MAIN);
390 PICK_COUNT_CTRL_FIELDS(USB);
393 #undef PICK_COUNT_CTRL_FIELDS
396 uint32_t measure_ctrl_reg = 0;
402 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)reg_offset,
404 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)reg_offset,
407 uint32_t measure_en_reg = 0;
410 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)en_offset, measure_en_reg);
416 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock) {
417 if (clkmgr == NULL) {
420 if (!clkmgr_measure_ctrl_regwen(clkmgr)) {
424 uint32_t en_offset = 0;
426 #define PICK_EN_OFFSET(kind_) \
427 IIF(IS_KIND_DEFINED(kind_), \
428 en_offset = CLKMGR_##kind_##_MEAS_CTRL_EN_REG_OFFSET; \
431 #if defined(OPENTITAN_IS_EARLGREY)
432 case kDifClkmgrMeasureClockIo:
435 case kDifClkmgrMeasureClockIoDiv2:
436 PICK_EN_OFFSET(IO_DIV2);
438 #elif defined(OPENTITAN_IS_DARJEELING)
441 #error "dif_clkmgr does not support this top"
444 PICK_EN_OFFSET(IO_DIV4);
447 PICK_EN_OFFSET(MAIN);
454 #undef PICK_EN_OFFSET
456 mmio_region_write32(clkmgr->base_addr, (ptrdiff_t)en_offset,
457 kMultiBitBool4False);
462 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
464 if (clkmgr == NULL || state == NULL) {
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:
478 case kDifClkmgrMeasureClockIoDiv2:
479 PICK_EN_OFFSET(IO_DIV2);
480 #elif defined(OPENTITAN_IS_DARJEELING)
483 #error "dif_clkmgr does not support this top"
486 PICK_EN_OFFSET(IO_DIV4);
488 PICK_EN_OFFSET(MAIN);
493 #undef PICK_EN_OFFSET
495 multi_bit_bool_t en_val =
496 mmio_region_read32(clkmgr->base_addr, (ptrdiff_t)en_offset);
503 const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
504 uint32_t *min_threshold, uint32_t *max_threshold) {
505 if (clkmgr == NULL || min_threshold == NULL || max_threshold == NULL) {
509 uint32_t reg_offset = 0;
513 #define PICK_THRESHOLD_FIELDS(kind_) \
514 IIF(IS_KIND_DEFINED(kind_), \
515 reg_offset = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_REG_OFFSET; \
516 lo_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_LO_FIELD; \
517 hi_field = CLKMGR_##kind_##_MEAS_CTRL_SHADOWED_HI_FIELD; break, break)
518 #if defined(OPENTITAN_IS_EARLGREY)
519 case kDifClkmgrMeasureClockIo:
520 PICK_THRESHOLD_FIELDS(IO);
521 case kDifClkmgrMeasureClockIoDiv2:
522 PICK_THRESHOLD_FIELDS(IO_DIV2);
523 #elif defined(OPENTITAN_IS_DARJEELING)
526 #error "dif_clkmgr does not support this top"
529 PICK_THRESHOLD_FIELDS(IO_DIV4);
531 PICK_THRESHOLD_FIELDS(MAIN);
533 PICK_THRESHOLD_FIELDS(USB);
536 #undef PICK_THRESHOLD_FIELDS
538 uint32_t thresholds_val =
539 mmio_region_read32(clkmgr->base_addr, (ptrdiff_t)reg_offset);
548 #undef CHECK_CLKMGR_IO_MEAS_CTRL_EN_REG_OFFSET
549 #undef CHECK_CLKMGR_IO_DIV2_MEAS_CTRL_EN_REG_OFFSET
550 #undef CHECK_CLKMGR_IO_DIV4_MEAS_CTRL_EN_REG_OFFSET
551 #undef CHECK_CLKMGR_MAIN_MEAS_CTRL_EN_REG_OFFSET
552 #undef CHECK_CLKMGR_USB_MEAS_CTRL_EN_REG_OFFSET
555 #undef IS_KIND_DEFINED
562 if (clkmgr == NULL || codes == NULL) {
566 mmio_region_read32(clkmgr->base_addr, CLKMGR_RECOV_ERR_CODE_REG_OFFSET);
572 if (clkmgr == NULL) {
575 mmio_region_write32(clkmgr->base_addr, CLKMGR_RECOV_ERR_CODE_REG_OFFSET,
582 if (clkmgr == NULL || codes == NULL) {
586 mmio_region_read32(clkmgr->base_addr, CLKMGR_FATAL_ERR_CODE_REG_OFFSET);
591 if (clkmgr == NULL) {
597 mmio_region_read32(clkmgr->base_addr, CLKMGR_EXTCLK_STATUS_REG_OFFSET);
598 }
while (ext_status != kMultiBitBool4True);