1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #ifndef MOD_CSS_CLOCK_H 9 #define MOD_CSS_CLOCK_H 10 11 #include <fwk_element.h> 12 #include <fwk_id.h> 13 14 #include <stdbool.h> 15 #include <stdint.h> 16 17 /*! 18 * \addtogroup GroupModules Modules 19 * \{ 20 */ 21 22 /*! 23 * \defgroup GroupCSSClock CSS Clock Driver 24 * 25 * \details A driver for Arm Compute Sub-System clock devices. 26 * 27 * \{ 28 */ 29 30 /*! 31 * \brief Type of the clock (indexed vs non-indexed). 32 */ 33 enum mod_css_clock_type { 34 /*! A lookup table is used to find the settings for a given rate. */ 35 MOD_CSS_CLOCK_TYPE_INDEXED, 36 /*! The clock rate is set without looking up settings in a table. */ 37 MOD_CSS_CLOCK_TYPE_NON_INDEXED, 38 }; 39 40 /*! 41 * \brief APIs that the module makes available to entities requesting binding. 42 */ 43 enum mod_css_clock_api_types { 44 /*! Clock HAL */ 45 MOD_CSS_CLOCK_API_TYPE_CLOCK, 46 MOD_CSS_CLOCK_API_COUNT, 47 }; 48 49 /*! 50 * \brief Rate lookup table entry. 51 */ 52 struct mod_css_clock_rate { 53 /*! Rate of the clock in Hertz. */ 54 uint64_t rate; 55 56 /*! Rate of the source PLL in Hertz. */ 57 uint64_t pll_rate; 58 59 /*! The clock source used to attain the rate. */ 60 uint8_t clock_source; 61 62 /*! The clock divider to program. */ 63 uint8_t clock_div_type; 64 65 /*! The clock divider used to attain the rate. */ 66 uint32_t clock_div; 67 68 /*! The clock modulator numerator setting, if implemented. */ 69 uint32_t clock_mod_numerator; 70 71 /*! The clock modulator denominator setting, if implemented. */ 72 uint32_t clock_mod_denominator; 73 }; 74 75 /*! 76 * \brief Subsystem clock device configuration. 77 */ 78 struct mod_css_clock_dev_config { 79 /*! The type of the clock (indexed vs non-indexed). */ 80 enum mod_css_clock_type clock_type; 81 82 /*! Clock source used for non-indexed clocks. */ 83 uint8_t clock_default_source; 84 85 /*! Clock source used when changing the PLL rate. */ 86 uint8_t clock_switching_source; 87 88 /*! Element identifier for the associated PLL. */ 89 fwk_id_t pll_id; 90 91 /*! Reference to the API provided by the PLL driver. */ 92 fwk_id_t pll_api_id; 93 94 /*! Pointer to the table of clocks that are members of the group. */ 95 fwk_id_t const *member_table; 96 97 /*! The number of clocks in the member table. */ 98 uint32_t member_count; 99 100 /*! Reference to the API for the clocks that are members of the group. */ 101 fwk_id_t member_api_id; 102 103 /*! 104 * The rate, in Hz, that the member clocks run at before any configuration. 105 */ 106 uint64_t initial_rate; 107 108 /*! The clock's support for modulation. */ 109 bool modulation_supported; 110 111 /*! Pointer to the clock's rate lookup table. */ 112 struct mod_css_clock_rate const *rate_table; 113 114 /*! The number of rates in the rate lookup table. */ 115 uint32_t rate_count; 116 }; 117 118 /*! 119 * \brief CSS clock control interface. 120 */ 121 struct mod_css_clock_direct_api { 122 /*! Set the clock device's divider */ 123 int (*set_div)(fwk_id_t device_id, uint32_t divider_type, 124 uint32_t divider); 125 126 /*! Set the clock device's source (multi-source clocks only) */ 127 int (*set_source)(fwk_id_t device_id, uint8_t source); 128 129 /*! Set the clock device's modulator (multi-source clocks only) */ 130 int (*set_mod)(fwk_id_t device_id, uint32_t numerator, 131 uint32_t denominator); 132 133 /*! 134 * \brief Handle the condition where the state of a clock's power domain is 135 * about to change. 136 * 137 * \details This function will be called prior to the change in power 138 * state occurring so that the clock driver implementing this API is 139 * able to perform any required preparatory work beforehand. 140 * 141 * \note This function is optional. If the driver does not control any 142 * clocks that require power state awareness then the pointer may be set 143 * to NULL. 144 * 145 * \param clock_id Clock device identifier. 146 * 147 * \param current_state The current power state that the clock's power 148 * domain will transition away from. 149 * 150 * \param new_state The power state that the clock's power domain will 151 * transition to. 152 * 153 * \retval ::FWK_SUCCESS The operation succeeded. 154 * \return One of the standard framework error codes. 155 */ 156 int (*process_pending_power_transition)( 157 fwk_id_t clock_id, 158 unsigned int current_state, 159 unsigned int new_state); 160 161 /*! 162 * \brief Handle the condition where the state of a clock's power domain 163 * has changed. 164 * 165 * \details This function will be called after the change in power state 166 * has occurred. The driver can take any appropriate actions that are 167 * required to accommodate the new state. The transition can be to a 168 * deeper power state (e.g. ON->OFF) or to a shallower power state 169 * (e.g. OFF->ON). 170 * 171 * \note This function is optional. If the driver does not control any 172 * clocks that require power state awareness then the pointer may be set 173 * to NULL. 174 * 175 * \param clock_id Clock device identifier. 176 * 177 * \param state The power state that the clock's power domain transitioned 178 * to. 179 * 180 * \retval ::FWK_SUCCESS The operation succeeded. 181 * \return One of the standard framework error codes. 182 */ 183 int (*process_power_transition)(fwk_id_t clock_id, unsigned int state); 184 }; 185 186 /*! 187 * \} 188 */ 189 190 /*! 191 * \} 192 */ 193 194 #endif /* MOD_CSS_CLOCK_H */ 195