diff --git a/include/libopencm3/sam3x/eefc.h b/include/libopencm3/sam3x/eefc.h index a2adf7e5..6fe70538 100644 --- a/include/libopencm3/sam3x/eefc.h +++ b/include/libopencm3/sam3x/eefc.h @@ -68,6 +68,11 @@ #define EEFC_FSR_FCMDE (0x01 << 1) #define EEFC_FSR_FRDY (0x01 << 0) +static inline void eefc_set_latency(u8 wait) +{ + EEFC_FMR(EEFC0) = (EEFC_FMR(EEFC0) & ~EEFC_FMR_FWS_MASK) | (wait << 8); + EEFC_FMR(EEFC1) = (EEFC_FMR(EEFC1) & ~EEFC_FMR_FWS_MASK) | (wait << 8); +} #endif diff --git a/include/libopencm3/sam3x/pmc.h b/include/libopencm3/sam3x/pmc.h index 9b4b63ee..b08bf51a 100644 --- a/include/libopencm3/sam3x/pmc.h +++ b/include/libopencm3/sam3x/pmc.h @@ -125,6 +125,15 @@ #define PMC_SR_LOCKA (0x01 << 1) #define PMC_SR_MOSCXTS (0x01 << 0) +enum mck_src { + MCK_SRC_SLOW = 0, + MCK_SRC_MAIN = 1, + MCK_SRC_PLLA = 2, + MCK_SRC_UPLL = 3, +}; + +void pmc_mck_set_source(enum mck_src src); +void pmc_xtal_enable(bool en, u8 startup_time); void pmc_plla_config(u8 mul, u8 div); void pmc_peripheral_clock_enable(u8 pid); void pmc_peripheral_clock_disable(u8 pid); diff --git a/lib/sam3x/pmc.c b/lib/sam3x/pmc.c index deeb8e1e..c37e325d 100644 --- a/lib/sam3x/pmc.c +++ b/lib/sam3x/pmc.c @@ -19,9 +19,20 @@ #include +void pmc_xtal_enable(bool en, u8 startup_time) +{ + if (en) { + CKGR_MOR |= CKGR_MOR_KEY | + CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST_MASK; + while (!(PMC_SR & PMC_SR_MOSCXTS)); + } else { + CKGR_MOR = CKGR_MOR_KEY | (CKGR_MOR & ~CKGR_MOR_MOSCXTEN); + } +} + void pmc_plla_config(u8 mul, u8 div) { - CKGR_PLLAR = CKGR_PLLAR_ONE | (mul << 16) | + CKGR_PLLAR = CKGR_PLLAR_ONE | ((mul - 1) << 16) | CKGR_PLLAR_PLLACOUNT_MASK | div; while (!(PMC_SR & PMC_SR_LOCKA)); } @@ -42,3 +53,9 @@ void pmc_peripheral_clock_disable(u8 pid) PMC_PCDR1 = 1 << (pid & 31); } +void pmc_mck_set_source(enum mck_src src) +{ + PMC_MCKR = (PMC_MCKR & ~PMC_MCKR_CSS_MASK) | src; + while (!(PMC_SR & PMC_SR_MCKRDY)); +} +