Merge pull request #2616 from jmichelp/fix14b
[RRG-proxmark3.git] / common_arm / clocks.c
blob6e39eef87861563e0d9eb2fa9f641331751c9f5b
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 #include "clocks.h"
17 #include "proxmark3_arm.h"
19 void mck_from_pll_to_slck(void) {
20 // switch main clk to slow clk, first CSS then PRES
21 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK;
22 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
23 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_CSS_SLOW_CLK;
24 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
26 // disable the PLL
27 AT91C_BASE_PMC->PMC_PLLR = 0x0;
29 // disable main oscillator
30 AT91C_BASE_PMC->PMC_MOR = 0;
33 void mck_from_slck_to_pll(void) {
34 // worst case scenario, with MAINCK = 16MHz xtal, startup delay is 1.4ms
35 // if SLCK slow clock runs at its worst case (max) frequency of 42kHz
36 // max startup delay = (1.4ms*42k)/8 = 7.356 so round up to 8
37 // UPDATE:
38 // we observed on 10% of the devices very wrong initial slow clock RC TIA measures.
39 // Bumping delay to 16 helps fixing the issue even on the most screwed RC.
41 // enable main oscillator and set startup delay
42 AT91C_BASE_PMC->PMC_MOR =
43 AT91C_CKGR_MOSCEN |
44 PMC_MAIN_OSC_STARTUP_DELAY(16);
46 // wait for main oscillator to stabilize
47 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {};
49 // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00
50 // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10
51 // PLL output is MAINCK * multiplier / divisor = 16MHz * 12 / 2 = 96MHz
52 AT91C_BASE_PMC->PMC_PLLR =
53 PMC_PLL_DIVISOR(2) |
54 //PMC_PLL_COUNT_BEFORE_LOCK(0x10) |
55 PMC_PLL_COUNT_BEFORE_LOCK(0x3F) |
56 PMC_PLL_FREQUENCY_RANGE(0) |
57 PMC_PLL_MULTIPLIER(12) |
58 PMC_PLL_USB_DIVISOR(1);
60 // wait for PLL to lock
61 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {};
63 // we want a master clock (MCK) to be PLL clock / 2 = 96MHz / 2 = 48MHz
64 // datasheet recommends that this register is programmed in two operations
65 // when changing to PLL, program the prescaler first then the source
66 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK;
68 // wait for main clock ready signal
69 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
71 // set the source to PLL
72 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK;
74 // wait for main clock ready signal
75 while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};