blob: fb31374fe39e7a6ced68bc9a6ab98f1a3858a641 [file] [log] [blame]
Christina Quast8be71e42014-12-02 13:06:01 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/*----------------------------------------------------------------------------
31 * Headers
32 *----------------------------------------------------------------------------*/
33
34#include "board.h"
35
36/*----------------------------------------------------------------------------
37 * Types
38 *----------------------------------------------------------------------------*/
39
40/*
41 * \brief Describes a possible clock configuration (processor clock & master clock),
42 * including the necessary register values.
43 */
44typedef struct _ClockConfiguration
45{
46
47 /** Processor clock frequency (in MHz). */
48 uint16_t pck;
49 /** Master clock frequency (in MHz). */
50 uint16_t mck;
51 /** CKGR_PLL reqister value. */
52 uint32_t pllr;
53 /** PMC_MCKR register value. */
54 uint32_t mckr;
55} ClockConfiguration ;
56
57/*----------------------------------------------------------------------------
58 * Local variables
59 *----------------------------------------------------------------------------*/
60
61/* Clock configurations for the AT91SAM3S4-EK */
62#define CKGR_MUL_SHIFT 16
63#define CKGR_PLLCOUNT_SHIFT 8
64#define CKGR_DIV_SHIFT 0
65
66/* Clock configuration for the AT91SAM3S */
67static const ClockConfiguration clockConfigurations[] = {
68
69 /* PCK = 24 MHz, MCK = 24 MHz
70 * PCK = 12000000 * (7+1) / 2 / 2 = 24 MHz
71 */
72 {24, 24, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
73 | (0x3f << CKGR_PLLCOUNT_SHIFT) \
74 | (2 << CKGR_DIV_SHIFT)),
75 ( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
76 /* PCK = 48 MHz, MCK = 48 MHz
77 * PCK = 12000000 * (7+1) / 1 / 2 = 48 MHz
78 */
79 {48, 48, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
80 | (0x3f << CKGR_PLLCOUNT_SHIFT) \
81 | (1 << CKGR_DIV_SHIFT)),
82 ( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
83 /* PCK = 64 MHz, MCK = 64 MHz
84 * PCK = 12000000 * (15+1) / 3 / 1 = 64 MHz
85 */
86 {64, 64, (CKGR_PLLAR_STUCKTO1 | (15 << CKGR_MUL_SHIFT) \
87 | (0x3f << CKGR_PLLCOUNT_SHIFT) \
88 | (3 << CKGR_DIV_SHIFT)),
89 ( PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)}
90};
91
92/* Number of available clock configurations */
93#define NB_CLOCK_CONFIGURATION (sizeof(clockConfigurations)/sizeof(clockConfigurations[0]))
94
95/* Current clock configuration */
96uint32_t currentConfig = 0; /* 0 have to be the default configuration */
97
98/*----------------------------------------------------------------------------
99 * Exported functions
100 *----------------------------------------------------------------------------*/
101
102/**
103 * \brief Sets the specified clock configuration.
104 *
105 * \param configuration Index of the configuration to set.
106 */
107void CLOCK_SetConfig(uint8_t configuration)
108{
109 TRACE_DEBUG("Setting clock configuration #%d ... ", configuration);
110 currentConfig = configuration;
111
112 /* Switch to main oscillator in two operations */
113 PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
114 while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
115
116 /* Configure PLL */
117 PMC->CKGR_PLLAR = clockConfigurations[configuration].pllr;
118 while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);
119
120 /* Configure master clock in two operations */
121 PMC->PMC_MCKR = (clockConfigurations[configuration].mckr & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
122 while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
123 PMC->PMC_MCKR = clockConfigurations[configuration].mckr;
124 while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0);
125
126 /* DBGU reconfiguration */
127 UART_Configure(115200, clockConfigurations[configuration].mck*1000000);
128 TRACE_DEBUG("done.\n\r");
129}
130
131/**
132 * \brief Display the user menu on the DBGU.
133 */
134void CLOCK_DisplayMenu(void)
135{
136 uint32_t i;
137
138 printf("\n\rMenu Clock configuration:\n\r");
139 for (i = 0; i < NB_CLOCK_CONFIGURATION; i++) {
140
141 printf(" %u: Set PCK = %3u MHz, MCK = %3u MHz %s\n\r",
142 (unsigned int)i,
143 (unsigned int)clockConfigurations[i].pck,
144 (unsigned int)clockConfigurations[i].mck,
145 (currentConfig==i)?"(curr)":"");
146 }
147}
148
149/**
150 * \brief Get the current MCK
151 */
152uint16_t CLOCK_GetCurrMCK(void)
153{
154 return clockConfigurations[currentConfig].mck;
155}
156
157/**
158 * \brief Get the current PCK
159 */
160uint16_t CLOCK_GetCurrPCK(void)
161{
162 return clockConfigurations[currentConfig].pck;
163}
164
165/**
166 * \brief Change clock configuration.
167 */
168void CLOCK_UserChangeConfig(void)
169{
170 uint8_t key = 0;
171
172 while (1)
173 {
174 CLOCK_DisplayMenu();
175 key = UART_GetChar();
176
177 if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1)))
178 {
179 CLOCK_SetConfig(key - '0');
180 break;
181 }
182 }
183}
184