rp/clocks: provide fbdiv, not vco_freq

solvers usually output fbdiv directly, using vco_freq to get back to
fbdiv is not all that necessary or useful. both vco_freq and fbdiv have
hidden constraints, but vco_freq is a lot less accurate because the
fbdiv value resulting from the division may be off by almost a full
ref_freq's worth of frequency.

also fixes the usb pll config, which ran the pll vco way out of (below)
spec.
This commit is contained in:
pennae 2023-05-13 19:07:36 +02:00
parent d3494a4bdf
commit 5bbed31513

View File

@ -37,15 +37,15 @@ impl ClockConfig {
clock_type: ExternalClock::Crystal, clock_type: ExternalClock::Crystal,
sys_pll: Some(PllConfig { sys_pll: Some(PllConfig {
refdiv: 1, refdiv: 1,
vco_freq: 1500_000_000, fbdiv: 125,
post_div1: 6, post_div1: 6,
post_div2: 2, post_div2: 2,
}), }),
usb_pll: Some(PllConfig { usb_pll: Some(PllConfig {
refdiv: 1, refdiv: 1,
vco_freq: 480_000_000, fbdiv: 120,
post_div1: 5, post_div1: 6,
post_div2: 2, post_div2: 5,
}), }),
}), }),
ref_clk: RefClkConfig { ref_clk: RefClkConfig {
@ -126,7 +126,7 @@ pub struct XoscConfig {
pub struct PllConfig { pub struct PllConfig {
pub refdiv: u32, pub refdiv: u32,
pub vco_freq: u32, pub fbdiv: u16,
pub post_div1: u8, pub post_div1: u8,
pub post_div2: u8, pub post_div2: u8,
} }
@ -587,16 +587,15 @@ unsafe fn start_xosc(crystal_hz: u32) {
unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) { unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) {
let ref_freq = input_freq / config.refdiv; let ref_freq = input_freq / config.refdiv;
let fbdiv = config.vco_freq / ref_freq; assert!(config.fbdiv >= 16 && config.fbdiv <= 320);
assert!(fbdiv >= 16 && fbdiv <= 320);
assert!(config.post_div1 >= 1 && config.post_div1 <= 7); assert!(config.post_div1 >= 1 && config.post_div1 <= 7);
assert!(config.post_div2 >= 1 && config.post_div2 <= 7); assert!(config.post_div2 >= 1 && config.post_div2 <= 7);
assert!(config.post_div2 <= config.post_div1); assert!(config.post_div2 <= config.post_div1);
assert!(ref_freq <= (config.vco_freq / 16)); assert!(ref_freq >= 5_000_000 && ref_freq <= 800_000_000);
// Load VCO-related dividers before starting VCO // Load VCO-related dividers before starting VCO
p.cs().write(|w| w.set_refdiv(config.refdiv as _)); p.cs().write(|w| w.set_refdiv(config.refdiv as _));
p.fbdiv_int().write(|w| w.set_fbdiv_int(fbdiv as _)); p.fbdiv_int().write(|w| w.set_fbdiv_int(config.fbdiv));
// Turn on PLL // Turn on PLL
p.pwr().modify(|w| { p.pwr().modify(|w| {