From 162098678b78df15b9a526b774e83e5ed4636bd7 Mon Sep 17 00:00:00 2001 From: majbthrd Date: Tue, 6 Apr 2021 04:42:18 -0500 Subject: [PATCH] move PLL reset code from clocks driver to pll driver (#110) * move PLL reset code from clocks driver to pll driver * Don't clear PLL PWR/FBDIV after reset as unnecessary. Call out in runtime.c why USB/syscfg aren't reset. Co-authored-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Co-authored-by: Luke Wren --- src/rp2_common/hardware_clocks/clocks.c | 4 --- src/rp2_common/hardware_pll/pll.c | 33 ++++++++++++++++--------- src/rp2_common/pico_runtime/runtime.c | 3 +++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index ac11680..c052956 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -7,7 +7,6 @@ #include "pico.h" #include "hardware/regs/clocks.h" #include "hardware/platform_defs.h" -#include "hardware/resets.h" #include "hardware/clocks.h" #include "hardware/watchdog.h" #include "hardware/pll.h" @@ -149,9 +148,6 @@ void clocks_init(void) { // PLL USB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz /// \end::pll_settings[] - reset_block(RESETS_RESET_PLL_SYS_BITS | RESETS_RESET_PLL_USB_BITS); - unreset_block_wait(RESETS_RESET_PLL_SYS_BITS | RESETS_RESET_PLL_USB_BITS); - /// \tag::pll_init[] pll_init(pll_sys, 1, 1500 * MHZ, 6, 2); pll_init(pll_usb, 1, 480 * MHZ, 5, 2); diff --git a/src/rp2_common/hardware_pll/pll.c b/src/rp2_common/hardware_pll/pll.c index 4daeb51..6cc6184 100644 --- a/src/rp2_common/hardware_pll/pll.c +++ b/src/rp2_common/hardware_pll/pll.c @@ -7,15 +7,11 @@ // For MHZ definitions etc #include "hardware/clocks.h" #include "hardware/pll.h" +#include "hardware/resets.h" /// \tag::pll_init_calculations[] void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div2) { - // Turn off PLL in case it is already running - pll->pwr = 0xffffffff; - pll->fbdiv_int = 0; - uint32_t ref_mhz = XOSC_MHZ / refdiv; - pll->cs = refdiv; // What are we multiplying the reference clock by to get the vco freq // (The regs are called div, because you divide the vco output and compare it to the refclk) @@ -34,11 +30,28 @@ void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div // than postdiv2 assert(post_div2 <= post_div1); -/// \tag::pll_init_finish[] // Check that reference frequency is no greater than vco / 16 assert(ref_mhz <= (vco_freq / 16)); - // Put calculated value into feedback divider + // div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10 + uint32_t pdiv = (post_div1 << PLL_PRIM_POSTDIV1_LSB) | + (post_div2 << PLL_PRIM_POSTDIV2_LSB); + +/// \tag::pll_init_finish[] + if ((pll->cs & PLL_CS_LOCK_BITS) && + (refdiv == (pll->cs & PLL_CS_REFDIV_BITS)) && + (fbdiv == (pll->fbdiv_int & PLL_FBDIV_INT_BITS)) && + (pdiv == (pll->prim & (PLL_PRIM_POSTDIV1_BITS & PLL_PRIM_POSTDIV2_BITS)))) { + // do not disrupt PLL that is already correctly configured and operating + return; + } + + uint32_t pll_reset = (pll_usb_hw == pll) ? RESETS_RESET_PLL_USB_BITS : RESETS_RESET_PLL_SYS_BITS; + reset_block(pll_reset); + unreset_block_wait(pll_reset); + + // Load VCO-related dividers before starting VCO + pll->cs = refdiv; pll->fbdiv_int = fbdiv; // Turn on PLL @@ -50,9 +63,7 @@ void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div // Wait for PLL to lock while (!(pll->cs & PLL_CS_LOCK_BITS)) tight_loop_contents(); - // Set up post dividers - div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10 - uint32_t pdiv = (post_div1 << PLL_PRIM_POSTDIV1_LSB) | - (post_div2 << PLL_PRIM_POSTDIV2_LSB); + // Set up post dividers pll->prim = pdiv; // Turn on post divider @@ -63,4 +74,4 @@ void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div void pll_deinit(PLL pll) { // todo: Make sure there are no sources running from this pll? pll->pwr = PLL_PWR_BITS; -} \ No newline at end of file +} diff --git a/src/rp2_common/pico_runtime/runtime.c b/src/rp2_common/pico_runtime/runtime.c index 2340ba7..b968bed 100644 --- a/src/rp2_common/pico_runtime/runtime.c +++ b/src/rp2_common/pico_runtime/runtime.c @@ -63,10 +63,13 @@ void runtime_init(void) { // Reset all peripherals to put system into a known state, // - except for QSPI pads and the XIP IO bank, as this is fatal if running from flash // - and the PLLs, as this is fatal if clock muxing has not been reset on this boot + // - and USB, syscfg, as this disturbs USB-to-SWD on core 1 reset_block(~( RESETS_RESET_IO_QSPI_BITS | RESETS_RESET_PADS_QSPI_BITS | RESETS_RESET_PLL_USB_BITS | + RESETS_RESET_USBCTRL_BITS | + RESETS_RESET_SYSCFG_BITS | RESETS_RESET_PLL_SYS_BITS ));