113 lines
2.9 KiB
C++
113 lines
2.9 KiB
C++
|
|
// ****************************************************************************
|
|
//
|
|
// Overclock
|
|
//
|
|
// ****************************************************************************
|
|
|
|
#include "include.h"
|
|
|
|
// Search PLL setup
|
|
// reqkhz ... required output frequency in kHz
|
|
// input ... PLL input frequency in kHz (default 12000, or use clock_get_hz(clk_ref)/1000)
|
|
// vcomin ... minimal VCO frequency in kHz (default 400000)
|
|
// vcomax ... maximal VCO frequency in kHz (default 1600000)
|
|
// lowvco ... prefer low VCO (lower power but more jiter)
|
|
// outputs:
|
|
// outkhz ... output achieved frequency in kHz (0=not found)
|
|
// outvco ... output VCO frequency in kHz
|
|
// outfbdiv ... output fbdiv (16..320)
|
|
// outpd1 ... output postdiv1 (1..7)
|
|
// outpd2 ... output postdiv2 (1..7)
|
|
// Returns true if precise frequency has been found, or near frequency used otherwise.
|
|
bool vcocalc(u32 reqkhz, u32 input, u32 vcomin, u32 vcomax, bool lowvco,
|
|
u32* outkhz, u32* outvco, u16* outfbdiv, u8* outpd1, u8* outpd2)
|
|
{
|
|
u32 khz, vco, margin;
|
|
u16 fbdiv;
|
|
u8 pd1, pd2;
|
|
u32 margin_best = 100000;
|
|
*outkhz = 0;
|
|
|
|
// fbdiv loop
|
|
fbdiv = lowvco ? 16 : 320;
|
|
for (;;)
|
|
{
|
|
// get current vco
|
|
vco = fbdiv * input;
|
|
|
|
// check vco range
|
|
if ((vco >= vcomin) && (vco <= vcomax))
|
|
{
|
|
// pd1 loop
|
|
for (pd1 = 7; pd1 >= 1; pd1--)
|
|
{
|
|
// pd2 loop
|
|
for (pd2 = pd1; pd2 >= 1; pd2--)
|
|
{
|
|
// current output frequency
|
|
khz = vco / (pd1 * pd2);
|
|
|
|
// check best frequency
|
|
margin = abs((int)(khz - reqkhz));
|
|
if (margin < margin_best)
|
|
{
|
|
margin_best = margin;
|
|
*outkhz = khz;
|
|
*outvco = vco;
|
|
*outfbdiv = fbdiv;
|
|
*outpd1 = pd1;
|
|
*outpd2 = pd2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// shift fbdiv
|
|
if (lowvco)
|
|
{
|
|
fbdiv++;
|
|
if (fbdiv > 320) break;
|
|
}
|
|
else
|
|
{
|
|
fbdiv--;
|
|
if (fbdiv < 16) break;
|
|
}
|
|
}
|
|
|
|
// check precise frequency
|
|
return (*outkhz == reqkhz) && (*outvco == *outkhz * *outpd1 * *outpd2);
|
|
}
|
|
|
|
// find sysclock setup (use set_sys_clock_pll to set sysclock)
|
|
// reqkhz ... required frequency in kHz
|
|
// outputs:
|
|
// outkhz ... output achieved frequency in kHz (0=not found)
|
|
// outvco ... output VCO frequency in kHz
|
|
// outfbdiv ... output fbdiv (16..320)
|
|
// outpd1 ... output postdiv1 (1..7)
|
|
// outpd2 ... output postdiv2 (1..7)
|
|
// Returns true if precise frequency has been found, or near frequency used otherwise.
|
|
bool FindSysClock(u32 reqkhz, u32* outkhz, u32* outvco, u16* outfbdiv, u8* outpd1, u8* outpd2)
|
|
{
|
|
// get reference frequency in kHz (should be 12 MHz)
|
|
u32 input = clock_get_hz(clk_ref)/1000;
|
|
|
|
// find PLL setup
|
|
return vcocalc(reqkhz, input, 400000, 1600000, false, outkhz, outvco, outfbdiv, outpd1, outpd2);
|
|
}
|
|
|
|
// set flash SSI speed (4 default, <4 faster, >4 slower)
|
|
void __not_in_flash_func(FlashSpeedSetup)(int baud)
|
|
{
|
|
// disable SSI for further config
|
|
ssi_hw->ssienr = 0;
|
|
|
|
// set baud rate
|
|
ssi_hw->baudr = baud;
|
|
|
|
// Re-enable
|
|
ssi_hw->ssienr = 1;
|
|
}
|