1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "pico/stdlib.h"
8 #include "hardware/pll.h"
9 #include "hardware/clocks.h"
10 #if LIB_PICO_STDIO_UART
11 #include "pico/stdio_uart.h"
12 #else
13 #include "pico/binary_info.h"
14 #endif
15
16 // everything running off the USB oscillator
set_sys_clock_48mhz()17 void set_sys_clock_48mhz() {
18 if (!running_on_fpga()) {
19 // Change clk_sys to be 48MHz. The simplest way is to take this from PLL_USB
20 // which has a source frequency of 48MHz
21 clock_configure(clk_sys,
22 CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
23 CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
24 48 * MHZ,
25 48 * MHZ);
26
27 // Turn off PLL sys for good measure
28 pll_deinit(pll_sys);
29
30 // CLK peri is clocked from clk_sys so need to change clk_peri's freq
31 clock_configure(clk_peri,
32 0,
33 CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
34 48 * MHZ,
35 48 * MHZ);
36 }
37 }
38
set_sys_clock_pll(uint32_t vco_freq,uint post_div1,uint post_div2)39 void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2) {
40 if (!running_on_fpga()) {
41 clock_configure(clk_sys,
42 CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
43 CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
44 48 * MHZ,
45 48 * MHZ);
46
47 pll_init(pll_sys, 1, vco_freq, post_div1, post_div2);
48 uint32_t freq = vco_freq / (post_div1 * post_div2);
49
50 // Configure clocks
51 // CLK_REF = XOSC (12MHz) / 1 = 12MHz
52 clock_configure(clk_ref,
53 CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC,
54 0, // No aux mux
55 12 * MHZ,
56 12 * MHZ);
57
58 // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz
59 clock_configure(clk_sys,
60 CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
61 CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
62 freq, freq);
63
64 clock_configure(clk_peri,
65 0, // Only AUX mux on ADC
66 CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
67 48 * MHZ,
68 48 * MHZ);
69 }
70 }
71
check_sys_clock_khz(uint32_t freq_khz,uint * vco_out,uint * postdiv1_out,uint * postdiv_out)72 bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, uint *postdiv_out) {
73 uint crystal_freq_khz = clock_get_hz(clk_ref) / 1000;
74 for (uint fbdiv = 320; fbdiv >= 16; fbdiv--) {
75 uint vco = fbdiv * crystal_freq_khz;
76 if (vco < PICO_PLL_VCO_MIN_FREQ_MHZ * 1000 || vco > PICO_PLL_VCO_MAX_FREQ_MHZ * 1000) continue;
77 for (uint postdiv1 = 7; postdiv1 >= 1; postdiv1--) {
78 for (uint postdiv2 = postdiv1; postdiv2 >= 1; postdiv2--) {
79 uint out = vco / (postdiv1 * postdiv2);
80 if (out == freq_khz && !(vco % (postdiv1 * postdiv2))) {
81 *vco_out = vco * 1000;
82 *postdiv1_out = postdiv1;
83 *postdiv_out = postdiv2;
84 return true;
85 }
86 }
87 }
88 }
89 return false;
90 }
91
setup_default_uart()92 void setup_default_uart() {
93 #if LIB_PICO_STDIO_UART
94 stdio_uart_init();
95 #elif defined(PICO_DEFAULT_UART_BAUD_RATE) && defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN)
96 // this is mostly for backwards compatibility - stdio_uart_init is a bit more nuanced, and usually likely to be present
97 uart_init(uart_default, PICO_DEFAULT_UART_BAUD_RATE);
98 if (PICO_DEFAULT_UART_TX_PIN >= 0)
99 gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART);
100 if (PICO_DEFAULT_UART_RX_PIN >= 0)
101 gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART);
102 bi_decl_if_func_used(bi_2pins_with_func(PICO_DEFAULT_UART_RX_PIN, PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART));
103 #endif
104 }
105