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
)) {};
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
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
=
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
=
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
)) {};