diff --git a/ChangeLog b/ChangeLog index 85bd587258dde890260a3ab06051faf5372822cc..750cee5577c752aa3e3206b0dca1fe4fdf2280fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4532,3 +4532,7 @@ leaving the interrupts in a strange state (2013-4-7). * arch/arm/src/lpc17_lcd.c: Rommel Marcelo go the LPC1788 framebuffer-based LCD working. Very nice! (2013-4-08). + * arch/arm/src/lm/lm_clockconfig.c and configs/lm4f120-launchpad: + Fix handling of the RCC SYSDIV2 field whent the PLL output is + 400MHz. Don't forget to set the USERCC2 bit in the register or + all is for naught (2013-4-09). diff --git a/arch/arm/src/lm/chip/lm4f_syscontrol.h b/arch/arm/src/lm/chip/lm4f_syscontrol.h index e0701c11e62f4f2a92cdd158e541874d9eb98c6d..cc7659f299e77a258b101dbd60b8131824e04c17 100644 --- a/arch/arm/src/lm/chip/lm4f_syscontrol.h +++ b/arch/arm/src/lm/chip/lm4f_syscontrol.h @@ -475,7 +475,8 @@ #define SYSCON_RCC2_SYSDIV2_SHIFT 23 /* Bits 28-23: System Clock Divisor */ #define SYSCON_RCC2_SYSDIV2_MASK (0x3f << SYSCON_RCC2_SYSDIV2_SHIFT) # define SYSCON_RCC2_SYSDIV(n) ((n-1) << SYSCON_RCC2_SYSDIV2_SHIFT) -#define SYSCON_RCC2_DIV400 (1 << 30) /* Bit 3-: Divide PLL as 400 MHz vs. 200 MHz */ +# define SYSCON_RCC2_SYSDIV_DIV400(n) (((n-1) >> 1) << SYSCON_RCC2_SYSDIV2_SHIFT) +#define SYSCON_RCC2_DIV400 (1 << 30) /* Bit 30: Divide PLL as 400 MHz vs. 200 MHz */ #define SYSCON_RCC2_USERCC2 (1 << 31) /* Bit 31: Use RCC2 When set */ /* Main Oscillator Control */ diff --git a/arch/arm/src/lm/lm_syscontrol.c b/arch/arm/src/lm/lm_syscontrol.c index 3c4c31a7b5d5bd8e965691ab721731db770437a4..b4210c44aa5497e2f1d0e8cacec33372bafeb6ca 100644 --- a/arch/arm/src/lm/lm_syscontrol.c +++ b/arch/arm/src/lm/lm_syscontrol.c @@ -57,26 +57,29 @@ ****************************************************************************/ #ifdef LM4F -# define RCC_OSCMASK (SYSCON_RCC_MOSCDIS) +# define RCC_OSCMASK (SYSCON_RCC_MOSCDIS) +# define RCC_XTALMASK (SYSCON_RCC_XTAL_MASK | SYSCON_RCC_OSCSRC_MASK | \ + SYSCON_RCC_PWRDN) +# define RCC2_XTALMASK (SYSCON_RCC2_OSCSRC2_MASK | SYSCON_RCC2_PWRDN2 | \ + SYSCON_RCC2_SYSDIV2LSB | SYSCON_RCC2_SYSDIV2_MASK | \ + SYSCON_RCC2_DIV400 | SYSCON_RCC2_USERCC2) +# define RCC_DIVMASK (SYSCON_RCC_SYSDIV_MASK | SYSCON_RCC_USESYSDIV | \ + SYSCON_RCC_MOSCDIS) +# define RCC2_DIVMASK (SYSCON_RCC2_SYSDIV2LSB | SYSCON_RCC2_SYSDIV2_MASK) #else -# define RCC_OSCMASK (SYSCON_RCC_IOSCDIS|SYSCON_RCC_MOSCDIS) +# define RCC_OSCMASK (SYSCON_RCC_IOSCDIS | SYSCON_RCC_MOSCDIS) +# define RCC_XTALMASK (SYSCON_RCC_XTAL_MASK | SYSCON_RCC_OSCSRC_MASK | \ + SYSCON_RCC_PWRDN) +# define RCC2_XTALMASK (SYSCON_RCC2_OSCSRC2_MASK | SYSCON_RCC2_PWRDN2 | \ + SYSCON_RCC2_SYSDIV2_MASK | SYSCON_RCC2_USERCC2) +# define RCC_DIVMASK (SYSCON_RCC_SYSDIV_MASK | SYSCON_RCC_USESYSDIV | \ + SYSCON_RCC_IOSCDIS | SYSCON_RCC_MOSCDIS) +# define RCC2_DIVMASK (SYSCON_RCC2_SYSDIV2_MASK) #endif -#define RCC_XTALMASK (SYSCON_RCC_XTAL_MASK|SYSCON_RCC_OSCSRC_MASK|\ - SYSCON_RCC_PWRDN) -#define RCC2_XTALMASK (SYSCON_RCC2_USERCC2|SYSCON_RCC2_OSCSRC2_MASK|\ - SYSCON_RCC2_PWRDN2) -#ifdef LM4F -# define RCC_DIVMASK (SYSCON_RCC_SYSDIV_MASK|SYSCON_RCC_USESYSDIV|\ - SYSCON_RCC_MOSCDIS) -#else -# define RCC_DIVMASK (SYSCON_RCC_SYSDIV_MASK|SYSCON_RCC_USESYSDIV|\ - SYSCON_RCC_IOSCDIS|SYSCON_RCC_MOSCDIS) -#endif -#define RCC2_DIVMASK (SYSCON_RCC2_SYSDIV2_MASK) -#define FAST_OSCDELAY (512*1024) -#define SLOW_OSCDELAY (4*1024) -#define PLLLOCK_DELAY (32*1024) +#define FAST_OSCDELAY (512*1024) +#define SLOW_OSCDELAY (4*1024) +#define PLLLOCK_DELAY (32*1024) /**************************************************************************** * Private Data @@ -253,16 +256,25 @@ void lm_clockconfig(uint32_t newrcc, uint32_t newrcc2) putreg32(SYSCON_MISC_PLLLMIS, LM_SYSCON_MISC); - /* Write the new RCC/RCC2 values. Order depends upon whether RCC2 or RCC - * is currently enabled. + /* Write the new RCC/RCC2 values. + * + * Original LM3S Logic: Order depends upon whether RCC2 or RCC is + * currently enabled. + * + * LM4F120 Data Sheet: "Write the RCC register prior to writing the + * RCC2 register. If a subsequent write to the RCC register is required, + * include another register access after writing the RCC register and + * before writing the RCC2 register. */ - if (rcc2 & SYSCON_RCC2_USERCC2) +#ifndef LM4F + if ((rcc2 & SYSCON_RCC2_USERCC2) != 0) { putreg32(rcc2, LM_SYSCON_RCC2); putreg32(rcc, LM_SYSCON_RCC); } - else + else +#endif { putreg32(rcc, LM_SYSCON_RCC); putreg32(rcc2, LM_SYSCON_RCC2); @@ -294,9 +306,18 @@ void lm_clockconfig(uint32_t newrcc, uint32_t newrcc2) rcc2 &= ~SYSCON_RCC2_BYPASS2; } - /* Now we can set the final RCC/RCC2 values */ + /* Now we can set the final RCC/RCC2 values: + * + * LM4F120 Data Sheet: "Write the RCC register prior to writing the + * RCC2 register. If a subsequent write to the RCC register is required, + * include another register access after writing the RCC register and + * before writing the RCC2 register. + */ putreg32(rcc, LM_SYSCON_RCC); +#ifdef LM4F + rcc = getreg32(LM_SYSCON_RCC); +#endif putreg32(rcc2, LM_SYSCON_RCC2); /* Wait for the system divider to be effective */ diff --git a/configs/lm4f120-launchpad/include/board.h b/configs/lm4f120-launchpad/include/board.h index 2a88506a61d0437fc7d37fd6312ab7cfec790b0e..0bdc3fc89da92ef7b454f2cca619d0ee476dc198 100644 --- a/configs/lm4f120-launchpad/include/board.h +++ b/configs/lm4f120-launchpad/include/board.h @@ -77,16 +77,36 @@ * - No auto-clock gating reset */ -#define LM_RCC_VALUE (SYSCON_RCC_OSCSRC | SYSCON_RCC_XTAL | SYSCON_RCC_USESYSDIV | SYSCON_RCC_SYSDIV(LM_SYSDIV)) +#define LM_RCC_VALUE (SYSCON_RCC_OSCSRC | SYSCON_RCC_XTAL | \ + SYSCON_RCC_USESYSDIV | SYSCON_RCC_SYSDIV(LM_SYSDIV)) -/* RCC2 settings -- RCC2 not used. Other RCC2 settings +/* RCC2 settings * * - PLL and sys dividers not bypassed. * - PLL not powered down * - Not using RCC2 + * + * When SYSCON_RCC2_DIV400 is not selected, SYSDIV2 is the divisor-1. + * When SYSCON_RCC2_DIV400 is selected, SYSDIV2 is the divisor-1)/2, plus + * the LSB: + * + * SYSDIV2 SYSDIV2LSB DIVISOR + * 0 N/A 2 + * 1 0 3 + * " 1 4 + * 2 0 5 + * " 1 6 + * etc. */ -#define LM_RCC2_VALUE (SYSCON_RCC2_OSCSRC | SYSCON_RCC2_SYSDIV(LM_SYSDIV) | SYSCON_RCC2_DIV400) +#if (LM_SYSDIV & 1) == 0 +# define LM_RCC2_VALUE (SYSCON_RCC2_OSCSRC | SYSCON_RCC2_SYSDIV2LSB | \ + SYSCON_RCC2_SYSDIV_DIV400(LM_SYSDIV) | \ + SYSCON_RCC2_DIV400 | SYSCON_RCC2_USERCC2) +#else +# define LM_RCC2_VALUE (SYSCON_RCC2_OSCSRC | SYSCON_RCC2_SYSDIV_DIV400(LM_SYSDIV) | \ + SYSCON_RCC2_DIV400 | SYSCON_RCC2_USERCC2) +#endif /* LED definitions ******************************************************************/ /* The LM4F120 LaunchPad has a single RGB LED. There is only one visible LED which