diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h index 1d23b9d1..53798884 100644 --- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h @@ -61,6 +61,11 @@ #endif #endif +// PICO_CONFIG: PICO_USE_FASTEST_SUPPORTED_CLOCK, Use the fastest officially supported clock by default, type=bool, default=0, group=hardware_base +#ifndef PICO_USE_FASTEST_SUPPORTED_CLOCK +#define PICO_USE_FASTEST_SUPPORTED_CLOCK 0 +#endif + // PICO_CONFIG: SYS_CLK_HZ, System operating frequency in Hz, type=int, default=125000000, advanced=true, group=hardware_base #ifndef SYS_CLK_HZ #ifdef SYS_CLK_KHZ @@ -68,9 +73,13 @@ #elif defined(SYS_CLK_MHZ) #define SYS_CLK_HZ ((SYS_CLK_MHZ) * _u(1000000)) #else +#if PICO_USE_FASTEST_SUPPORTED_CLOCK +#define SYS_CLK_HZ _u(200000000) +#else #define SYS_CLK_HZ _u(125000000) #endif #endif +#endif // PICO_CONFIG: USB_CLK_HZ, USB clock frequency. Must be 48MHz for the USB interface to operate correctly, type=int, default=48000000, advanced=true, group=hardware_base #ifndef USB_CLK_HZ diff --git a/src/rp2350/hardware_regs/include/hardware/platform_defs.h b/src/rp2350/hardware_regs/include/hardware/platform_defs.h index bd8b68a9..25dc1d62 100644 --- a/src/rp2350/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2350/hardware_regs/include/hardware/platform_defs.h @@ -89,6 +89,11 @@ #endif #endif +// PICO_CONFIG: PICO_USE_FASTEST_SUPPORTED_CLOCK, Use the fastest officially supported clock by default, type=bool, default=0, group=hardware_base +#ifndef PICO_USE_FASTEST_SUPPORTED_CLOCK +#define PICO_USE_FASTEST_SUPPORTED_CLOCK 0 +#endif + // PICO_CONFIG: SYS_CLK_HZ, System operating frequency in Hz, type=int, default=150000000, advanced=true, group=hardware_base #ifndef SYS_CLK_HZ #ifdef SYS_CLK_KHZ diff --git a/src/rp2_common/BUILD.bazel b/src/rp2_common/BUILD.bazel index 6ad8f224..fe1c0c3e 100644 --- a/src/rp2_common/BUILD.bazel +++ b/src/rp2_common/BUILD.bazel @@ -71,6 +71,7 @@ alias( "//src/rp2_common/hardware_base:__pkg__", "//src/rp2_common/hardware_irq:__pkg__", "//src/rp2_common/hardware_pll:__pkg__", + "//src/rp2_common/hardware_vreg:__pkg__", "//src/rp2_common/hardware_watchdog:__pkg__", "//src/rp2_common/hardware_xosc:__pkg__", "//src/rp2_common/pico_bit_ops:__pkg__", diff --git a/src/rp2_common/hardware_clocks/CMakeLists.txt b/src/rp2_common/hardware_clocks/CMakeLists.txt index 87312781..95b16c2f 100644 --- a/src/rp2_common/hardware_clocks/CMakeLists.txt +++ b/src/rp2_common/hardware_clocks/CMakeLists.txt @@ -10,4 +10,8 @@ pico_mirrored_target_link_libraries(hardware_clocks INTERFACE hardware_vreg hardware_watchdog hardware_xosc -) \ No newline at end of file +) + +if (PICO_USE_FASTEST_SUPPORTED_CLOCK) + target_compile_definitions(hardware_clocks INTERFACE PICO_USE_FASTEST_SUPPORTED_CLOCK=1) +endif() \ No newline at end of file diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index ec6eb060..8320cea2 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -206,6 +206,36 @@ extern "C" { #endif #endif // SYS_CLK_KHZ == 125000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1 +#if PICO_RP2040 && (SYS_CLK_HZ == 200 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_SYS_REFDIV == 1) +// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST, Should the regulator voltage be adjusted above SYS_CLK_VREG_VOLTAGE_MIN when initializing the clocks, type=bool, default=0, advanced=true, group=hardware_clocks +#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST +#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 1 +#endif +// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_MIN, minimum voltage (see VREG_VOLTAGE_x_xx) for the voltage regulator to be ensured during clock initialization if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST is 1, type=int, advanced=true, group=hardware_clocks +#if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST && !defined(SYS_CLK_VREG_VOLTAGE_MIN) +#define SYS_CLK_VREG_VOLTAGE_MIN VREG_VOLTAGE_1_15 +#endif +// PLL settings for fast 200 MHz system clock on RP2040 +#ifndef PLL_SYS_VCO_FREQ_HZ +#define PLL_SYS_VCO_FREQ_HZ (1200 * MHZ) +#endif +#ifndef PLL_SYS_POSTDIV1 +#define PLL_SYS_POSTDIV1 6 +#endif +#ifndef PLL_SYS_POSTDIV2 +#define PLL_SYS_POSTDIV2 1 +#endif +#else +#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST +#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 0 +#endif +#endif // PICO_RP2040 && SYS_CLK_KHZ == 200000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1 + +// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US, Number of microseconds to wait after updating regulator voltage due to SYS_CLK_VREG_VOLTAGE_MIN to allow voltage to settle, type=bool, default=1, advanced=true, group=hardware_clocks +#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US +#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US 1000 +#endif + #if !defined(PLL_SYS_VCO_FREQ_HZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2) #error PLL_SYS_VCO_FREQ_HZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup #endif diff --git a/src/rp2_common/hardware_vreg/BUILD.bazel b/src/rp2_common/hardware_vreg/BUILD.bazel index a1d381ee..d8f092be 100644 --- a/src/rp2_common/hardware_vreg/BUILD.bazel +++ b/src/rp2_common/hardware_vreg/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( target_compatible_with = compatible_with_rp2(), deps = [ "//src/rp2_common:hardware_structs", - "//src/rp2_common:pico_platform", + "//src/rp2_common:pico_platform_internal", "//src/rp2_common/hardware_base", ], ) diff --git a/src/rp2_common/hardware_vreg/include/hardware/vreg.h b/src/rp2_common/hardware_vreg/include/hardware/vreg.h index ce6ad0ca..011ba799 100644 --- a/src/rp2_common/hardware_vreg/include/hardware/vreg.h +++ b/src/rp2_common/hardware_vreg/include/hardware/vreg.h @@ -82,6 +82,13 @@ enum vreg_voltage { void vreg_set_voltage(enum vreg_voltage voltage); +/*! \brief Get voltage + * \ingroup hardware_vreg + * + * \return The current voltage (from enumeration \ref vreg_voltage) of the voltage regulator + **/ +enum vreg_voltage vreg_get_voltage(void); + /*! \brief Enable use of voltages beyond the safe range of operation * \ingroup hardware_vreg * diff --git a/src/rp2_common/hardware_vreg/vreg.c b/src/rp2_common/hardware_vreg/vreg.c index 61fd0804..b5a406c0 100644 --- a/src/rp2_common/hardware_vreg/vreg.c +++ b/src/rp2_common/hardware_vreg/vreg.c @@ -16,7 +16,7 @@ void vreg_set_voltage(enum vreg_voltage voltage) { VREG_AND_CHIP_RESET_VREG_VSEL_BITS ); -#elif PICO_RP2350 +#else hw_set_bits(&powman_hw->vreg_ctrl, POWMAN_PASSWORD_BITS | POWMAN_VREG_CTRL_UNLOCK_BITS); @@ -32,19 +32,21 @@ void vreg_set_voltage(enum vreg_voltage voltage) { while (powman_hw->vreg & POWMAN_VREG_UPDATE_IN_PROGRESS_BITS) tight_loop_contents(); +#endif +} + +enum vreg_voltage vreg_get_voltage(void) { +#if PICO_RP2040 + return (vreg_and_chip_reset_hw->vreg & VREG_AND_CHIP_RESET_VREG_VSEL_BITS) >> VREG_AND_CHIP_RESET_VREG_VSEL_LSB; #else - panic_unsupported(); + return (powman_hw->vreg & POWMAN_VREG_VSEL_BITS) >> POWMAN_VREG_VSEL_LSB; #endif } void vreg_disable_voltage_limit(void) { #if PICO_RP2040 - // The voltage limit can't be disabled on RP2040 (was implemented by - // hardwiring the LDO controls) - return; -#elif PICO_RP2350 - hw_set_bits(&powman_hw->vreg_ctrl, POWMAN_PASSWORD_BITS | POWMAN_VREG_CTRL_DISABLE_VOLTAGE_LIMIT_BITS); + // The voltage limit can't be disabled on RP2040 (was implemented by hard-wiring the LDO controls) #else - panic_unsupported(); + hw_set_bits(&powman_hw->vreg_ctrl, POWMAN_PASSWORD_BITS | POWMAN_VREG_CTRL_DISABLE_VOLTAGE_LIMIT_BITS); #endif } diff --git a/src/rp2_common/pico_runtime_init/BUILD.bazel b/src/rp2_common/pico_runtime_init/BUILD.bazel index ec5c4020..8956c4e1 100644 --- a/src/rp2_common/pico_runtime_init/BUILD.bazel +++ b/src/rp2_common/pico_runtime_init/BUILD.bazel @@ -34,6 +34,8 @@ cc_library( "//src/rp2_common/hardware_base", "//src/rp2_common/hardware_clocks", "//src/rp2_common/hardware_ticks", + "//src/rp2_common/hardware_timer", + "//src/rp2_common/hardware_vreg", "//src/rp2_common/pico_bootrom", "//src/rp2_common/pico_runtime", ], diff --git a/src/rp2_common/pico_runtime_init/CMakeLists.txt b/src/rp2_common/pico_runtime_init/CMakeLists.txt index 769e4aa1..81f6ab47 100644 --- a/src/rp2_common/pico_runtime_init/CMakeLists.txt +++ b/src/rp2_common/pico_runtime_init/CMakeLists.txt @@ -13,7 +13,7 @@ pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE ) if (TARGET hardware_clocks) - pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE hardware_clocks) + pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE hardware_clocks hardware_timer hardware_vreg) endif() # pico/runtime_init.h includes pico/runtime.h diff --git a/src/rp2_common/pico_runtime_init/runtime_init_clocks.c b/src/rp2_common/pico_runtime_init/runtime_init_clocks.c index 435a8016..85d473b8 100644 --- a/src/rp2_common/pico_runtime_init/runtime_init_clocks.c +++ b/src/rp2_common/pico_runtime_init/runtime_init_clocks.c @@ -10,6 +10,8 @@ #include "hardware/clocks.h" #include "hardware/pll.h" #include "hardware/ticks.h" +#include "hardware/timer.h" +#include "hardware/vreg.h" #include "hardware/xosc.h" #if PICO_RP2040 #include "hardware/regs/rtc.h" @@ -85,6 +87,15 @@ void __weak runtime_init_clocks(void) { 0, XOSC_HZ); + // This must be done after we've configured CLK_REF to XOSC due to the need to time a delay +#if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST && defined(SYS_CLK_VREG_VOLTAGE_MIN) + if (vreg_get_voltage() < SYS_CLK_VREG_VOLTAGE_MIN) { + vreg_set_voltage(SYS_CLK_VREG_VOLTAGE_MIN); + // wait for voltage to settle; must use CPU cycles as TIMER is not yet clocked correctly + busy_wait_at_least_cycles((uint32_t)((SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US * (uint64_t)XOSC_HZ) / 1000000)); + } +#endif + /// \tag::configure_clk_sys[] // CLK SYS = PLL SYS (usually) 125MHz / 1 = 125MHz clock_configure_undivided(clk_sys,