Merge pull request #1335 from rad1game/patch-1
[RRG-proxmark3.git] / common_arm / clocks.c
blobc6fa874d3d61613e560817826e14c39ed79e169b
1 #include "clocks.h"
2 #include "proxmark3_arm.h"
4 void mck_from_pll_to_slck(void) {
5 // switch main clk to slow clk, first CSS then PRES
6 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK;
7 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
8 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_CSS_SLOW_CLK;
9 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
11 // disable the PLL
12 AT91C_BASE_PMC->PMC_PLLR = 0x0;
14 // disable main oscillator
15 AT91C_BASE_PMC->PMC_MOR = 0;
18 void mck_from_slck_to_pll(void) {
19 // worst case scenario, with MAINCK = 16MHz xtal, startup delay is 1.4ms
20 // if SLCK slow clock runs at its worst case (max) frequency of 42kHz
21 // max startup delay = (1.4ms*42k)/8 = 7.356 so round up to 8
22 // UPDATE:
23 // we observed on 10% of the devices very wrong initial slow clock RC TIA measures.
24 // Bumping delay to 16 helps fixing the issue even on the most screwed RC.
26 // enable main oscillator and set startup delay
27 AT91C_BASE_PMC->PMC_MOR =
28 AT91C_CKGR_MOSCEN |
29 PMC_MAIN_OSC_STARTUP_DELAY(16);
31 // wait for main oscillator to stabilize
32 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {};
34 // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00
35 // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10
36 // PLL output is MAINCK * multiplier / divisor = 16MHz * 12 / 2 = 96MHz
37 AT91C_BASE_PMC->PMC_PLLR =
38 PMC_PLL_DIVISOR(2) |
39 //PMC_PLL_COUNT_BEFORE_LOCK(0x10) |
40 PMC_PLL_COUNT_BEFORE_LOCK(0x3F) |
41 PMC_PLL_FREQUENCY_RANGE(0) |
42 PMC_PLL_MULTIPLIER(12) |
43 PMC_PLL_USB_DIVISOR(1);
45 // wait for PLL to lock
46 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {};
48 // we want a master clock (MCK) to be PLL clock / 2 = 96MHz / 2 = 48MHz
49 // datasheet recommends that this register is programmed in two operations
50 // when changing to PLL, program the prescaler first then the source
51 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK;
53 // wait for main clock ready signal
54 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
56 // set the source to PLL
57 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK;
59 // wait for main clock ready signal
60 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};