Example #1
0
File: cpu.c Project: ant9000/RIOT
/**
 * @brief   Configure clock sources and the cpu frequency
 */
static void clk_init(void)
{
    /* enable clocks for the power, sysctrl and gclk modules */
    PM->APBAMASK.reg = (PM_APBAMASK_PM | PM_APBAMASK_SYSCTRL |
                        PM_APBAMASK_GCLK);

    /* adjust NVM wait states, see table 42.30 (p. 1070) in the datasheet */
#if (CLOCK_CORECLOCK > 24000000)
    PM->APBAMASK.reg |= PM_AHBMASK_NVMCTRL;
    NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(1);
    PM->APBAMASK.reg &= ~PM_AHBMASK_NVMCTRL;
#endif

    /* configure internal 8MHz oscillator to run without prescaler */
    SYSCTRL->OSC8M.bit.PRESC = 0;
    SYSCTRL->OSC8M.bit.ONDEMAND = 1;
    SYSCTRL->OSC8M.bit.RUNSTDBY = 0;
    SYSCTRL->OSC8M.bit.ENABLE = 1;
    while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC8MRDY)) {}

#if CLOCK_USE_PLL
    /* reset the GCLK module so it is in a known state */
    GCLK->CTRL.reg = GCLK_CTRL_SWRST;
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* setup generic clock 1 to feed DPLL with 1MHz */
    GCLK->GENDIV.reg = (GCLK_GENDIV_DIV(8) |
                        GCLK_GENDIV_ID(1));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_OSC8M |
                         GCLK_GENCTRL_ID(1));
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN(1) |
                         GCLK_CLKCTRL_ID(1) |
                         GCLK_CLKCTRL_CLKEN);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* enable PLL */
    SYSCTRL->DPLLRATIO.reg = (SYSCTRL_DPLLRATIO_LDR(CLOCK_PLL_MUL));
    SYSCTRL->DPLLCTRLB.reg = (SYSCTRL_DPLLCTRLB_REFCLK_GCLK);
    SYSCTRL->DPLLCTRLA.reg = (SYSCTRL_DPLLCTRLA_ENABLE);
    while(!(SYSCTRL->DPLLSTATUS.reg &
           (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK))) {}

    /* select the PLL as source for clock generator 0 (CPU core clock) */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_DIV(CLOCK_PLL_DIV) |
                        GCLK_GENDIV_ID(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_FDPLL |
                         GCLK_GENCTRL_ID(0));
#else /* do not use PLL, use internal 8MHz oscillator directly */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_DIV(CLOCK_DIV) |
                        GCLK_GENDIV_ID(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_OSC8M |
                         GCLK_GENCTRL_ID(0));
#endif

    /* make sure we synchronize clock generator 0 before we go on */
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}

    /* Setup Clock generator 2 with divider 1 (32.768kHz) */
    GCLK->GENDIV.reg  = (GCLK_GENDIV_ID(2)  | GCLK_GENDIV_DIV(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_GENEN |
            GCLK_GENCTRL_RUNSTDBY |
            GCLK_GENCTRL_SRC_OSCULP32K);

    while (GCLK->STATUS.bit.SYNCBUSY) {}

    /* redirect all peripherals to a disabled clock generator (7) by default */
    for (int i = 0x3; i <= 0x22; i++) {
        GCLK->CLKCTRL.reg = ( GCLK_CLKCTRL_ID(i) | GCLK_CLKCTRL_GEN_GCLK7 );
        while (GCLK->STATUS.bit.SYNCBUSY) {}
    }
}
Example #2
0
void _sysctrl_init_referenced_generators(void)
{
	void *hw = (void *)SYSCTRL;

#if CONF_DFLL_CONFIG == 1

#    if CONF_DFLL_USBCRM != 1 && CONF_DFLL_MODE != CONF_DFLL_OPEN_LOOP_MODE
			hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(0) |
			GCLK_CLKCTRL_GEN(CONF_DFLL_GCLK) |
			( 1 << GCLK_CLKCTRL_CLKEN_Pos ));
