|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]> |
| 3 | + * SPDX-FileCopyrightText: 2025 HAW Hamburg |
| 4 | + * SPDX-License-Identifier: LGPL-2.1-only |
| 5 | + */ |
| 6 | + |
| 7 | +#pragma once |
| 8 | + |
| 9 | +/** |
| 10 | + * @ingroup cpu_rp2350 |
| 11 | + * @{ |
| 12 | + * |
| 13 | + * @file |
| 14 | + * @brief Clock configuration for the RP2350 |
| 15 | + * |
| 16 | + * @author Tom Hert <[email protected]> |
| 17 | + */ |
| 18 | + |
| 19 | +#include "RP2350.h" |
| 20 | +#include "macros/units.h" |
| 21 | + |
| 22 | +/** 1-15 MHz range |
| 23 | + * @see hardware/regs/xosc.h and chapter 8.2.8 |
| 24 | + */ |
| 25 | +#define XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ 0xaa0u |
| 26 | +/** 10-30 MHz range */ |
| 27 | +#define XOSC_CTRL_FREQ_RANGE_VALUE_10_30MHZ 0xaa1u |
| 28 | +/** 25-60 MHz range */ |
| 29 | +#define XOSC_CTRL_FREQ_RANGE_VALUE_25_60MHZ 0xaa2u |
| 30 | +/** 40-100 MHz range */ |
| 31 | +#define XOSC_CTRL_FREQ_RANGE_VALUE_40_100MHZ 0xaa3u |
| 32 | +/** Disable the XOSC */ |
| 33 | +#define XOSC_CTRL_ENABLE_VALUE_DISABLE 0xd1eu |
| 34 | +/** Enable the XOSC */ |
| 35 | +#define XOSC_CTRL_ENABLE_VALUE_ENABLE 0xfabu |
| 36 | +/** LSB of the enable bit */ |
| 37 | +#define XOSC_CTRL_ENABLE_LSB 12u |
| 38 | +/** Stable bit in the XOSC status register */ |
| 39 | +#define XOSC_STATUS_STABLE_BITS 0x80000000u |
| 40 | +/** Default crystal frequency is 12 MHz */ |
| 41 | +#define XOSC_HZ MHZ(12u) |
| 42 | +/** Reference divider for the PLL, set to 2 as per hardware manual */ |
| 43 | +#define PLL_REF_DIV 2u |
| 44 | +/** VCO frequency for the PLL, set to 750 MHz as per hardware manual */ |
| 45 | +#define PLL_VCO_FREQ 750000000u |
| 46 | +/** Post divider 1 for the PLL, set to 6 as per hardware manual */ |
| 47 | +#define PLL_PD1 6u |
| 48 | +/** Post divider 2 for the PLL, set to 2 as per hardware manual */ |
| 49 | +#define PLL_PD2 2u |
| 50 | +/** Power down bits for the PLL */ |
| 51 | +#define PLL_PWR_PD_BITS 0x00000001u |
| 52 | +/** VCO power down bits for the PLL */ |
| 53 | +#define PLL_PWR_VCOPD_BITS 0x00000020u |
| 54 | +/** Lock bit in the PLL control status register */ |
| 55 | +#define PLL_CS_LOCK_BITS 0x80000000u |
| 56 | +/** LSB of the post divider 1 in the PLL primary register */ |
| 57 | +#define PLL_PRIM_POSTDIV1_LSB 16u |
| 58 | +/** LSB of the post divider 2 in the PLL primary register */ |
| 59 | +#define PLL_PRIM_POSTDIV2_LSB 12u |
| 60 | +/** Post divider power down bits for the PLL */ |
| 61 | +#define PLL_PWR_POSTDIVPD_BITS 0x00000008u |
| 62 | +/** Enable bit for the peripheral clock control register */ |
| 63 | +#define CLK_PERI_CTRL_ENABLE_BIT (1u << 11u) |
| 64 | +/** Default CPU frequency in Hz, set to 125 MHz as per hardware manual */ |
| 65 | +#define CPUFREQ 125000000u |
| 66 | +/** Maximum crystal frequency */ |
| 67 | +#define CLOCK_XOSC_MAX MHZ(15u) |
| 68 | +/** Minimum crystal frequency */ |
| 69 | +#define CLOCK_XOSC_MIN MHZ(5u) |
| 70 | +/** Crystal frequency */ |
| 71 | +#define CLOCK_XOSC (XOSC_HZ) |
| 72 | +/** Minimum value of the post PLL clock divers */ |
| 73 | +#define PLL_POSTDIV_MIN 1u |
| 74 | +/** Maximum value of the post PLL clock divers */ |
| 75 | +#define PLL_POSTDIV_MAX 7u |
| 76 | +/** Minimum value of the PLL VCO feedback scaler */ |
| 77 | +#define PLL_VCO_FEEDBACK_SCALE_MIN 16u |
| 78 | +/** Maximum value of the PLL VCO feedback scaler */ |
| 79 | +#define PLL_VCO_FEEDBACK_SCALE_MAX 320u |
| 80 | +/** Minimum value of the clock divider applied before |
| 81 | + * feeding in the reference clock into the PLL */ |
| 82 | +#define PLL_REF_DIV_MIN 1u |
| 83 | +/** Minimum value of the clock divider applied before feeding in |
| 84 | + * the reference clock into the PLL */ |
| 85 | +#define PLL_REF_DIV_MAX 1u |
| 86 | +/** PLL feedback divider value, set to 125 as per hardware manual */ |
| 87 | +#define PLL_FEEDBACK_DIVIDER_VALUE 125u |
| 88 | +/** Enable bit for the system clock control register to select the peripheral |
| 89 | + * clock */ |
| 90 | +#define CLK_SYS_PERI_CTRL_ENABLE_BIT (1u << 0u) |
| 91 | +/** Selected field value for the system clock control register |
| 92 | + * to select the peripheral clock */ |
| 93 | +#define CLK_SYS_SELECTED_PERI_FIELD_VALUE 2u |
| 94 | +/** RIOT core clock frequency defined as the CPU frequency */ |
| 95 | +#define CLOCK_CORECLOCK MHZ(12u) |
| 96 | + |
| 97 | +#if (PLL_VCO_FEEDBACK_SCALE_MIN < PLL_VCO_FEEDBACK_SCALE_MIN) || \ |
| 98 | +(PLL_VCO_FEEDBACK_SCALE_MAX > PLL_VCO_FEEDBACK_SCALE_MAX) |
| 99 | +# error "Value for PLL_VCO_FEEDBACK_SCALE out of range, check config" |
| 100 | +#endif |
| 101 | +#if (PLL_REF_DIV_MIN < PLL_REF_DIV_MIN) || (PLL_REF_DIV_MAX > PLL_REF_DIV_MAX) |
| 102 | +# error "Value for PLLxosc_sleep_REF_DIV out of range, check config" |
| 103 | +#endif |
| 104 | +#if (PLL_POSTDIV_MIN < PLL_POSTDIV_MIN) || (PLL_POSTDIV_MAX > PLL_POSTDIV_MAX) |
| 105 | +# error "Value for PLL_POSTDIV out of range, check config" |
| 106 | +#endif |
| 107 | +#if ((CLOCK_XOSC > CLOCK_XOSC_MAX) || (CLOCK_XOSC < CLOCK_XOSC_MIN)) |
| 108 | +# error "Value for CLOCK_XOSC out of range, check config" |
| 109 | +#endif |
| 110 | + |
| 111 | +/** Post divider for the PLL, calculated based on the post divider values */ |
| 112 | +#define PDIV ((PLL_PD1 << PLL_PRIM_POSTDIV1_LSB) | (PLL_PD2 << PLL_PRIM_POSTDIV2_LSB)) |
| 113 | +/** Feedback divider for the PLL, calculated based on the VCO frequency and |
| 114 | +* reference clock frequency */ |
| 115 | +#define FBDIV ((PLL_VCO_FREQ / XOSC_HZ) / PLL_REF_DIV) |
| 116 | + |
| 117 | +#ifdef __cplusplus |
| 118 | +extern "C" { |
| 119 | +#endif |
| 120 | + |
| 121 | +/** |
| 122 | + * @brief Configures the Crystal to run. |
| 123 | + * @note The reference hardware manual suggests to use a 12 MHz crystal, which we |
| 124 | + * use by default. |
| 125 | + */ |
| 126 | +void xosc_start(void); |
| 127 | + |
| 128 | +/** |
| 129 | + * @brief Stop the crystal. |
| 130 | + */ |
| 131 | +void xosc_stop(void); |
| 132 | + |
| 133 | +/** |
| 134 | + * @brief Sleep for a given time in milliseconds. |
| 135 | + * @param milliseconds The time to sleep in milliseconds. |
| 136 | + */ |
| 137 | +void xosc_sleep(uint32_t milliseconds); |
| 138 | + |
| 139 | +/** |
| 140 | + * @brief Reset the clock system. |
| 141 | + * |
| 142 | + * This function resets the clock system to a known state. |
| 143 | + * It is recommended to call this function before configuring the clock system. |
| 144 | + */ |
| 145 | +void clock_reset(void); |
| 146 | + |
| 147 | +/** |
| 148 | + * @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it |
| 149 | + * @pre Make sure to call clock_reset() before this function to reset the |
| 150 | + * clock system |
| 151 | + * @see RP2350 Docs Chapter 8, mostly 8.2 for more details |
| 152 | + */ |
| 153 | +void cpu_clock_init(void); |
| 154 | + |
| 155 | +#ifdef __cplusplus |
| 156 | +} |
| 157 | +#endif |
| 158 | + |
| 159 | +/** @} */ |
0 commit comments