1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_CLOCKS_H
8 #define _HARDWARE_CLOCKS_H
9 
10 #include "pico.h"
11 #include "hardware/structs/clocks.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /** \file hardware/clocks.h
18  *  \defgroup hardware_clocks hardware_clocks
19  *
20  * Clock Management API
21  *
22  * This API provides a high level interface to the clock functions.
23  *
24  * The clocks block provides independent clocks to on-chip and external components. It takes inputs from a variety of clock
25  * sources allowing the user to trade off performance against cost, board area and power consumption. From these sources
26  * it uses multiple clock generators to provide the required clocks. This architecture allows the user flexibility to start and
27  * stop clocks independently and to vary some clock frequencies whilst maintaining others at their optimum frequencies
28  *
29  * Please refer to the datasheet for more details on the RP2040 clocks.
30  *
31  * The clock source depends on which clock you are attempting to configure. The first table below shows main clock sources. If
32  * you are not setting the Reference clock or the System clock, or you are specifying that one of those two will be using an auxiliary
33  * clock source, then you will need to use one of the entries from the subsequent tables.
34  *
35  * **Main Clock Sources**
36  *
37  * Source | Reference Clock | System Clock
38  * -------|-----------------|---------
39  * ROSC      | CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH     |  |
40  * Auxiliary | CLOCKS_CLK_REF_CTRL_SRC_VALUE_CLKSRC_CLK_REF_AUX | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX
41  * XOSC      | CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC        |  |
42  * Reference |                                                  | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF
43  *
44  * **Auxiliary Clock Sources**
45  *
46  * The auxiliary clock sources available for use in the configure function depend on which clock is being configured. The following table
47  * describes the available values that can be used. Note that for clk_gpout[x], x can be 0-3.
48  *
49  *
50  * Aux Source | clk_gpout[x] | clk_ref | clk_sys
51  * -----------|------------|---------|--------
52  * System PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS |                                                | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
53  * GPIO in 0  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0   | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0  | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
54  * GPIO in 1  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1   | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1  | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
55  * USB PLL    | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB| CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
56  * ROSC       | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_ROSC_CLKSRC    |                                                | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
57  * XOSC       | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_XOSC_CLKSRC    |                                                | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
58  * System clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_SYS      | | |
59  * USB Clock  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_USB        | | |
60  * ADC clock  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_ADC        | | |
61  * RTC Clock  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_RTC        | | |
62  * Ref clock  | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_REF        | | |
63  *
64  * Aux Source |  clk_peri | clk_usb | clk_adc
65  * -----------|-----------|---------|--------
66  * System PLL | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS    | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
67  * GPIO in 0  | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0      | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0   | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
68  * GPIO in 1  | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1      | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1   | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
69  * USB PLL    | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB    | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
70  * ROSC       | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH    | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
71  * XOSC       | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC       | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_XOSC_CLKSRC    | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
72  * System clock | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS         | | |
73  *
74  * Aux Source | clk_rtc
75  * -----------|----------
76  * System PLL |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
77  * GPIO in 0  |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
78  * GPIO in 1  |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
79  * USB PLL    |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
80  * ROSC       |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
81  * XOSC       |  CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
82 
83  *
84  * \section clock_example Example
85  * \addtogroup hardware_clocks
86  * \include hello_48MHz.c
87  */
88 
89 #define KHZ 1000
90 #define MHZ 1000000
91 
92 /// \tag::pll_settings[]
93 //
94 // There are two PLLs in RP2040:
95 // 1. The 'SYS PLL' generates the 125MHz system clock, the frequency is defined by `SYS_CLK_KHZ`.
96 // 2. The 'USB PLL' generates the 48MHz USB clock, the frequency is defined by `USB_CLK_KHZ`.
97 //
98 // The two PLLs use the crystal oscillator output directly as their reference frequency input; the PLLs reference
99 // frequency cannot be reduced by the dividers present in the clocks block. The crystal frequency is defined by `XOSC_KHZ` or
100 // `XOSC_MHZ`.
101 //
102 // The system's default definitions are correct for the above frequencies with a 12MHz
103 // crystal frequency.  If different frequencies are required, these must be defined in
104 // the board configuration file together with the revised PLL settings
105 // Use `vcocalc.py` to check and calculate new PLL settings if you change any of these frequencies.
106 //
107 // Default PLL configuration:
108 //                   REF     FBDIV VCO            POSTDIV
109 // PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz
110 // PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 =  48MHz
111 /// \end::pll_settings[]
112 
113 // PICO_CONFIG: PLL_COMMON_REFDIV, PLL reference divider setting - used for both PLLs, type=int, default=1, advanced=true, group=hardware_clocks
114 #ifndef PLL_COMMON_REFDIV
115 #define PLL_COMMON_REFDIV                   1
116 #endif
117 
118 #if (SYS_CLK_KHZ == 125000) && (XOSC_KHZ == 12000) && (PLL_COMMON_REFDIV == 1)
119 // PLL settings for standard 125 MHz system clock.
120 // PICO_CONFIG: PLL_SYS_VCO_FREQ_KHZ, System clock PLL frequency, type=int, default=1500 * KHZ, advanced=true, group=hardware_clocks
121 #ifndef PLL_SYS_VCO_FREQ_KHZ
122 #define PLL_SYS_VCO_FREQ_KHZ                (1500 * KHZ)
123 #endif
124 // PICO_CONFIG: PLL_SYS_POSTDIV1, System clock PLL post divider 1 setting, type=int, default=6, advanced=true, group=hardware_clocks
125 #ifndef PLL_SYS_POSTDIV1
126 #define PLL_SYS_POSTDIV1                    6
127 #endif
128 // PICO_CONFIG: PLL_SYS_POSTDIV2, System clock PLL post divider 2 setting, type=int, default=2, advanced=true, group=hardware_clocks
129 #ifndef PLL_SYS_POSTDIV2
130 #define PLL_SYS_POSTDIV2                    2
131 #endif
132 #endif // SYS_CLK_KHZ == 125000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
133 #if !defined(PLL_SYS_VCO_FREQ_KHZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2)
134 #error PLL_SYS_VCO_FREQ_KHZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup
135 #endif
136 
137 #if (USB_CLK_KHZ == 48000) && (XOSC_KHZ == 12000) && (PLL_COMMON_REFDIV == 1)
138 // PLL settings for a USB clock of 48MHz.
139 // PICO_CONFIG: PLL_USB_VCO_FREQ_KHZ, USB clock PLL frequency, type=int, default=1200 * KHZ, advanced=true, group=hardware_clocks
140 #ifndef PLL_USB_VCO_FREQ_KHZ
141 #define PLL_USB_VCO_FREQ_KHZ                (1200 * KHZ)
142 #endif
143 // PICO_CONFIG: PLL_USB_POSTDIV1, USB clock PLL post divider 1 setting, type=int, default=5, advanced=true, group=hardware_clocks
144 #ifndef PLL_USB_POSTDIV1
145 #define PLL_USB_POSTDIV1                    5
146 #endif
147 // PICO_CONFIG: PLL_USB_POSTDIV2, USB clock PLL post divider 2 setting, type=int, default=5, advanced=true, group=hardware_clocks
148 #ifndef PLL_USB_POSTDIV2
149 #define PLL_USB_POSTDIV2                    5
150 #endif
151 #endif // USB_CLK_KHZ == 48000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
152 #if !defined(PLL_USB_VCO_FREQ_KHZ) || !defined(PLL_USB_POSTDIV1) || !defined(PLL_USB_POSTDIV2)
153 #error PLL_USB_VCO_FREQ_KHZ, PLL_USB_POSTDIV1 and PLL_USB_POSTDIV2 must all be specified when using custom clock setup.
154 #endif
155 
156 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_CLOCKS, Enable/disable assertions in the clocks module, type=bool, default=0, group=hardware_clocks
157 #ifndef PARAM_ASSERTIONS_ENABLED_CLOCKS
158 #define PARAM_ASSERTIONS_ENABLED_CLOCKS 0
159 #endif
160 
161 /*! \brief Initialise the clock hardware
162  *  \ingroup hardware_clocks
163  *
164  *  Must be called before any other clock function.
165  */
166 void clocks_init(void);
167 
168 /*! \brief Configure the specified clock
169  *  \ingroup hardware_clocks
170  *
171  * See the tables in the description for details on the possible values for clock sources.
172  *
173  * \param clk_index The clock to configure
174  * \param src The main clock source, can be 0.
175  * \param auxsrc The auxiliary clock source, which depends on which clock is being set. Can be 0
176  * \param src_freq Frequency of the input clock source
177  * \param freq Requested frequency
178  */
179 bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);
180 
181 /*! \brief Stop the specified clock
182  *  \ingroup hardware_clocks
183  *
184  * \param clk_index The clock to stop
185  */
186 void clock_stop(enum clock_index clk_index);
187 
188 /*! \brief Get the current frequency of the specified clock
189  *  \ingroup hardware_clocks
190  *
191  * \param clk_index Clock
192  * \return Clock frequency in Hz
193  */
194 uint32_t clock_get_hz(enum clock_index clk_index);
195 
196 /*! \brief Measure a clocks frequency using the Frequency counter.
197  *  \ingroup hardware_clocks
198  *
199  * Uses the inbuilt frequency counter to measure the specified clocks frequency.
200  * Currently, this function is accurate to +-1KHz. See the datasheet for more details.
201  */
202 uint32_t frequency_count_khz(uint src);
203 
204 /*! \brief Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the clock
205  *  \ingroup hardware_clocks
206  *
207  * \see clock_get_hz()
208  */
209 void clock_set_reported_hz(enum clock_index clk_index, uint hz);
210 
211 /// \tag::frequency_count_mhz[]
frequency_count_mhz(uint src)212 static inline float frequency_count_mhz(uint src) {
213     return ((float) (frequency_count_khz(src))) / KHZ;
214 }
215 /// \end::frequency_count_mhz[]
216 
217 /*! \brief Resus callback function type.
218  *  \ingroup hardware_clocks
219  *
220  * User provided callback for a resus event (when clk_sys is stopped by the programmer and is restarted for them).
221  */
222 typedef void (*resus_callback_t)(void);
223 
224 /*! \brief Enable the resus function. Restarts clk_sys if it is accidentally stopped.
225  *  \ingroup hardware_clocks
226  *
227  * The resuscitate function will restart the system clock if it falls below a certain speed (or stops). This
228  * could happen if the clock source the system clock is running from stops. For example if a PLL is stopped.
229  *
230  * \param resus_callback a function pointer provided by the user to call if a resus event happens.
231  */
232 void clocks_enable_resus(resus_callback_t resus_callback);
233 
234 /*! \brief Output an optionally divided clock to the specified gpio pin.
235  *  \ingroup hardware_clocks
236  *
237  * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
238  * \param src  The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
239  * \param div_int  The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. this is in range of 1..2^24-1.
240  * \param div_frac The fractional part of the value to divide the source clock by. This is in range of 0..255 (/256).
241  */
242 void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac);
243 
244 /*! \brief Output an optionally divided clock to the specified gpio pin.
245  *  \ingroup hardware_clocks
246  *
247  * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
248  * \param src  The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
249  * \param div  The float amount to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock.
250  */
clock_gpio_init(uint gpio,uint src,float div)251 static inline void clock_gpio_init(uint gpio, uint src, float div)
252 {
253     uint div_int = (uint)div;
254     uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB));
255     clock_gpio_init_int_frac(gpio, src, div_int, frac);
256 }
257 
258 /*! \brief Configure a clock to come from a gpio input
259  *  \ingroup hardware_clocks
260  *
261  * \param clk_index The clock to configure
262  * \param gpio The GPIO pin to run the clock from. Valid GPIOs are: 20 and 22.
263  * \param src_freq Frequency of the input clock source
264  * \param freq Requested frequency
265  */
266 bool clock_configure_gpin(enum clock_index clk_index, uint gpio, uint32_t src_freq, uint32_t freq);
267 
268 
269 #ifdef __cplusplus
270 }
271 #endif
272 
273 #endif
274