/* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2008, Atmel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ---------------------------------------------------------------------------- */ //------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------ #include "clock.h" #include #include //------------------------------------------------------------------------------ // Internal types //------------------------------------------------------------------------------ int currentConfig = 0; // 0 have to be the default configuration //------------------------------------------------------------------------------ /// Describes a possible clock configuration (processor clock & master clock), /// including the necessary register values. //------------------------------------------------------------------------------ struct ClockConfiguration { /// Processor clock frequency (in MHz). unsigned short pck; /// Master clock frequency (in MHz). unsigned short mck; /// CKGR_PLL reqister value. unsigned int pllr; /// PMC_MCKR register value. unsigned int mckr; }; //------------------------------------------------------------------------------ // Internal variables //------------------------------------------------------------------------------ // Clock configurations for the AT91SAM9263-EK #if defined(at91sam9263) #define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR #define AT91C_PMC_LOCK AT91C_PMC_LOCKA static const struct ClockConfiguration clockConfigurations[] = { // PCK = 200 MHz, MCK = 100 MHz {200, 100, 0x206DBF09, 0x00000102}, // PCK = 240 MHz, MCK = 120 MHz {240, 120, 0x202BC003, 0x00000102}, // PCK = 120 MHz, MCK = 120 MHz {120, 120, 0x20156003, 0x00000002}, // PCK = 96 MHz, MCK = 48 MHz {96, 48, 0x2057400F, 0x00000102}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x2057400F, 0x00000006} }; // Clock configurations for the AT91SAM9G20-EK #elif defined(at91sam9g20) #define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR #define AT91C_PMC_LOCK AT91C_PMC_LOCKA static const struct ClockConfiguration clockConfigurations[] = { // PCK = 400 MHz, MCK = 133 MHz {400, 133, 0x202A0101, 0x00001302}, // PCK = 200 MHz, MCK = 100 MHz {200, 100, 0x202A3F01, 0x0000010A}, // PCK = 96 MHz, MCK = 48 MHz {96, 48, 0x207C3F03, 0x0000010E}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x207C3F03, 0x00000012} }; // Clock configurations for the AT91SAM9XE-EK, AT91SAM9261-EK #elif defined(at91sam9xe128) || \ defined(at91sam9xe256) || \ defined(at91sam9xe512) || \ defined(at91sam9261) #define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR #define AT91C_PMC_LOCK AT91C_PMC_LOCKA static const struct ClockConfiguration clockConfigurations[] = { // PCK = 200 MHz, MCK = 100 MHz {200, 100, 0x208CBF0D, 0x00000102}, // PCK = 100 MHz, MCK = 100 MHz {100, 100, 0x20273F07, 0x00000002}, // PCK = 96 MHz, MCK = 48 MHz {96, 48, 0x20483F0E, 0x00000102}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x20483F0E, 0x00000006} }; // Clock configurations for the AT91SAM9RL64-EK, AT91CAP9-DK, AT91CAP9-STK #elif defined(at91sam9rl64) || \ defined(at91cap9) #define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR #define AT91C_PMC_LOCK AT91C_PMC_LOCKA static const struct ClockConfiguration clockConfigurations[] = { // PCK = 200 MHz, MCK = 100 MHz {200, 100, 0x2031BF03, 0x00000102}, // PCK = 100 MHz, MCK = 100 MHz {100, 100, 0x20183F03, 0x00000002}, // PCK = 96 MHz, MCK = 48 MHz {96, 48, 0x20073F01, 0x00000102}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x20073F01, 0x00000006} }; // Clock configuration for the AT91SAM7X-EK, AT91SAM7S-EK, AT91SAM7SE-EK #elif defined(at91sam7x128) || defined(at91sam7x256) || defined(at91sam7x512) \ || defined(at91sam7xc128) || defined(at91sam7xc256) || defined(at91sam7xc512) \ || defined(at91sam7s16) || defined(at91sam7s161) || defined(at91sam7s32) \ || defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) \ || defined(at91sam7s256) || defined(at91sam7s512) || defined(at91sam7se32) \ || defined(at91sam7se256) || defined(at91sam7se512) static const struct ClockConfiguration clockConfigurations[] = { // PCK = 55 MHz, MCK = 55 MHz {55, 55, 0x006A3F12, 0x00000007}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x00483F0E, 0x00000007}, }; // Clock configuration for the AT91SAM7A3 #elif defined(at91sam7a3) static const struct ClockConfiguration clockConfigurations[] = { // PCK = 60 MHz, MCK = 60 MHz {60, 60, 0x000C3F02, 0x00000007}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x00483F0E, 0x00000007} }; // Clock configurations for the AT91SAM9XE-EK, AT91SAM9261-EK #elif defined(at91sam9g10) #define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR #define AT91C_PMC_LOCK AT91C_PMC_LOCKA static const struct ClockConfiguration clockConfigurations[] = { // PCK = 266 MHz, MCK = 133 MHz {266, 133, 0x2064BF07, 0x00000102}, // PCK = 100 MHz, MCK = 100 MHz {100, 100, 0x20273F07, 0x00000002}, // PCK = 96 MHz, MCK = 48 MHz {96, 48, 0x20483F0E, 0x00000102}, // PCK = 48 MHz, MCK = 48 MHz {48, 48, 0x20483F0E, 0x00000006} }; // Clock configuration for the AT91SAM3U #elif defined(at91sam3u) static const struct ClockConfiguration clockConfigurations[] = { // PCK = 48 MHz, MCK = 48 MHz (default) {48, 48, 0x20073f01, 0x00000012}, // PCK = 96 MHz, MCK = 96 MHz {96, 96, 0x20073f01, 0x00000002}, // PCK = 24 MHz, MCK = 24 MHz {24, 24, 0x20073f02, 0x00000012} }; // No clock configuration #else #error No clock configuration for this board. #endif /// Number of available clock configurations #define NB_CLOCK_CONFIGURATION (sizeof(clockConfigurations)/sizeof(clockConfigurations[0])) //------------------------------------------------------------------------------ // Global Functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Sets the specified clock configuration. /// \param configuration Index of the configuration to set. //------------------------------------------------------------------------------ void CLOCK_SetConfig(unsigned char configuration) { TRACE_DEBUG("Setting clock configuration #%d ... ", configuration); currentConfig = configuration; // Switch to main oscillator in two operations AT91C_BASE_PMC->PMC_MCKR = (AT91C_BASE_PMC->PMC_MCKR & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK; while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0); // Configure PLL *AT91C_CKGR_PLLAR = clockConfigurations[configuration].pllr; while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) == 0); // Configure master clock in two operations AT91C_BASE_PMC->PMC_MCKR = (clockConfigurations[configuration].mckr & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK; while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0); AT91C_BASE_PMC->PMC_MCKR = clockConfigurations[configuration].mckr; while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0); // DBGU reconfiguration DBGU_Configure(DBGU_STANDARD, 115200, clockConfigurations[configuration].mck*1000000); TRACE_DEBUG("done.\n\r"); } //------------------------------------------------------------------------------ /// Display the user menu on the DBGU. //------------------------------------------------------------------------------ void CLOCK_DisplayMenu(void) { unsigned int i; printf("\n\rMenu Clock configuration:\n\r"); for (i = 0; i < NB_CLOCK_CONFIGURATION; i++) { printf(" %d: Set PCK = %3d MHz, MCK = %3d MHz %s\n\r", i, clockConfigurations[i].pck, clockConfigurations[i].mck, (currentConfig==i)?"(curr)":""); } } //------------------------------------------------------------------------------ /// Get the current MCK //------------------------------------------------------------------------------ unsigned short CLOCK_GetCurrMCK(void) { return clockConfigurations[currentConfig].mck; } //------------------------------------------------------------------------------ /// Get the current PCK //------------------------------------------------------------------------------ unsigned short CLOCK_GetCurrPCK(void) { return clockConfigurations[currentConfig].pck; } //------------------------------------------------------------------------------ /// Change clock configuration. //------------------------------------------------------------------------------ void CLOCK_UserChangeConfig(void) { unsigned char key = 0; while (1) { CLOCK_DisplayMenu(); key = DBGU_GetChar(); if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1))) { CLOCK_SetConfig(key - '0'); break; } } }