/* Configure PLL1 (Main MCU Clock) to max speed (204MHz). Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. This function shall be called after cpu_clock_init(). */ void cpu_clock_pll1_max_speed(void) { uint32_t pll_reg; /* Configure PLL1 to Intermediate Clock (between 90 MHz and 110 MHz) */ /* Integer mode: FCLKOUT = M*(FCLKIN/N) FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */ CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ /* Set PLL1 up to 12MHz * 8 = 96MHz. */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | CGU_PLL1_CTRL_PSEL(0) | CGU_PLL1_CTRL_NSEL(0) | CGU_PLL1_CTRL_MSEL(7) | CGU_PLL1_CTRL_FBSEL(1); CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); /* Wait before to switch to max speed */ delay(WAIT_CPU_CLOCK_INIT_DELAY); /* Configure PLL1 Max Speed */ /* Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */ CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ /* Set PLL1 up to 12MHz * 17 = 204MHz. */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | CGU_PLL1_CTRL_PSEL(0) | CGU_PLL1_CTRL_NSEL(0) | CGU_PLL1_CTRL_MSEL(9) //XXX: 16 | CGU_PLL1_CTRL_FBSEL(1) | CGU_PLL1_CTRL_DIRECT(1); CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); }
/* Configure PLL1 to low speed (48MHz). Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. This function shall be called after cpu_clock_init(). This function is mainly used to lower power consumption. */ void cpu_clock_pll1_low_speed(void) { uint32_t pll_reg; /* Configure PLL1 Clock (48MHz) */ /* Integer mode: FCLKOUT = M*(FCLKIN/N) FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */ CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ /* Set PLL1 up to 12MHz * 4 = 48MHz. */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | CGU_PLL1_CTRL_PSEL(0) | CGU_PLL1_CTRL_NSEL(0) | CGU_PLL1_CTRL_MSEL(3) | CGU_PLL1_CTRL_FBSEL(1) | CGU_PLL1_CTRL_DIRECT(1); CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); /* Wait a delay after switch to new frequency with Direct mode */ delay(WAIT_CPU_CLOCK_INIT_DELAY); }
/* Configure PLL1 to low speed with CGU_SRC_GP_CLKIN. Connect PLL1 to M4/M0 core, Peripheral, APB1, APB3. Init I2C0 & I2C1. This function is mainly used to lower power consumption. */ void cpu_clock_pll1_low_speed(const airspy_pll1_ls_t* const pt_airspy_pll1_ls_conf) { uint32_t pll_reg; uint32_t pll1_psel; uint32_t pll1_nsel; uint32_t pll1_msel; pll1_psel = pt_airspy_pll1_ls_conf->pll1_ls_psel; pll1_nsel = pt_airspy_pll1_ls_conf->pll1_ls_nsel; pll1_msel = pt_airspy_pll1_ls_conf->pll1_ls_msel; /* Configure PLL1 Clock */ /* Integer mode: FCLKOUT = M*(FCLKIN/N) FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS | /* BYPASS */ CGU_PLL1_CTRL_DIRECT | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ /* Set PLL1 */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_GP_CLKIN) | CGU_PLL1_CTRL_PSEL(pll1_psel) | CGU_PLL1_CTRL_NSEL(pll1_nsel) | CGU_PLL1_CTRL_MSEL(pll1_msel) | CGU_PLL1_CTRL_FBSEL | CGU_PLL1_CTRL_DIRECT; CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); }
/* Configure PLL1 to high speed with CGU_SRC_GP_CLKIN. (PLL1 High Speed compliant with UM10503 Rev. 1.8 — 28 January 2014 Fig 30. BASE_M4_CLK ramp-up procedure) Connect PLL1 to M4/M0 core, Peripheral, APB1, APB3. */ void cpu_clock_pll1_high_speed(const airspy_pll1_hs_t* const pt_airspy_pll1_hs_conf) { uint32_t pll_reg; uint32_t pll1_psel; uint32_t pll1_nsel; uint32_t pll1_msel; pll1_psel = pt_airspy_pll1_hs_conf->pll1_hs_psel; pll1_nsel = pt_airspy_pll1_hs_conf->pll1_hs_nsel; pll1_msel = pt_airspy_pll1_hs_conf->pll1_hs_msel; /* Configure PLL1 to Intermediate Clock final freq / 2 (because DIRECT=1) */ /* Integer mode: FCLKOUT = M*(FCLKIN/N) FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS | /* BYPASS */ CGU_PLL1_CTRL_DIRECT | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ #ifdef USE_PACKING pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_GP_CLKIN) | CGU_PLL1_CTRL_PSEL(pll1_psel) | CGU_PLL1_CTRL_NSEL(pll1_nsel) | CGU_PLL1_CTRL_MSEL(4) | CGU_PLL1_CTRL_FBSEL | CGU_PLL1_CTRL_DIRECT; #else /* Set PLL1 to High Speed/2 */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_GP_CLKIN) | CGU_PLL1_CTRL_PSEL(pll1_psel) | CGU_PLL1_CTRL_NSEL(pll1_nsel) | CGU_PLL1_CTRL_MSEL(pll1_msel) | CGU_PLL1_CTRL_FBSEL; CGU_PLL1_CTRL = pll_reg; #endif /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); /* Wait before to switch to max speed (at least 50us) See UM10503 Rev1.8 Fig 30. BASE_M4_CLK ramp-up procedure Page 150 / 1420 */ delay(WAIT_CPU_CLOCK_INIT_DELAY); /* Configure PLL1 High Speed (DIRECT=1) */ /* Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ pll_reg = CGU_PLL1_CTRL; /* Clear PLL1 bits */ pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ CGU_PLL1_CTRL_BYPASS | /* BYPASS */ CGU_PLL1_CTRL_DIRECT | /* DIRECT */ CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ /* Set PLL1 to HighSpeed */ pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_GP_CLKIN) | CGU_PLL1_CTRL_PSEL(pll1_psel) | CGU_PLL1_CTRL_NSEL(pll1_nsel) | CGU_PLL1_CTRL_MSEL(pll1_msel) | CGU_PLL1_CTRL_FBSEL | CGU_PLL1_CTRL_DIRECT; CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); }