blob: 7b9b4e18b35fcdc047e7e3b071d2d4b6fec81fd5 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SW_DEVICE_LIB_DIF_DIF_CLKMGR_H_
#define SW_DEVICE_LIB_DIF_DIF_CLKMGR_H_
/**
* @file
* @brief <a href="/hw/ip/clkmgr/doc/">Clock Manager</a> Device Interface
* Functions
*/
#include <stdint.h>
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/autogen/dif_clkmgr_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* An Index of a "Gateable" Clock.
*
* "Gateable" clocks are under full software control: they can be enabled and
* disabled by software, which directly starts and stops the identified clock.
*/
typedef uint32_t dif_clkmgr_gateable_clock_t;
/**
* An Index of a "Hintable" Clock.
*
* "Hintable" clocks are under partial software control: software can suggest
* they are stopped, but the clock manager may delay stopping the peripheral, or
* may ignore the request altogether.
*/
typedef uint32_t dif_clkmgr_hintable_clock_t;
typedef enum dif_clkmgr_measure_clock {
/**
* The Audio clock.
*/
kDifClkmgrMeasureClockAudio,
/**
* The Io clock.
*/
kDifClkmgrMeasureClockIo,
/**
* The Io_div2 clock.
*/
kDifClkmgrMeasureClockIoDiv2,
/**
* The Io div4 clock.
*/
kDifClkmgrMeasureClockIoDiv4,
/**
* The Main clock.
*/
kDifClkmgrMeasureClockMain,
/**
* The Ml clock.
*/
kDifClkmgrMeasureClockMl,
/**
* The Smc clock.
*/
kDifClkmgrMeasureClockSmc,
/**
* The Usb clock.
*/
kDifClkmgrMeasureClockUsb,
/**
* The Video clock.
*/
kDifClkmgrMeasureClockVideo
} dif_clkmgr_measure_clock_t;
typedef enum dif_clkmgr_recov_err_type {
/**
* A recoverable update error for one of the clocks.
*/
kDifClkmgrRecovErrTypeShadowUpdate = 1u << 0,
/**
* A recoverable measurement error for AUDIO clock.
*/
kDifClkmgrRecovErrTypeAudioMeas = 1u << 1,
/**
* A recoverable measurement error for IO clock.
*/
kDifClkmgrRecovErrTypeIoMeas = 1u << 2,
/**
* A recoverable measurement error for IO_DIV2 clock.
*/
kDifClkmgrRecovErrTypeIoDiv2Meas = 1u << 3,
/**
* A recoverable measurement error for IO_DIV4 clock.
*/
kDifClkmgrRecovErrTypeIoDiv4Meas = 1u << 4,
/**
* A recoverable measurement error for MAIN clock.
*/
kDifClkmgrRecovErrTypeMainMeas = 1u << 5,
/**
* A recoverable measurement error for ML clock.
*/
kDifClkmgrRecovErrTypeMlMeas = 1u << 6,
/**
* A recoverable measurement error for SMC clock.
*/
kDifClkmgrRecovErrTypeSmcMeas = 1u << 7,
/**
* A recoverable measurement error for USB clock.
*/
kDifClkmgrRecovErrTypeUsbMeas = 1u << 8,
/**
* A recoverable measurement error for VIDEO clock.
*/
kDifClkmgrRecovErrTypeVideoMeas = 1u << 9,
/**
* A recoverable timeout error for AUDIO clock.
*/
kDifClkmgrRecovErrTypeAudioTimeout = 1u << 10,
/**
* A recoverable timeout error for IO clock.
*/
kDifClkmgrRecovErrTypeIoTimeout = 1u << 11,
/**
* A recoverable timeout error for IO_DIV2 clock.
*/
kDifClkmgrRecovErrTypeIoDiv2Timeout = 1u << 12,
/**
* A recoverable timeout error for IO_DIV4 clock.
*/
kDifClkmgrRecovErrTypeIoDiv4Timeout = 1u << 13,
/**
* A recoverable timeout error for MAIN clock.
*/
kDifClkmgrRecovErrTypeMainTimeout = 1u << 14,
/**
* A recoverable timeout error for ML clock.
*/
kDifClkmgrRecovErrTypeMlTimeout = 1u << 15,
/**
* A recoverable timeout error for SMC clock.
*/
kDifClkmgrRecovErrTypeSmcTimeout = 1u << 16,
/**
* A recoverable timeout error for USB clock.
*/
kDifClkmgrRecovErrTypeUsbTimeout = 1u << 17,
/**
* A recoverable timeout error for VIDEO clock.
*/
kDifClkmgrRecovErrTypeVideoTimeout = 1u << 18
} dif_clkmgr_recov_err_type_t;
/**
* A set of recoverable errors.
*
* This type is used to clear and read the recoverable error codes.
*/
typedef uint32_t dif_clkmgr_recov_err_codes_t;
typedef enum dif_clkmgr_fatal_err_type {
/**
* A fatal error for regfile integrity.
*/
kDifClkmgrFatalErrTypeRegfileIntegrity = 1u << 0,
/**
* A fatal error for a duplicate idle counter.
*/
kDifClkmgrFatalErrTypeIdleCount = 1u << 1,
/**
* A fatal error for a shadow register storage.
*/
kDifClkmgrFatalErrTypeShadowStorage = 1u << 2,
} dif_clkmgr_fatal_err_type_t;
/**
* A set of fatal errors.
*
* This type is used to read the fatal error codes.
*/
typedef uint32_t dif_clkmgr_fatal_err_codes_t;
/**
* Check if jitter is Enabled.
* @param clkmgr Clock Manager Handle.
* @param[out] is_enabled whether jitter is enabled or not.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_jitter_get_enabled(const dif_clkmgr_t *clkmgr,
dif_toggle_t *state);
/**
* Enable of Disable jitter.
* @param clkmgr Clock Manager Handle.
* @param new_state whether to enable or disable jitter.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_jitter_set_enabled(const dif_clkmgr_t *clkmgr,
dif_toggle_t new_state);
/**
* Check if a Gateable Clock is Enabled or Disabled.
*
* @param clkmgr Clock Manager Handle.
* @param clock Gateable Clock ID.
* @param[out] is_enabled whether the clock is enabled or not.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_gateable_clock_get_enabled(
const dif_clkmgr_t *clkmgr, dif_clkmgr_gateable_clock_t clock,
dif_toggle_t *state);
/**
* Enable or Disable a Gateable Clock.
*
* @param clkmgr Clock Manager Handle.
* @param clock Gateable Clock ID.
* @param new_state whether to enable or disable the clock.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_gateable_clock_set_enabled(
const dif_clkmgr_t *clkmgr, dif_clkmgr_gateable_clock_t clock,
dif_toggle_t new_state);
/**
* Check if a Hintable Clock is Enabled or Disabled.
*
* Hintable clocks are not under full software control, but this operation
* accurately reflects the state of the current clock, regardless of any hint
* requests made by software.
*
* To read what hint the software has given the hardware, use
* #dif_clkmgr_hintable_clock_get_hint.
*
* @param clkmgr Clock Manager Handle.
* @param clock Hintable Clock ID.
* @param[out] is_enabled whether the clock is enabled or not.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_hintable_clock_get_enabled(
const dif_clkmgr_t *clkmgr, dif_clkmgr_hintable_clock_t clock,
dif_toggle_t *state);
/**
* Enable or Disable a Hintable Clock.
*
* This only sets a hint that the clock should be enabled or disabled. The clock
* manager is in control of whether the clock should actually be enabled or
* disabled.
*
* To read what hint the software has given the hardware, use
* #dif_clkmgr_hintable_clock_get_hint. To read whether the clock is currently
* enabled or disabled, use #dif_clkmgr_hintable_clock_get_enabled.
*
* @param clkmgr Clock Manager Handle.
* @param clock Hintable Clock ID.
* @param new_state whether to enable or disable the clock.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_hintable_clock_set_hint(
const dif_clkmgr_t *clkmgr, dif_clkmgr_hintable_clock_t clock,
dif_toggle_t new_state);
/**
* Read the current Hint for a Hintable Clock.
*
* Hintable clocks are not under full software control; this operation
* accurately reflects the current software hint, not the current state of the
* clock.
*
* To read whether the clock is currently enabled or disabled, use
* #dif_clkmgr_hintable_clock_get_enabled.
*
* @param clkmgr Clock Manager Handle.
* @param clock Hintable Clock ID.
* @param[out] hinted_is_enabled the current software request (hint) for this
* clock.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_hintable_clock_get_hint(
const dif_clkmgr_t *clkmgr, dif_clkmgr_hintable_clock_t clock,
dif_toggle_t *state);
/**
* Enable chip to use the external clock.
*
* @param clkmgr Clock Manager Handle.
* @param is_low_speed External clock is low speed or high speed.
* @returns The result of the operation.
* High speed - external clock is close to nominal speeds (e.g. external clock
* is 96MHz and nominal frequency is 96MHz-100MHz). Low speed - external clock
* is half of nominal speeds (e.g. external clock is 48MHz and nominal frequency
* is 96MHz-100MHz).
*
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_external_clock_set_enabled(const dif_clkmgr_t *clkmgr,
bool is_low_speed);
/**
* Determine if the transition to using external clock is complete.
*
* @param clkmgr Clock Manager Handle.
* @param[out] status Set to true if the transition is complete.
* @returns The result of the operation once it completes.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_external_clock_is_settled(const dif_clkmgr_t *clkmgr,
bool *status);
/**
* Disable measurement control updates.
*
* This can only be disabled, and stays disabled until the next POR.
*
* @param clkmgr Clock Manager Handle.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_measure_ctrl_disable(const dif_clkmgr_t *clkmgr);
/**
* Get measurement control state.
*
* @param clkmgr Clock Manager Handle.
* @param[out] state The state of control enable.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_measure_ctrl_get_enable(const dif_clkmgr_t *clkmgr,
dif_toggle_t *state);
/**
* Configure count measurements.
*
* @param clkmgr Clock Manager Handle.
* @param clock A clock to be measured.
* @param min_threshold The smallest permissible cycle count.
* @param max_threshold The largest permissible cycle count.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_enable_measure_counts(const dif_clkmgr_t *clkmgr,
dif_clkmgr_measure_clock_t clock,
uint32_t min_threshold,
uint32_t max_threshold);
/**
* Disable count measurements.
*
* Does not modify the thresholds.
*
* @param clkmgr Clock Manager Handle.
* @param clock A clock to be measured.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_disable_measure_counts(
const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock);
/**
* Get the count measurement enable.
*
* @param clkmgr Clock Manager Handle.
* @param clock A clock to be measured.
* @param[out] state The state of control enable.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_measure_counts_get_enable(
const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
dif_toggle_t *state);
/**
* Get the count measurement thresholds.
*
* @param clkmgr Clock Manager Handle.
* @param clock A clock to be measured.
* @param[out] min_threshold The minumum threshold.
* @param[out] max_threshold The maximum threshold.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_measure_counts_get_thresholds(
const dif_clkmgr_t *clkmgr, dif_clkmgr_measure_clock_t clock,
uint32_t *min_threshold, uint32_t *max_threshold);
/**
* Read the recoverable error codes.
*
* @param clkmgr Clock Manager Handle.
* @param[out] codes The recoverable error codes.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_recov_err_code_get_codes(
const dif_clkmgr_t *clkmgr, dif_clkmgr_recov_err_codes_t *codes);
/**
* Clear selected recoverable error codes.
*
* @param clkmgr Clock Manager Handle.
* @param codes The recoverable error codes to be cleared.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_recov_err_code_clear_codes(
const dif_clkmgr_t *clkmgr, dif_clkmgr_recov_err_codes_t codes);
/**
* Read the fatal error codes.
*
* @param clkmgr Clock Manager Handle.
* @param[out] codes The fatal error codes.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_fatal_err_code_get_codes(
const dif_clkmgr_t *clkmgr, dif_clkmgr_fatal_err_codes_t *codes);
/**
* Wait for external clock switch to finish.
*
* @param clkmgr Clock Manager Handle.
* @returns The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_wait_for_ext_clk_switch(const dif_clkmgr_t *clkmgr);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // SW_DEVICE_LIB_DIF_DIF_CLKMGR_H_