diff options
Diffstat (limited to 'nuttx/arch/arm/src/lpc17xx')
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/chip/lpc178x_syscon.h | 42 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/chip/lpc17_memorymap.h | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconfig.h | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconn.h | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/chip/lpc17_syscon.h | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/lpc176x_clockconfig.c | 221 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/lpc178x_clockconfig.c | 233 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/lpc17_clockconfig.c | 185 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc17xx/lpc17_serial.c | 2 |
9 files changed, 514 insertions, 185 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc178x_syscon.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc178x_syscon.h index f52fca35c..80c5386af 100644 --- a/nuttx/arch/arm/src/lpc17xx/chip/lpc178x_syscon.h +++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc178x_syscon.h @@ -78,9 +78,9 @@ /* Clocking and power control -- Clock dividers */ -#define LPC17_SYSCON_EMCCLKCFG_OFFSET 0x0100 /* EMC Clock Configuration Register */ -#define LPC17_SYSCON_CCLKCFG_OFFSET 0x0104 /* CPU Clock Configuration Register */ -#define LPC17_SYSCON_USBCLKCFG_OFFSET 0x0108 /* USB Clock Configuration Register */ +#define LPC17_SYSCON_EMCCLKSEL_OFFSET 0x0100 /* EMC Clock Selection Register */ +#define LPC17_SYSCON_CCLKSEL_OFFSET 0x0104 /* CPU Clock Selection Register */ +#define LPC17_SYSCON_USBCLKSEL_OFFSET 0x0108 /* USB Clock Selection Register */ /* 0x400f c110 - 0x400f c114: CAN Wake and Sleep Registers */ @@ -160,9 +160,9 @@ /* Clocking and power control -- Clock dividers */ -#define LPC17_SYSCON_EMCCLKCFG (LPC17_SYSCON_BASE+LPC17_SYSCON_EMCCLKCFG_OFFSET) -#define LPC17_SYSCON_CCLKCFG (LPC17_SYSCON_BASE+LPC17_SYSCON_CCLKCFG_OFFSET) -#define LPC17_SYSCON_USBCLKCFG (LPC17_SYSCON_BASE+LPC17_SYSCON_USBCLKCFG_OFFSET) +#define LPC17_SYSCON_EMCCLKSEL (LPC17_SYSCON_BASE+LPC17_SYSCON_EMCCLKSEL_OFFSET) +#define LPC17_SYSCON_CCLKSEL (LPC17_SYSCON_BASE+LPC17_SYSCON_CCLKSEL_OFFSET) +#define LPC17_SYSCON_USBCLKSEL (LPC17_SYSCON_BASE+LPC17_SYSCON_USBCLKSEL_OFFSET) /* 0x400f c110 - 0x400f c114: CAN Wake and Sleep Registers */ @@ -277,28 +277,28 @@ /* 0: EMC uses same clock as CPU */ /* 1: EMC uses half the rate of CPU */ /* Bits 1-31: Reserved */ -/* CPU Clock Configuration register */ +/* CPU Clock Selection register */ -#define SYSCON_CCLKCFG_CCLKDIV_SHIFT (0) /* 0-4: Divide value for CPU clock (CCLK) */ -#define SYSCON_CCLKCFG_CCLKDIV_MASK (0x1f << SYSCON_CCLKCFG_CCLKDIV_SHIFT) -# define SYSCON_CCLKCFG_CCLKDIV(n) ((n-1) << SYSCON_CCLKCFG_CCLKDIV_SHIFT) /* n = 2 - 31 */ +#define SYSCON_CCLKSEL_CCLKDIV_SHIFT (0) /* 0-4: Divide value for CPU clock (CCLK) */ +#define SYSCON_CCLKSEL_CCLKDIV_MASK (0x1f << SYSCON_CCLKSEL_CCLKDIV_SHIFT) +# define SYSCON_CCLKSEL_CCLKDIV(n) ((n-1) << SYSCON_CCLKSEL_CCLKDIV_SHIFT) /* n = 2 - 31 */ /* Bits 5-7: Reserved */ -#define SYSCON_CCLKCFG_CCLKSEL (1 << 8) /* Bit 8: Select input clock to CPU clock divider */ +#define SYSCON_CCLKSEL_CCLKSEL (1 << 8) /* Bit 8: Select input clock to CPU clock divider */ /* 0: Sysclk used as input to CCLKDIV */ /* 1: Main PLL used as input to CCLKDIV */ /* Bits 9-31: Reserved */ -/* USB Clock Configuration register */ +/* USB Clock Selection register */ -#define SYSCON_USBCLKCFG_USBDIV_SHIFT (0) /* Bits 0-4: PLL0/1 divide value USB clock */ -#define SYSCON_USBCLKCFG_USBDIV_MASK (0x1f << SYSCON_USBCLKCFG_USBDIV_SHIFT) -# define SYSCON_USBCLKCFG_USBDIV_DIV1 (1 << SYSCON_USBCLKCFG_USBDIV_SHIFT) /* PLL0/1 output must be 48MHz */ -# define SYSCON_USBCLKCFG_USBDIV_DIV2 (2 << SYSCON_USBCLKCFG_USBDIV_SHIFT) /* PLL0/1 output must be 96MHz */ -# define SYSCON_USBCLKCFG_USBDIV_DIV3 (3 << SYSCON_USBCLKCFG_USBDIV_SHIFT) /* PLL0/1 output must be 144MHz */ +#define SYSCON_USBCLKSEL_USBDIV_SHIFT (0) /* Bits 0-4: PLL0/1 divide value USB clock */ +#define SYSCON_USBCLKSEL_USBDIV_MASK (0x1f << SYSCON_USBCLKSEL_USBDIV_SHIFT) +# define SYSCON_USBCLKSEL_USBDIV_DIV1 (1 << SYSCON_USBCLKSEL_USBDIV_SHIFT) /* PLL0/1 output must be 48MHz */ +# define SYSCON_USBCLKSEL_USBDIV_DIV2 (2 << SYSCON_USBCLKSEL_USBDIV_SHIFT) /* PLL0/1 output must be 96MHz */ +# define SYSCON_USBCLKSEL_USBDIV_DIV3 (3 << SYSCON_USBCLKSEL_USBDIV_SHIFT) /* PLL0/1 output must be 144MHz */ /* Bits 5-7: Reserved */ -#define SYSCON_USBCLKCFG_USBSEL_SHIFT (8) /* Bits 8-9: Input clock to USBDIV */ -#define SYSCON_USBCLKCFG_USBSEL_MASK (3 << SYSCON_USBCLKCFG_USBSEL_SHIFT) -#define SYSCON_USBCLKCFG_USBSEL_PLL0 (1 << SYSCON_USBCLKCFG_USBSEL_SHIFT) /* 01: PLL0 is used as input clock to USBDIV */ -#define SYSCON_USBCLKCFG_USBSEL_PLL1 (2 << SYSCON_USBCLKCFG_USBSEL_SHIFT) /* 10: PLL1 is used as input clock to USBDIV */ +#define SYSCON_USBCLKSEL_USBSEL_SHIFT (8) /* Bits 8-9: Input clock to USBDIV */ +#define SYSCON_USBCLKSEL_USBSEL_MASK (3 << SYSCON_USBCLKSEL_USBSEL_SHIFT) +#define SYSCON_USBCLKSEL_USBSEL_PLL0 (1 << SYSCON_USBCLKSEL_USBSEL_SHIFT) /* 01: PLL0 is used as input clock to USBDIV */ +#define SYSCON_USBCLKSEL_USBSEL_PLL1 (2 << SYSCON_USBCLKSEL_USBSEL_SHIFT) /* 10: PLL1 is used as input clock to USBDIV */ /* 11: unused */ /* Bits 10-31: Reserved */ /* CAN0/1 Sleep Clear Register */ diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_memorymap.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_memorymap.h index ef720ae59..c51fe8e74 100644 --- a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_memorymap.h +++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_memorymap.h @@ -42,6 +42,10 @@ #include <nuttx/config.h> +/* This file is only a thin shell that includes the correct memory map definitions + * for the selected LPC17xx family. + */ + #include <arch/lpc17xx/chip.h> #if defined(LPC176x) diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconfig.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconfig.h index e90b425a9..c98c90e6b 100644 --- a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconfig.h +++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconfig.h @@ -42,6 +42,10 @@ #include <nuttx/config.h> +/* This file is only a thin shell that includes the correct pin configuration + * definitions for the selected LPC17xx family. + */ + #include <arch/lpc17xx/chip.h> #if defined(LPC176x) diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconn.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconn.h index 1ca4d163f..8b6829f9b 100644 --- a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconn.h +++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_pinconn.h @@ -42,6 +42,10 @@ #include <nuttx/config.h> +/* This file is only a thin shell that includes the correct pin configuration + * register definitions for the selected LPC17xx family. + */ + #include <arch/lpc17xx/chip.h> #if defined(LPC176x) diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_syscon.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_syscon.h index ebe39cb72..ebab3a1be 100644 --- a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_syscon.h +++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_syscon.h @@ -42,6 +42,10 @@ #include <nuttx/config.h> +/* This file is only a thin shell that includes the correct system controller + * register definitions for the selected LPC17xx family. + */ + #include <arch/lpc17xx/chip.h> #if defined(LPC176x) diff --git a/nuttx/arch/arm/src/lpc17xx/lpc176x_clockconfig.c b/nuttx/arch/arm/src/lpc17xx/lpc176x_clockconfig.c new file mode 100644 index 000000000..4befd3759 --- /dev/null +++ b/nuttx/arch/arm/src/lpc17xx/lpc176x_clockconfig.c @@ -0,0 +1,221 @@ +/**************************************************************************** + * arch/arm/src/lpc17xx/lpc17_clockconfig.c + * arch/arm/src/chip/lpc17_clockconfig.c + * + * Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <arch/board/board.h> + +#include "up_arch.h" +#include "up_internal.h" +#include "lpc17_clockconfig.h" +#include "chip/lpc17_syscon.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef LPC176x +# error "The logic in this file applies only to the LPC176x family" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: lpc17_clockconfig + * + * Description: + * Called to initialize the LPC176x. This does whatever setup is needed to put the + * SoC in a usable state. This includes the initialization of clocking using the + * settings in board.h. + * + * The LPC176x and LPC178x system control block is *nearly* identical but we have + * found that the LPC178x is more sensitive to the ordering of certain operations. + * So, although the hardware seems very similar, the safer thing to do is to + * separate the LPC176x and LPC178x into separate files. + * + ************************************************************************************/ + +void lpc17_clockconfig(void) +{ + /* Enable the main oscillator (or not) and the frequency range of the main oscillator */ + + putreg32(BOARD_SCS_VALUE, LPC17_SYSCON_SCS); + + /* Wait for the main oscillator to be ready. */ + +#ifdef CONFIG_LPC17_MAINOSC + while ((getreg32(LPC17_SYSCON_SCS) & SYSCON_SCS_OSCSTAT) == 0); +#endif + + /* Setup up the divider value for the CPU clock. The output of the divider is CCLK. + * The input to the divider (PLLCLK) is equal to SYSCLK unless PLL0 is enabled. CCLK + * will be further divided to produce peripheral clocks, but that peripheral clock + * setup is performed in the peripheral device drivers. Here only CCLK is + * configured. + */ + + putreg32(BOARD_CCLKCFG_VALUE, LPC17_SYSCON_CCLKCFG); + + /* PLL0 is used to generate the CPU clock divider input (PLLCLK). */ + +#ifdef CONFIG_LPC17_PLL0 + /* Select the PLL0 source clock, multiplier, and pre-divider values. NOTE that + * a special "feed" sequence must be written to the PLL0FEED register in order + * for changes to the PLL0CFG register to take effect. + */ + + putreg32(BOARD_CLKSRCSEL_VALUE, LPC17_SYSCON_CLKSRCSEL); + putreg32(BOARD_PLL0CFG_VALUE, LPC17_SYSCON_PLL0CFG); + putreg32(0xaa, LPC17_SYSCON_PLL0FEED); + putreg32(0x55, LPC17_SYSCON_PLL0FEED); + + /* Enable the PLL. NOTE that a special "feed" sequence must be written to the + * PLL0FEED register in order for changes to the PLL0CON register to take effect. + */ + + putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL0CON); + putreg32(0xaa, LPC17_SYSCON_PLL0FEED); + putreg32(0x55, LPC17_SYSCON_PLL0FEED); + + /* Wait for PLL0 to lock */ + + while ((getreg32(LPC17_SYSCON_PLL0STAT) & SYSCON_PLL0STAT_PLOCK) == 0); + + /* Enable and connect PLL0 */ + + putreg32(SYSCON_PLLCON_PLLE|SYSCON_PLLCON_PLLC, LPC17_SYSCON_PLL0CON); + putreg32(0xaa, LPC17_SYSCON_PLL0FEED); + putreg32(0x55, LPC17_SYSCON_PLL0FEED); + + /* Wait for PLL to report that it is connected and enabled */ + + while ((getreg32(LPC17_SYSCON_PLL0STAT) & (SYSCON_PLL0STAT_PLLE|SYSCON_PLL0STAT_PLLC)) + != (SYSCON_PLL0STAT_PLLE|SYSCON_PLL0STAT_PLLC)); + +#endif /* CONFIG_LPC17_PLL0 */ + + /* PLL1 receives its clock input from the main oscillator only and can be used to + * provide a fixed 48 MHz clock only to the USB subsystem (if that clock cannot be + * obtained from PLL0). + */ + +#ifdef CONFIG_LPC17_PLL1 + /* Select the PLL1 multiplier, and pre-divider values. NOTE that a special "feed" + * sequence must be written to the PLL1FEED register in order for changes to the + * PLL1CFG register to take effect. + */ + + putreg32(BOARD_PLL1CFG_VALUE, LPC17_SYSCON_PLL1CFG); + putreg32(0xaa, LPC17_SYSCON_PLL1FEED); + putreg32(0x55, LPC17_SYSCON_PLL1FEED); + + /* Enable the PLL. NOTE that a special "feed" sequence must be written to the + * PLL1FEED register in order for changes to the PLL1CON register to take effect. + */ + + putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL1CON); + putreg32(0xaa, LPC17_SYSCON_PLL1FEED); + putreg32(0x55, LPC17_SYSCON_PLL1FEED); + + /* Wait for PLL1 to lock */ + + while ((getreg32(LPC17_SYSCON_PLL1STAT) & SYSCON_PLL1STAT_PLOCK) == 0); + + /* Enable and connect PLL1 */ + + putreg32(SYSCON_PLLCON_PLLE|SYSCON_PLLCON_PLLC, LPC17_SYSCON_PLL1CON); + putreg32(0xaa, LPC17_SYSCON_PLL1FEED); + putreg32(0x55, LPC17_SYSCON_PLL1FEED); + + /* Wait for PLL to report that it is connected and enabled */ + + while ((getreg32(LPC17_SYSCON_PLL1STAT) & (SYSCON_PLL1STAT_PLLE|SYSCON_PLL1STAT_PLLC)) + != (SYSCON_PLL1STAT_PLLE|SYSCON_PLL1STAT_PLLC)); + +#else /* CONFIG_LPC17_PLL1 */ + + /* Otherwise, setup up the USB clock divider to generate the USB clock from PLL0 */ + + putreg32(BOARD_USBCLKCFG_VALUE, LPC17_SYSCON_USBCLKCFG); + +#endif /* CONFIG_LPC17_PLL1 */ + + /* Disable all peripheral clocks. They must be configured by each device driver + * when the device driver is initialized. + */ + + putreg32(0, LPC17_SYSCON_PCLKSEL0); + putreg32(0, LPC17_SYSCON_PCLKSEL1); + + /* Disable power to all peripherals (execpt GPIO). Peripherals must be re-powered + * one at a time by each device driver when the driver is initialized. + */ + + putreg32(SYSCON_PCONP_PCGPIO, LPC17_SYSCON_PCONP); + + /* Disable CLKOUT */ + + putreg32(0, LPC17_SYSCON_CLKOUTCFG); + + /* Configure FLASH */ + +#ifdef CONFIG_LPC17_FLASH + putreg32(BOARD_FLASHCFG_VALUE, LPC17_SYSCON_FLASHCFG); +#endif +} + diff --git a/nuttx/arch/arm/src/lpc17xx/lpc178x_clockconfig.c b/nuttx/arch/arm/src/lpc17xx/lpc178x_clockconfig.c new file mode 100644 index 000000000..948c17d7f --- /dev/null +++ b/nuttx/arch/arm/src/lpc17xx/lpc178x_clockconfig.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * arch/arm/src/lpc17xx/lpc17_clockconfig.c + * arch/arm/src/chip/lpc17_clockconfig.c + * + * Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <arch/board/board.h> + +#include "up_arch.h" +#include "up_internal.h" +#include "lpc17_clockconfig.h" +#include "chip/lpc17_syscon.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef LPC178x +# error "The logic in this file applies only to the LPC178x family" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************************ + * Name: lpc17_clockconfig + * + * Description: + * Called to initialize the LPC17xx. This does whatever setup is needed to put the + * SoC in a usable state. This includes the initialization of clocking using the + * settings in board.h. + * + * The LPC176x and LPC178x system control block is *nearly* identical but we have + * found that the LPC178x is more sensitive to the ordering of certain operations. + * So, although the hardware seems very similar, the safer thing to do is to + * separate the LPC176x and LPC178x into separate files. + * + ************************************************************************************/ + +void lpc17_clockconfig(void) +{ + /* TODO: + * + * (1) "Make sure that the PLL output is not already being used. The CCLKSEL, + * USBCLKSEL, and SPIFICLKSEL registers must not select the PLL being set up. + * Clock dividers included in these registers may also be set up at this time + * if writing to any of the noted registers." + * + * (2) "If the main PLL is being set up, and the main clock source is being changed + * (IRC versus main oscillator), change this first by writing the correct + * value to the CLKSRCSEL register." + * + * This is not an issue now because we only setup the clocks on power up, so the + * PLL cannot be the select source. However, this could be an issue at some point + * later when, for example, we may want to implement reduced power mode with other + * clocking. + */ + + /* Enable the main oscillator (or not) and the frequency range of the main oscillator */ + + putreg32(BOARD_SCS_VALUE, LPC17_SYSCON_SCS); + + /* Wait for the main oscillator to be ready. */ + +#ifdef CONFIG_LPC17_MAINOSC + while ((getreg32(LPC17_SYSCON_SCS) & SYSCON_SCS_OSCSTAT) == 0); +#endif + + /* PLL0 is used to generate the CPU clock divider input (PLLCLK). */ + +#ifdef CONFIG_LPC17_PLL0 + /* (3) "Write PLL new setup values to the PLLCFG register. Write a 1 to the + * PLLE bit in the PLLCON register. Perform a PLL feed sequence by writing + * first the value 0xAA, then the value 0x55 to the PLLFEED register" + * + * Select the PLL0 source clock, multiplier, and pre-divider values. NOTE that + * a special "feed" sequence must be written to the PLL0FEED register in order + * for changes to the PLL0CFG register to take effect. + */ + + putreg32(BOARD_CLKSRCSEL_VALUE, LPC17_SYSCON_CLKSRCSEL); + putreg32(BOARD_PLL0CFG_VALUE, LPC17_SYSCON_PLL0CFG); + putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL0CON); + + /* Enable the PLL. NOTE that a special "feed" sequence must be written to the + * PLL0FEED register in order for changes to the PLL0CON register to take effect. + */ + + putreg32(0xaa, LPC17_SYSCON_PLL0FEED); + putreg32(0x55, LPC17_SYSCON_PLL0FEED); + + /* (4) "Set up the necessary clock dividers. These may include the CCLKSEL, + * PCLKSEL, EMCCLKSEL, USBCLKSEL, and the SPIFICLKSEL registers. + */ + + putreg32(BOARD_CCLKSEL_VALUE, LPC17_SYSCON_CCLKSEL); + putreg32(BOARD_PCLKDIV, LPC17_SYSCON_PCLKSEL); + +#ifdef CONFIG_LPC17_EMC + putreg32(BOARD_EMCCLKSEL_VALUE, LPC17_SYSCON_EMCCLKSEL); +#endif +#if defined(CONFIG_LPC17_USBDEV) || defined(CONFIG_LPC17_USBHOST) + putreg32(BOARD_USBCLKSEL_VALUE, LPC17_SYSCON_USBCLKSEL); +#endif +#ifdef CONFIG_LPC17_SPIFI + putreg32(BOARD_SPIFICLKSEL_VALUE, LPC17_SPIFICLKSEL_CCLKSEL); +#endif + + /* (5) "Wait for the PLL to lock. This may be accomplished by polling the + * PLLSTAT register and testing for PLOCK = 1, or by using the PLL lock + * interrupt.Wait for PLL0 to lock. + */ + + while ((getreg32(LPC17_SYSCON_PLL0STAT) & SYSCON_PLL0STAT_PLOCK) == 0); + + /* (6) "Connect the PLL by selecting its output in the appropriate places. This + * may include the CCLKSEL, USBCLKSEL, and SPIFICLKSEL registers. + */ + +#endif /* CONFIG_LPC17_PLL0 */ + + /* PLL1 receives its clock input from the main oscillator only and can be used to + * provide a fixed 48 MHz clock only to the USB subsystem (if that clock cannot be + * obtained from PLL0). + */ + +#ifdef CONFIG_LPC17_PLL1 + /* (3) "Write PLL new setup values to the PLLCFG register. Write a 1 to the + * PLLE bit in the PLLCON register. Perform a PLL feed sequence by writing + * first the value 0xAA, then the value 0x55 to the PLLFEED register" + * + * Select the PLL1 multiplier, and pre-divider values. NOTE that a special "feed" + * sequence must be written to the PLL1FEED register in order for changes to the + * PLL1CFG register to take effect. + */ + + putreg32(BOARD_PLL1CFG_VALUE, LPC17_SYSCON_PLL1CFG); + putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL1CON); + + /* Enable the PLL. NOTE that a special "feed" sequence must be written to the + * PLL1FEED register in order for changes to the PLL1CON register to take effect. + */ + + putreg32(0xaa, LPC17_SYSCON_PLL1FEED); + putreg32(0x55, LPC17_SYSCON_PLL1FEED); + + /* (4) "Set up the necessary clock dividers. These may include the CCLKSEL, + * PCLKSEL, EMCCLKSEL, USBCLKSEL, and the SPIFICLKSEL registers. + */ + + /* (5) "Wait for the PLL to lock. This may be accomplished by polling the + * PLLSTAT register and testing for PLOCK = 1, or by using the PLL lock + * interrupt.Wait for PLL0 to lock. + */ + + while ((getreg32(LPC17_SYSCON_PLL1STAT) & SYSCON_PLL1STAT_PLOCK) == 0); + + /* (6) "Connect the PLL by selecting its output in the appropriate places. This + * may include the CCLKSEL, USBCLKSEL, and SPIFICLKSEL registers. + */ + +#endif /* CONFIG_LPC17_PLL1 */ + + /* Disable power to all peripherals (execpt GPIO). Peripherals must be re-powered + * one at a time by each device driver when the driver is initialized. + */ + + putreg32(SYSCON_PCONP_PCGPIO, LPC17_SYSCON_PCONP); + + /* Disable CLKOUT */ + + putreg32(0, LPC17_SYSCON_CLKOUTCFG); + + /* Configure FLASH */ + +#ifdef CONFIG_LPC17_FLASH + putreg32(BOARD_FLASHCFG_VALUE, LPC17_SYSCON_FLASHCFG); +#endif +} + diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_clockconfig.c b/nuttx/arch/arm/src/lpc17xx/lpc17_clockconfig.c index 9dc033d2d..97ef496f0 100644 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_clockconfig.c +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_clockconfig.c @@ -40,16 +40,28 @@ #include <nuttx/config.h> -#include <stdint.h> -#include <debug.h> - -#include <nuttx/arch.h> -#include <arch/board/board.h> - -#include "up_arch.h" -#include "up_internal.h" -#include "lpc17_clockconfig.h" -#include "chip/lpc17_syscon.h" +/* This file is only a thin shell that includes the correct clock + * configuration logic for the selected LPC17xx family. The correct file + * cannot be selected by the make system because it needs the intelligence + * that only exists in chip.h that can associate an LPC17xx part number with + * an LPC17xx family. + * + * The LPC176x and LPC178x system control block is *nearly* identical but + * we have found that the LPC178x is more sensitive to the ordering of + * certain operations. So, although the hardware seems very similar, the + * safer thing to do is to separate the LPC176x and LPC178x into separate + * files. + */ + +#include <arch/lpc17xx/chip.h> + +#if defined(LPC176x) +# include "chip/lpc176x_clockconfig.c" +#elif defined(LPC178x) +# include "chip/lpc178x_clockconfig.c" +#else +# error "Unrecognized LPC17xx family" +#endif /**************************************************************************** * Pre-processor Definitions @@ -70,156 +82,3 @@ /**************************************************************************** * Public Functions ****************************************************************************/ - -/************************************************************************************ - * Name: lpc17_clockconfig - * - * Description: - * Called to initialize the LPC17xx. This does whatever setup is needed to put the - * SoC in a usable state. This includes the initialization of clocking using the - * settings in board.h. - * - ************************************************************************************/ - -void lpc17_clockconfig(void) -{ - /* Enable the main oscillator (or not) and the frequency range of the main oscillator */ - - putreg32(BOARD_SCS_VALUE, LPC17_SYSCON_SCS); - - /* Wait for the main oscillator to be ready. */ - -#ifdef CONFIG_LPC17_MAINOSC - while ((getreg32(LPC17_SYSCON_SCS) & SYSCON_SCS_OSCSTAT) == 0); -#endif - - /* Setup up the divider value for the CPU clock. The output of the divider is CCLK. - * The input to the divider (PLLCLK) is equal to SYSCLK unless PLL0 is enabled. CCLK - * will be further divided to produce peripheral clocks, but that peripheral clock - * setup is performed in the peripheral device drivers. Here only CCLK is - * configured. - */ - - putreg32(BOARD_CCLKCFG_VALUE, LPC17_SYSCON_CCLKCFG); - - /* PLL0 is used to generate the CPU clock divider input (PLLCLK). */ - -#ifdef CONFIG_LPC17_PLL0 - /* Select the PLL0 source clock, multiplier, and pre-divider values. NOTE that - * a special "feed" sequence must be written to the PLL0FEED register in order - * for changes to the PLL0CFG register to take effect. - */ - - putreg32(BOARD_CLKSRCSEL_VALUE, LPC17_SYSCON_CLKSRCSEL); - putreg32(BOARD_PLL0CFG_VALUE, LPC17_SYSCON_PLL0CFG); - putreg32(0xaa, LPC17_SYSCON_PLL0FEED); - putreg32(0x55, LPC17_SYSCON_PLL0FEED); - - /* Enable the PLL. NOTE that a special "feed" sequence must be written to the - * PLL0FEED register in order for changes to the PLL0CON register to take effect. - */ - - putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL0CON); - putreg32(0xaa, LPC17_SYSCON_PLL0FEED); - putreg32(0x55, LPC17_SYSCON_PLL0FEED); - - /* Wait for PLL0 to lock */ - - while ((getreg32(LPC17_SYSCON_PLL0STAT) & SYSCON_PLL0STAT_PLOCK) == 0); - -# if defined(LPC176x) - /* Enable and connect PLL0 */ - - putreg32(SYSCON_PLLCON_PLLE|SYSCON_PLLCON_PLLC, LPC17_SYSCON_PLL0CON); - putreg32(0xaa, LPC17_SYSCON_PLL0FEED); - putreg32(0x55, LPC17_SYSCON_PLL0FEED); - - /* Wait for PLL to report that it is connected and enabled */ - - while ((getreg32(LPC17_SYSCON_PLL0STAT) & (SYSCON_PLL0STAT_PLLE|SYSCON_PLL0STAT_PLLC)) - != (SYSCON_PLL0STAT_PLLE|SYSCON_PLL0STAT_PLLC)); - -# endif /* LPC176x */ -#endif /* CONFIG_LPC17_PLL0 */ - - /* PLL1 receives its clock input from the main oscillator only and can be used to - * provide a fixed 48 MHz clock only to the USB subsystem (if that clock cannot be - * obtained from PLL0). - */ - -#ifdef CONFIG_LPC17_PLL1 - /* Select the PLL1 multiplier, and pre-divider values. NOTE that a special "feed" - * sequence must be written to the PLL1FEED register in order for changes to the - * PLL1CFG register to take effect. - */ - - putreg32(BOARD_PLL1CFG_VALUE, LPC17_SYSCON_PLL1CFG); - putreg32(0xaa, LPC17_SYSCON_PLL1FEED); - putreg32(0x55, LPC17_SYSCON_PLL1FEED); - - /* Enable the PLL. NOTE that a special "feed" sequence must be written to the - * PLL1FEED register in order for changes to the PLL1CON register to take effect. - */ - - putreg32(SYSCON_PLLCON_PLLE, LPC17_SYSCON_PLL1CON); - putreg32(0xaa, LPC17_SYSCON_PLL1FEED); - putreg32(0x55, LPC17_SYSCON_PLL1FEED); - - /* Wait for PLL1 to lock */ - - while ((getreg32(LPC17_SYSCON_PLL1STAT) & SYSCON_PLL1STAT_PLOCK) == 0); - -# if defined(LPC176x) - /* Enable and connect PLL1 */ - - putreg32(SYSCON_PLLCON_PLLE|SYSCON_PLLCON_PLLC, LPC17_SYSCON_PLL1CON); - putreg32(0xaa, LPC17_SYSCON_PLL1FEED); - putreg32(0x55, LPC17_SYSCON_PLL1FEED); - - /* Wait for PLL to report that it is connected and enabled */ - - while ((getreg32(LPC17_SYSCON_PLL1STAT) & (SYSCON_PLL1STAT_PLLE|SYSCON_PLL1STAT_PLLC)) - != (SYSCON_PLL1STAT_PLLE|SYSCON_PLL1STAT_PLLC)); - -# endif -#else /* CONFIG_LPC17_PLL1 */ - - /* Otherwise, setup up the USB clock divider to generate the USB clock from PLL0 */ - -#ifdef LPC176x - putreg32(BOARD_USBCLKCFG_VALUE, LPC17_SYSCON_USBCLKCFG); -#endif -#endif /* CONFIG_LPC17_PLL1 */ - - /* Disable all peripheral clocks. They must be configured by each device driver - * when the device driver is initialized. - */ - -#ifdef LPC176x - putreg32(0, LPC17_SYSCON_PCLKSEL0); - putreg32(0, LPC17_SYSCON_PCLKSEL1); -#endif - - /* Set the peripheral clock (PCLK) divider that is used by all APB peripherals. */ - -#ifdef LPC178x - putreg32(BOARD_PCLKDIV, LPC17_SYSCON_PCLKSEL); -#endif - - /* Disable power to all peripherals (execpt GPIO). Peripherals must be re-powered - * one at a time by each device driver when the driver is initialized. - */ - - putreg32(SYSCON_PCONP_PCGPIO, LPC17_SYSCON_PCONP); - - /* Disable CLKOUT */ - - putreg32(0, LPC17_SYSCON_CLKOUTCFG); - - /* Configure FLASH */ - -#ifdef CONFIG_LPC17_FLASH - putreg32(BOARD_FLASHCFG_VALUE, LPC17_SYSCON_FLASHCFG); -#endif -} - diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c b/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c index 0159d7c75..713426b6e 100644 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c @@ -855,7 +855,7 @@ static inline uint32_t lpc17_uartdl(uint32_t baud, uint8_t divcode) #else static inline uint32_t lpc17_uartdl(uint32_t baud) { - return (uint32_t)BOARD_PCLK / (baud << 4); + return (uint32_t)BOARD_PCLK_FREQUENCY / (baud << 4); } #endif |