]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/bsp/install/include/metal/clock.h
277841e0125712ef72f8508dbc31bebdbe1bac0a
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / bsp / install / include / metal / clock.h
1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #ifndef METAL__CLOCK_H
5 #define METAL__CLOCK_H
6
7 /*! 
8  * @file clock.h
9  * @brief API for manipulating clock sources
10  *
11  * The clock interface allows for controlling the rate of various clocks in the system.
12  */
13
14 struct metal_clock;
15
16 #include <stddef.h>
17
18 /* The generic interface to all clocks. */
19 struct __metal_clock_vtable {
20     long (*get_rate_hz)(const struct metal_clock *clk);
21     long (*set_rate_hz)(struct metal_clock *clk, long hz);
22 };
23
24 /*!
25  * @brief Function signature of clock pre-rate change callbacks
26  */
27 typedef void (*metal_clock_pre_rate_change_callback)(void *priv);
28
29 /*!
30  * @brief Function signature of clock post-rate change callbacks
31  */
32 typedef void (*metal_clock_post_rate_change_callback)(void *priv);
33
34 /*!
35  * @struct metal_clock
36  * @brief The handle for a clock
37  *
38  * Clocks are defined as a pointer to a `struct metal_clock`, the contents of which
39  * are implementation defined. Users of the clock interface must call functions
40  * which accept a `struct metal_clock *` as an argument to interract with the clock.
41  *
42  * Note that no mechanism for obtaining a pointer to a `struct metal_clock` has been
43  * defined, making it impossible to call any of these functions without invoking
44  * implementation-defined behavior.
45  */
46 struct metal_clock {
47     const struct __metal_clock_vtable *vtable;
48
49     /* Pre-rate change callback */
50     metal_clock_pre_rate_change_callback _pre_rate_change_callback;
51     void *_pre_rate_change_callback_priv;
52
53     /* Post-rate change callback */
54     metal_clock_post_rate_change_callback _post_rate_change_callback;
55     void *_post_rate_change_callback_priv;
56 };
57
58 /*!
59  * @brief Returns the current rate of the given clock
60  *
61  * @param clk The handle for the clock
62  * @return The current rate of the clock in Hz
63  */
64 inline long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk->vtable->get_rate_hz(clk); }
65
66 /*!
67  * @brief Set the current rate of a clock
68  *
69  * @param clk The handle for the clock
70  * @param hz The desired rate in Hz
71  * @return The new rate of the clock in Hz.
72  *
73  * Attempts to set the current rate of the given clock to as close as possible
74  * to the given rate in Hz. Returns the actual value that's been selected, which
75  * could be anything!
76  *
77  * Prior to and after the rate change of the clock, this will call the registered
78  * pre- and post-rate change callbacks.
79  */
80 inline long metal_clock_set_rate_hz(struct metal_clock *clk, long hz)
81 {
82     if(clk->_pre_rate_change_callback != NULL)
83         clk->_pre_rate_change_callback(clk->_pre_rate_change_callback_priv);
84
85     long out = clk->vtable->set_rate_hz(clk, hz);
86
87     if (clk->_post_rate_change_callback != NULL)
88         clk->_post_rate_change_callback(clk->_post_rate_change_callback_priv);
89
90     return out;
91 }
92
93 /*!
94  * @brief Register a callback that must be called before a rate change
95  *
96  * @param clk The handle for the clock
97  * @param cb The callback to be registered
98  * @param priv Private data for the callback handler
99  */
100 inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_pre_rate_change_callback cb, void *priv)
101 {
102     clk->_pre_rate_change_callback = cb;
103     clk->_pre_rate_change_callback_priv = priv;
104 }
105
106 /*!
107  * @brief Registers a callback that must be called after a rate change
108  *
109  * @param clk The handle for the clock
110  * @param cb The callback to be registered
111  * @param priv Private data for the callback handler
112  */
113 inline void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_post_rate_change_callback cb, void *priv)
114 {
115     clk->_post_rate_change_callback = cb;
116     clk->_post_rate_change_callback_priv = priv;
117 }
118
119 #endif