diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 67db9b76b..c648a729f 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -101,12 +101,22 @@ bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32 if (freq > src_freq) return false; - uint32_t div = (uint32_t)((((uint64_t) src_freq) << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) / freq); - // only clock divider of 1, or >= 2 are supported - if (div < (2u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB)) { - div = (1u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB); + uint64_t div64 =((((uint64_t) src_freq) << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) / freq); + uint32_t div, actual_freq; + if (div64 >> 32) { + // set div to 0 for maximum clock divider + div = 0; + actual_freq = src_freq >> (32 - CLOCKS_CLK_GPOUT0_DIV_INT_LSB); + } else { + div = div64; +#if PICO_RP2040 + // on RP2040 only clock divider of 1, or >= 2 are supported + if (div < (2u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB)) { + div = (1u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB); + } +#endif + actual_freq = (uint32_t) ((((uint64_t) src_freq) << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) / div); } - uint32_t actual_freq = (uint32_t) ((((uint64_t) src_freq) << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) / div); clock_configure_internal(clock, src, auxsrc, actual_freq, div); // Store the configured frequency diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 400b6e431..ec6eb0609 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -269,16 +269,22 @@ typedef clock_num_t clock_handle_t; * frequency to be specified, and will set the clock divider to achieve the exact or higher frequency * achievable, with the maximum being the src_freq. * - * Note: That the clock hardware only support divisors of exactly 1 or 2.0->65535.0 + * \if rp2350_specific + * Note: The RP2350 clock hardware supports divisors from 1.0->65536.0 in steps of 1/65536 * - * See the tables in the description for details on the possible values for clock sources. + * \endif + * \if rp2040_specific + * Note: The RP2040 clock hardware only supports divisors of exactly 1.0 or 2.0->16777216.0 in steps of 1/256 + * \endif * + * See the tables in the description for details on the possible values for clock sources. * * \param clock The clock to configure * \param src The main clock source, can be 0. * \param auxsrc The auxiliary clock source, which depends on which clock is being set. Can be 0 * \param src_freq Frequency of the input clock source * \param freq Requested frequency + * \return true if the clock is updated, false if freq > src_freq */ bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);