コード例 #1
0
ファイル: stm32_clktree.c プロジェクト: LoxaLin/stm32onQEMU
Clk clktree_create_clk(
                    const char *name,
                    uint16_t multiplier,
                    uint16_t divisor,
                    bool enabled,
                    uint32_t max_output_freq,
                    int selected_input,
                    ...)
{
    va_list input_clks;
    Clk clk, input_clk;

    clk = clktree_create_generic(name, multiplier, divisor, enabled);

    /* Add the input clock connections. */
    va_start(input_clks, selected_input);
    while((input_clk = va_arg(input_clks, Clk)) != NULL) {
        CLKTREE_ADD_LINK(
                clk->input,
                clk->input_count,
                input_clk,
                CLKTREE_MAX_INPUT);

        CLKTREE_ADD_LINK(
                input_clk->output,
                input_clk->output_count,
                clk,
                CLKTREE_MAX_OUTPUT);
    }

    clktree_set_selected_input(clk, selected_input);

    return clk;
}
コード例 #2
0
ファイル: stm32_rcc.c プロジェクト: Crazyball1999/qemu_pebble
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);
}
コード例 #3
0
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;
    }
}