static void stm32_rcc_RCC_PLLCFGR_write(Stm32Rcc *s, uint32_t new_value, bool init) { uint32_t new_PLLSRC, new_PLLP, new_PLLN, new_PLLM; /* PLLSRC */ new_PLLSRC = extract32(new_value, RCC_PLLCFGR_PLLSRC_BIT, 1); if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLSRC != s->RCC_PLLCFGR_PLLSRC)) { stm32_hw_warn("Can only change PLLSRC while PLL is disabled"); } } clktree_set_selected_input(s->PLLCLK, new_PLLSRC); s->RCC_PLLCFGR_PLLSRC = new_PLLSRC; new_PLLP = extract32(new_value, RCC_PLLCFGR_PLLP_START, RCC_PLLCFGR_PLLP_LENGTH); if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLP != s->RCC_PLLCFGR_PLLP)) { stm32_hw_warn("Can only change PLLP while PLL is disabled"); } } assert(new_PLLP <= 0xf); clktree_set_scale(s->PLLCLK, 1, 2 + 2 * new_PLLP); s->RCC_PLLCFGR_PLLP = new_PLLP; new_PLLM = extract32(new_value, RCC_PLLCFGR_PLLM_START, RCC_PLLCFGR_PLLM_LENGTH); new_PLLN = extract32(new_value, RCC_PLLCFGR_PLLN_START, RCC_PLLCFGR_PLLN_LENGTH); if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLM != s->RCC_PLLCFGR_PLLM || new_PLLN != s->RCC_PLLCFGR_PLLN)) { stm32_hw_warn("Can only change PLLM/N while PLL is disabled"); } } if(new_PLLN < 64 || new_PLLN > 432 || new_PLLM < 2) { stm32_hw_warn("Invalid PLLM (%u) or PLLN (%u) set", new_PLLM, new_PLLN); } else { clktree_set_scale(s->PLL_VCO, new_PLLN, new_PLLM); } s->RCC_PLLCFGR_PLLM = new_PLLM; s->RCC_PLLCFGR_PLLN = new_PLLN; DPRINT("PLLP=%u, PLLM=%u, PLLN=%u\n", new_PLLP, new_PLLM, new_PLLN); }
static void stm32_rcc_RCC_CFGR_write(Stm32Rcc *s, uint32_t new_value, bool init) { uint32_t new_PLLMUL, new_PLLXTPRE, new_PLLSRC; /* PLLMUL */ new_PLLMUL = (new_value & RCC_CFGR_PLLMUL_MASK) >> RCC_CFGR_PLLMUL_START; if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLMUL != s->RCC_CFGR_PLLMUL)) { stm32_hw_warn("Can only change PLLMUL while PLL is disabled"); } } assert(new_PLLMUL <= 0xf); if(new_PLLMUL == 0xf) { clktree_set_scale(s->PLLCLK, 16, 1); } else { clktree_set_scale(s->PLLCLK, new_PLLMUL + 2, 1); } s->RCC_CFGR_PLLMUL = new_PLLMUL; /* PLLXTPRE */ new_PLLXTPRE = GET_BIT_VALUE(new_value, RCC_CFGR_PLLXTPRE_BIT); if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLXTPRE != s->RCC_CFGR_PLLXTPRE)) { stm32_hw_warn("Can only change PLLXTPRE while PLL is disabled"); } } clktree_set_selected_input(s->PLLXTPRECLK, new_PLLXTPRE); s->RCC_CFGR_PLLXTPRE = new_PLLXTPRE; /* PLLSRC */ new_PLLSRC = GET_BIT_VALUE(new_value, RCC_CFGR_PLLSRC_BIT); if(!init) { if(clktree_is_enabled(s->PLLCLK) && (new_PLLSRC != s->RCC_CFGR_PLLSRC)) { stm32_hw_warn("Can only change PLLSRC while PLL is disabled"); } } clktree_set_selected_input(s->PLLCLK, new_PLLSRC); s->RCC_CFGR_PLLSRC = new_PLLSRC; /* PPRE2 */ s->RCC_CFGR_PPRE2 = (new_value & RCC_CFGR_PPRE2_MASK) >> RCC_CFGR_PPRE2_START; if(s->RCC_CFGR_PPRE2 < 0x4) { clktree_set_scale(s->PCLK2, 1, 1); } else { clktree_set_scale(s->PCLK2, 1, 2 * (s->RCC_CFGR_PPRE2 - 3)); } /* PPRE1 */ s->RCC_CFGR_PPRE1 = (new_value & RCC_CFGR_PPRE1_MASK) >> RCC_CFGR_PPRE1_START; if(s->RCC_CFGR_PPRE1 < 4) { clktree_set_scale(s->PCLK1, 1, 1); } else { clktree_set_scale(s->PCLK1, 1, 2 * (s->RCC_CFGR_PPRE1 - 3)); } /* HPRE */ s->RCC_CFGR_HPRE = (new_value & RCC_CFGR_HPRE_MASK) >> RCC_CFGR_HPRE_START; if(s->RCC_CFGR_HPRE < 8) { clktree_set_scale(s->HCLK, 1, 1); } else { clktree_set_scale(s->HCLK, 1, 2 * (s->RCC_CFGR_HPRE - 7)); } /* SW */ s->RCC_CFGR_SW = (new_value & RCC_CFGR_SW_MASK) >> RCC_CFGR_SW_START; switch(s->RCC_CFGR_SW) { case 0x0: case 0x1: case 0x2: clktree_set_selected_input(s->SYSCLK, s->RCC_CFGR_SW); break; default: hw_error("Invalid input selected for SYSCLK"); break; } }