#    endif

		hri_sysctrl_write_DFLLCTRL_reg(hw, SYSCTRL_DFLLCTRL_ENABLE);
		while(!hri_sysctrl_get_PCLKSR_DFLLRDY_bit(hw)) {;
		}

		hri_sysctrl_write_DFLLMUL_reg(hw, SYSCTRL_DFLLMUL_CSTEP(
				CONF_DFLL_CSTEP) |
			SYSCTRL_DFLLMUL_FSTEP(CONF_DFLL_FSTEP) |
			SYSCTRL_DFLLMUL_MUL(CONF_DFLL_MUL));
		hri_sysctrl_write_DFLLVAL_reg(hw, CONF_DFLLVAL);

		hri_sysctrl_dfllctrl_reg_t tmp =

			( CONF_DFLL_WAITLOCK << SYSCTRL_DFLLCTRL_WAITLOCK_Pos ) |
			( CONF_DFLL_BPLCKC << SYSCTRL_DFLLCTRL_BPLCKC_Pos ) |
			( CONF_DFLL_QLDIS << SYSCTRL_DFLLCTRL_QLDIS_Pos ) |
			( CONF_DFLL_CCDIS << SYSCTRL_DFLLCTRL_CCDIS_Pos ) |
			( CONF_DFLL_RUNSTDBY << SYSCTRL_DFLLCTRL_RUNSTDBY_Pos ) |
			( CONF_DFLL_USBCRM << SYSCTRL_DFLLCTRL_USBCRM_Pos ) |
			( CONF_DFLL_LLAW << SYSCTRL_DFLLCTRL_LLAW_Pos ) |
			( CONF_DFLL_STABLE << SYSCTRL_DFLLCTRL_STABLE_Pos ) |
			( CONF_DFLL_MODE << SYSCTRL_DFLLCTRL_MODE_Pos ) |
			( CONF_DFLL_ENABLE << SYSCTRL_DFLLCTRL_ENABLE_Pos );

		hri_sysctrl_write_DFLLCTRL_reg(hw, tmp);
#endif

#if CONF_DPLL_CONFIG == 1
#    if CONF_DPLL_REFCLK == SYSCTRL_DPLLCTRLB_REFCLK_GCLK_Val
			hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(1) |
			GCLK_CLKCTRL_GEN(CONF_DPLL_GCLK) | ( 1 << GCLK_CLKCTRL_CLKEN_Pos ));
#    endif

		hri_sysctrl_write_DPLLCTRLA_reg(hw,
			( CONF_DPLL_RUNSTDBY << SYSCTRL_DPLLCTRLA_RUNSTDBY_Pos ) |
			( CONF_DPLL_ENABLE << SYSCTRL_DPLLCTRLA_ENABLE_Pos ));
		hri_sysctrl_write_DPLLRATIO_reg(hw,
			SYSCTRL_DPLLRATIO_LDRFRAC(CONF_DPLL_LDRFRAC) |
			SYSCTRL_DPLLRATIO_LDR(CONF_DPLL_LDR));
		hri_sysctrl_write_DPLLCTRLB_reg(hw, SYSCTRL_DPLLCTRLB_DIV(
				CONF_DPLL_DIV) |
			( CONF_DPLL_LBYPASS << SYSCTRL_DPLLCTRLB_LBYPASS_Pos ) |
			SYSCTRL_DPLLCTRLB_LTIME(CONF_DPLL_LTIME) |
			SYSCTRL_DPLLCTRLB_REFCLK(CONF_DPLL_REFCLK) |
			( CONF_DPLL_WUF << SYSCTRL_DPLLCTRLB_WUF_Pos ) |
			( CONF_DPLL_LPEN << SYSCTRL_DPLLCTRLB_LPEN_Pos ) |
			SYSCTRL_DPLLCTRLB_FILTER(CONF_DPLL_FILTER));
#endif

#if CONF_DFLL_CONFIG == 1
#    if CONF_DFLL_ENABLE == 1

			if (hri_sysctrl_get_DFLLCTRL_MODE_bit(hw)) {
#        if CONF_DFLL_USBCRM == 0
					hri_sysctrl_pclksr_reg_t status_mask =
				SYSCTRL_PCLKSR_DFLLRDY |
				SYSCTRL_PCLKSR_DFLLLCKF | SYSCTRL_PCLKSR_DFLLLCKC;
#        else
						hri_sysctrl_pclksr_reg_t status_mask =
				SYSCTRL_PCLKSR_DFLLRDY;
#        endif

					while(hri_sysctrl_get_PCLKSR_reg(hw,
					status_mask) != status_mask) {;
					}
			} else {
				while(!hri_sysctrl_get_PCLKSR_DFLLRDY_bit(hw)) {;
				}
			}

#    endif
#    if CONF_DFLL_ONDEMAND == 1
					hri_sysctrl_set_DFLLCTRL_ONDEMAND_bit(hw);
#    endif
#endif

#if CONF_DPLL_CONFIG == 1
#    if CONF_DPLL_ENABLE == 1
				while (!( hri_sysctrl_get_DPLLSTATUS_ENABLE_bit(hw) ||
				hri_sysctrl_get_DPLLSTATUS_LOCK_bit(hw) ||
				hri_sysctrl_get_DPLLSTATUS_CLKRDY_bit(hw))) {;
				}
#    endif
#    if CONF_DPLL_ONDEMAND == 1
				hri_sysctrl_set_DPLLCTRLA_ONDEMAND_bit(hw);
#    endif
#endif

#if CONF_DFLL_CONFIG == 1
			while(hri_gclk_get_STATUS_SYNCBUSY_bit(GCLK)) {;
			}
#endif

#if CONF_OSC32K_CONFIG == 0 || CONF_OSC32K_ENABLE == 0
		    /* Disable after all possible configurations needs sync written. */
			hri_sysctrl_clear_OSC32K_ENABLE_bit(hw);
#endif

		(void)hw;
}