//go:build rp2040 package machine import ( "device/rp" "runtime/volatile" "unsafe" ) type pll struct { cs volatile.Register32 pwr volatile.Register32 fbDivInt volatile.Register32 prim volatile.Register32 } var ( pllSys = (*pll)(unsafe.Pointer(rp.PLL_SYS)) pllUSB = (*pll)(unsafe.Pointer(rp.PLL_USB)) ) // init initializes pll (Sys or USB) given the following parameters. // // Input clock divider, refdiv. // // Requested output frequency from the VCO (voltage controlled oscillator), vcoFreq. // // Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2. // // Post Divider 2, postDiv2 with range 1-7. func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) { refFreq := xoscFreq / 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) fbdiv := vcoFreq / (refFreq * MHz) // Check fbdiv range if !(fbdiv >= 16 && fbdiv <= 320) { panic("fbdiv should be in the range [16,320]") } // Check divider ranges if !((postDiv1 >= 1 && postDiv1 <= 7) && (postDiv2 >= 1 && postDiv2 <= 7)) { panic("postdiv1, postdiv1 should be in the range [1,7]") } // postDiv1 should be >= postDiv2 // from appnote page 11 // postdiv1 is designed to operate with a higher input frequency // than postdiv2 if postDiv1 < postDiv2 { panic("postdiv1 should be greater than or equal to postdiv2") } // Check that reference frequency is no greater than vco / 16 if refFreq > vcoFreq/16 { panic("reference frequency should not be greater than vco frequency divided by 16") } // div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10 pdiv := postDiv1<