summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/str71x
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-31 18:35:06 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-31 18:35:06 +0000
commita843c2be5cd076663201fd86109d031c4f425645 (patch)
tree655d384bf0e061b5cbf08711e7d2def019143f5c /nuttx/arch/arm/src/str71x
parent7badb15542ccc6e5426af8f5ae9a4c9c7469fec9 (diff)
downloadpx4-nuttx-a843c2be5cd076663201fd86109d031c4f425645.tar.gz
px4-nuttx-a843c2be5cd076663201fd86109d031c4f425645.tar.bz2
px4-nuttx-a843c2be5cd076663201fd86109d031c4f425645.zip
Add logic to initialize clocks
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1108 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/str71x')
-rw-r--r--nuttx/arch/arm/src/str71x/Make.defs2
-rw-r--r--nuttx/arch/arm/src/str71x/str71x_head.S85
-rw-r--r--nuttx/arch/arm/src/str71x/str71x_pcu.h23
-rw-r--r--nuttx/arch/arm/src/str71x/str71x_prccu.c342
4 files changed, 400 insertions, 52 deletions
diff --git a/nuttx/arch/arm/src/str71x/Make.defs b/nuttx/arch/arm/src/str71x/Make.defs
index 0b5fd99dd..a59ea4a2c 100644
--- a/nuttx/arch/arm/src/str71x/Make.defs
+++ b/nuttx/arch/arm/src/str71x/Make.defs
@@ -48,7 +48,7 @@ CMN_CSRCS += up_schedulesigaction.c up_sigdeliver.c
endif
CHIP_ASRCS = str71x_lowputc.S
-CHIP_CSRCS = str71x_decodeirq.c str71x_irq.c str71x_timerisr.c \
+CHIP_CSRCS = str71x_prccu.c str71x_decodeirq.c str71x_irq.c str71x_timerisr.c \
str71x_serial.c
ifeq ($(CONFIG_USBDEV),y)
diff --git a/nuttx/arch/arm/src/str71x/str71x_head.S b/nuttx/arch/arm/src/str71x/str71x_head.S
index 6f2b2892e..715b00446 100644
--- a/nuttx/arch/arm/src/str71x/str71x_head.S
+++ b/nuttx/arch/arm/src/str71x/str71x_head.S
@@ -82,6 +82,23 @@
#endif
/*****************************************************************************
+ * External references
+ *****************************************************************************/
+
+ .globl str71x_prccuinit /* Clock initialization */
+ .globl up_lowsetup /* Early initialization of UART */
+#ifdef CONFIG_USE_EARLYSERIALINIT
+ .globl up_earlyserialinit /* Early initialization of serial driver */
+#endif
+#ifdef CONFIG_ARCH_LEDS
+ .globl up_ledinit /* Boot LED setup */
+#endif
+#ifdef CONFIG_DEBUG
+ .globl up_lowputc /* Low-level debug output */
+#endif
+ .globl os_start /* NuttX entry point */
+
+/*****************************************************************************
* Macros
*****************************************************************************/
@@ -368,47 +385,10 @@ eicloop:
ldr \value, =STR71X_APB1_APB1ALL
strh \value, [\base1, #STR71X_APB_CKDIS_OFFSET]
- /* Disable all(or most) APB1 peripherals */
-#if 1 /* See below */
+ /* Disable all(or most) APB2 peripherals */
ldr \value, =(STR71X_APB2_APB2ALL & ~STR71X_APB2_EIC)
-#else
- ldr \value, =STR71X_APB2_APB2ALL
-#endif
strh \value, [\base2, #STR71X_APB_CKDIS_OFFSET]
- /* Reset and enable peripherals */
-#if 0
- /* Hold all APB1 and APB2 peripherals under reset */
-
- ldr \value, =STR71X_APB1_APB1ALL
- strh \value, [\base1, #STR71X_APB_SWRES_OFFSET]
- ldr \value, =STR71X_APB2_APB2ALL
- strh \value, [\base2, #STR71X_APB_SWRES_OFFSET]
-
- /* Wait that the selected macrocells exit from reset */
-
- mov \value, #10
-loop1: subs \value, \value, #1
- bne loop1
-
- /* Release APB1 and APB2 peripherals from reset */
-
- mov \value, #0
- strh \value, [\base1, #STR71X_APB_SWRES_OFFSET]
- strh \value, [\base2, #STR71X_APB_SWRES_OFFSET]
-
- /* Enable clocking for all APB1 and APB2 peripherals */
-
- strh \value, [\base1, #STR71X_APB_CKDIS_OFFSET]
- strh \value, [\base2, #STR71X_APB_CKDIS_OFFSET];
-
- /* Wait that the selected macrocells exit from reset */
-
- mov \value, #10
-loop2: subs \value, \value, #1
- bne loop2
-#endif
-
/* Allow EMI and USB */
ldr \base1, =STR71X_RCCU_BASE
@@ -543,13 +523,6 @@ __flashstart:
remap r0, r1
- /* Configure the uart so that we can get debug output as soon
- * as possible. Modifies r0, r1, r2, and r14.
- */
-
- bl up_lowsetup
- showprogress 'A'
-
/* Setup system stack (and get the BSS range) */
adr r0, LC0
@@ -562,8 +535,6 @@ __flashstart:
strcc r0, [r4], #4
bcc 1b
- showprogress 'B'
-
/* Copy system .data sections to new home in RAM. */
#ifdef CONFIG_BOOT_FROM_FLASH
@@ -577,6 +548,17 @@ __flashstart:
blt 1b
#endif
+ /* Initialize clocking */
+
+ bl str71x_prccuinit
+
+ /* Configure the uart so that we can get debug output as soon
+ * as possible. Modifies r0, r1, r2, and r14.
+ */
+
+ bl up_lowsetup
+ showprogress 'A'
+
/* Perform early serial initialization */
mov fp, #0
@@ -584,10 +566,11 @@ __flashstart:
bl up_earlyserialinit
#endif
- showprogress 'C'
+ showprogress 'B'
/* Call C++ constructors */
+#ifdef CONFIG_CPLUSPLUS
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
ctor_loop:
@@ -601,7 +584,8 @@ ctor_loop:
b ctor_loop
ctor_end:
- showprogress 'D'
+ showprogress 'C'
+#endif
showprogress '\n'
/* Initialize onboard LEDs */
@@ -615,7 +599,8 @@ ctor_end:
b os_start
/* Call destructors -- never get here */
-#if 0
+
+#if 0 /* CONFIG_CPLUSPLUS */
ldr r0, =__dtors_start__
ldr r1, =__dtors_end__
dtor_loop:
diff --git a/nuttx/arch/arm/src/str71x/str71x_pcu.h b/nuttx/arch/arm/src/str71x/str71x_pcu.h
index 8fdf5529d..423ab72f4 100644
--- a/nuttx/arch/arm/src/str71x/str71x_pcu.h
+++ b/nuttx/arch/arm/src/str71x/str71x_pcu.h
@@ -68,6 +68,27 @@
/* Register bit settings ************************************************************/
+/* PCU MDIVR register bit definitions */
+
+#define STR71X_PCUMDIVR_FACTMASK (0x0003) /* Bits 0-1: Division factor for main system clock */
+#define STR71X_PCUMDIVR_DIV1 (0x0000) /* MCLK = RCLK */
+#define STR71X_PCUMDIVR_DIV2 (0x0001) /* MCLK = RCLK / 2 */
+#define STR71X_PCUMDIVR_DIV4 (0x0002) /* MCLK = RCLK / 4 */
+#define STR71X_PCUMDIVR_DIV8 (0x0003) /* MCLK = RCLK / 8 */
+
+/* PCU PDIVR register bit definitions */
+
+#define STR71X_PCUPDIVR_FACT1MASK (0x0003) /* Bits 0-1: Division factor for APB1 peripherals */
+#define STR71X_PCUPDIVR_APB1DIV1 (0x0000) /* PCLK1 = RCLK */
+#define STR71X_PCUPDIVR_APB1DIV2 (0x0001) /* PCLK1 = RCLK / 2 */
+#define STR71X_PCUPDIVR_APB1DIV4 (0x0002) /* PCLK1 = RCLK / 4 */
+#define STR71X_PCUPDIVR_APB1DIV8 (0x0003) /* PCLK1 = RCLK / 8 */
+#define STR71X_PCUPDIVR_FACT1MASK (0x0300) /* Bits 8-9: Division factor for APB2 peripherals */
+#define STR71X_PCUPDIVR_APB2DIV1 (0x0000) /* PCLK2 = RCLK */
+#define STR71X_PCUPDIVR_APB2DIV2 (0x0100) /* PCLK2 = RCLK / 2 */
+#define STR71X_PCUPDIVR_APB2DIV4 (0x0200) /* PCLK2 = RCLK / 4 */
+#define STR71X_PCUPDIVR_APB2DIV8 (0x0300) /* PCLK2 = RCLK / 8 */
+
/* PCU RSTR register bit definitions */
#define STR71X_PCURSTR_EMIRESET (0x0004) /* Bit 2: EMI reset */
@@ -88,7 +109,7 @@
#define STR71X_PCUPPL2CR_MUL12 (0x0010) /* CLK2 * 12 */
#define STR71X_PCUPPL2CR_MUL28 (0x0020) /* CLK2 * 28 */
#define STR71X_PCUPPL2CR_MUL16 (0x0030) /* CLK2 * 16 */
-#define STR71X_PCUPPL2CR_FRRRNG (0x0040) /* Bit 6: PLL2 frequency range selection */
+#define STR71X_PCUPPL2CR_FRQRNG (0x0040) /* Bit 6: PLL2 frequency range selection */
#define STR71X_PCUPPL2CR_PLLEN (0x0080) /* Bit 7: PLL2 enable */
#define STR71X_PCUPPL2CR_USBEN (0x0100) /* Bit 8: Enable PLL clock to USB */
#define STR71X_PCUPPL2CR_IRQMASK (0x0200) /* Bit 9: Enable interrupt request CPU on lock transition */
diff --git a/nuttx/arch/arm/src/str71x/str71x_prccu.c b/nuttx/arch/arm/src/str71x/str71x_prccu.c
new file mode 100644
index 000000000..999094d24
--- /dev/null
+++ b/nuttx/arch/arm/src/str71x/str71x_prccu.c
@@ -0,0 +1,342 @@
+/********************************************************************************
+ * arch/arm/src/str71x/str71x_prccu.c
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sys/types.h>
+
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include "chip.h"
+
+/********************************************************************************
+ * Definitions
+ ********************************************************************************/
+
+/* Input frequency (CLK2) is either the main oscillator or the main oscillator
+ * divided by 2.
+ */
+
+#ifdef STR71X_PLL1_DIV2
+# define STR71X_PLL1_CLK2 (STR71X_RCCU_MAIN_OSC/2)
+#else
+# define STR71X_RCCU_MAIN_OSC STR71X_RCCU_MAIN_OSC
+#endif
+
+/* Select set of peripherals to be enabled */
+
+/* APB1 periperals */
+
+#ifndef CONFIG_STR71X_I2C0
+# define APB1EN_I2C0 STR71X_APB1_I2C0
+#else
+# define APB1EN_I2C0 (0)
+#endif
+
+#ifndef CONFIG_STR71X_I2C1
+# define APB1EN_I2C1 STR71X_APB1_I2C1
+#else
+# define APB1EN_I2C1 (0)
+#endif
+
+#ifndef CONFIG_STR71X_UART0
+# define APB1EN_UART0 STR71X_APB1_UART0
+#else
+# define APB1EN_UART0 (0)
+#endif
+
+#ifndef CONFIG_STR71X_UART1
+# define APB1EN_UART1 STR71X_APB1_UART1
+#else
+# define APB1EN_UART1 (0)
+#endif
+
+#ifndef CONFIG_STR71X_UART2
+# define APB1EN_UART2 STR71X_APB1_UART2
+#else
+# define APB1EN_UART2 (0)
+#endif
+
+#ifndef CONFIG_STR71X_UART3
+# define APB1EN_UART3 STR71X_APB1_UART3
+#else
+# define APB1EN_UART3 (0)
+#endif
+
+#ifndef CONFIG_STR71X_USB
+# define APB1EN_USB STR71X_APB1_USB
+#else
+# define APB1EN_USB (0)
+#endif
+
+#ifndef CONFIG_STR71X_CAN
+# define APB1EN_CAN STR71X_APB1_CAN
+#else
+# define APB1EN_CAN (0)
+#endif
+
+#ifndef CONFIG_STR71X_BSPI0
+# define APB1EN_BSPI0 STR71X_APB1_BSPI0
+#else
+# define APB1EN_BSPI0 (0)
+#endif
+
+#ifndef CONFIG_STR71X_BSPI1
+# define APB1EN_BSPI1 STR71X_APB1_BSPI1
+#else
+# define APB1EN_BSPI1 (0)
+#endif
+
+#ifndef CONFIG_STR71X_HDLC
+# define APB1EN_HDLC STR71X_APB1_HDLC
+#else
+# define APB1EN_HDLC (0)
+#endif
+
+#define APB1EN_ALL (APB1EN_I2C0|APB1EN_I2C1|APB1EN_UART0|APB1EN_UART1|\
+ APB1EN_UART2|APB1EN_UART3|APB1EN_USB|APB1EN_CAN|\
+ APB1EN_BSPI0|APB1EN_BSPI1|APB1EN_HDLC)
+
+/* APB2 Peripherals */
+
+#ifndef CONFIG_STR71X_XTI
+# define APB2EN_XTI STR71X_APB2_XTI
+#else
+# define APB2EN_XTI (0)
+#endif
+
+#ifndef CONFIG_STR71X_GPIO0
+# define APB2EN_GPIO0 STR71X_APB2_GPIO0
+#else
+# define APB2EN_GPIO0 (0)
+#endif
+
+#ifndef CONFIG_STR71X_GPIO1
+# define APB2EN_GPIO1 STR71X_APB2_GPIO1
+#else
+# define APB2EN_GPIO1 (0)
+#endif
+
+#ifndef CONFIG_STR71X_GPIO2
+# define APB2EN_GPIO2 STR71X_APB2_GPIO2
+#else
+# define APB2EN_GPIO2 (0)
+#endif
+
+#ifndef CONFIG_STR71X_ADC12
+# define APB2EN_ADC12 STR71X_APB2_ADC12
+#else
+# define APB2EN_ADC12 (0)
+#endif
+
+#ifndef CONFIG_STR71X_CKOUT
+# define APB2EN_CKOUT STR71X_APB2_CKOUT
+#else
+# define APB2EN_CKOUT (0)
+#endif
+
+#define APB2EN_TIM0 (0) /* System timer -- always enabled */
+
+#ifndef CONFIG_STR71X_TIM1
+# define APB2EN_TIM1 STR71X_APB2_TIM1
+#else
+# define APB2EN_TIM1 (0)
+#endif
+
+#ifndef CONFIG_STR71X_TIM2
+# define APB2EN_TIM2 STR71X_APB2_TIM2
+#else
+# define APB2EN_TIM2 (0)
+#endif
+
+#ifndef CONFIG_STR71X_TIM3
+# define APB2EN_TIM3 STR71X_APB2_TIM3
+#else
+# define APB2EN_TIM3 (0)
+#endif
+
+#ifndef CONFIG_STR71X_RTC
+# define APB2EN_RTC STR71X_APB2_RTC
+#else
+# define APB2EN_RTC (0)
+#endif
+
+#define APB2EN_EIC (0) /* Interrupt controller always enabled */
+
+#define APB2EN_ALL (APB2EN_XTI|APB2EN_GPIO0|APB2EN_GPIO1|APB2EN_GPIO2|\
+ APB2EN_ADC12|APB2EN_CKOUT|APB2EN_TIM0|APB2EN_TIM1|\
+ APB2EN_TIM2|APB2EN_TIM3|APB2EN_RTC|APB2EN_EIC)
+
+/********************************************************************************
+ * Private Types
+ ********************************************************************************/
+
+/********************************************************************************
+ * Public Data
+ ********************************************************************************/
+
+/********************************************************************************
+ * Private Data
+ ********************************************************************************/
+
+/********************************************************************************
+ * Private Functions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Public Funstions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Name: str71x_prccuinit
+ *
+ * Description:
+ * Initialize the PCU/RCCU based on the NuttX configuration and the board-specific
+ * settings in board.h
+ *
+ ********************************************************************************/
+
+void str71x_prccuinit(void)
+{
+ uint32 reg32;
+ uint16 reg16;
+
+ /* Divide RCLK to obtain PCLK1 & 2 clock for the APB1 & 2 peripherals. The divider
+ * values are provided in board.h
+ */
+
+ reg16 = getreg16(STR71X_PCU_PDIVR);
+ reg16 &= ~(STR71X_PCUPDIVR_FACT1MASK|STR71X_PCUPDIVR_FACT2MASK);
+ reg16 |= (STR71X_APB1_DIV|STR71X_APB2_DIV
+ putreg16(reg16, STR71X_PCU_PDIVR);
+
+ /* Configure the main system clock (MCLK) divider with value from board.h */
+
+ reg16 = getreg16(STR71X_PCU_MDIVR);
+ reg16 &= ~STR71X_PCUMDIVR_FACTMASK;
+ reg16 |= STR71X_MCLK_DIV
+ purreg16(reg16 , STR71X_PCU_MDIVR);
+
+ /* Turn off the PLL1 by setting bits DX[2:0] */
+
+ putreg32(STR71X_RCCUPLL1CR_CLK2, STR71X_RCCU_PLL1CR);
+
+ /* Configure the PLL1CR register using the provided multiplier and
+ * divider. The FREF_RANGE bit is also set if the input frequency
+ * (CLK2) is greater than 3MHz.
+ */
+
+#if STR71X_PLL1_CLK2 > 3000000
+ putreg32(STR71X_PLL1OUT_MUL|STR71X_PLL1OUT_DIV, STR71X_RCCU_PLL1CR);
+#else
+ putreg32(STR71X_PLL1OUT_MUL|STR71X_PLL1OUT_DIV|STR71X_RCCUPLL1CR_FREFRANGE, STR71X_RCCU_PLL1CR);
+#endif
+
+ /* Wait for the PLL to lock */
+
+ while (getreg16(STR71X_RCCU_CFR) & STR71X_RCCUCFR_LOCK) == 0);
+
+ /* Set the CK2_16 Bit in the CFR to use CLK2/PLL1OUT as CLK3 */
+
+ reg32 = getreg32(STR71X_RCCU_CFR);
+ putreg32(reg32 | STR71X_RCCUCFR_CK216, STR71X_RCCU_CFR);
+
+ /* Wait for the PLL to lock */
+
+ while (getreg16(STR71X_RCCU_CFR) & STR71X_RCCUCFR_LOCK) == 0);
+
+ /* Select CLK3 (vs the alternative source) for RCLK in the clock
+ * control register (CCR)
+ */
+
+ reg16 = getreg16(STR71X_RCCU_CCR);
+ reg16 &= ~STR71X_RCCUCCR_CKAFSEL
+ putreg16(reg16, STR71X_RCCU_CCR);
+
+ /* Select PLL1OUT as the CLK3 */
+
+ reg32 = getreg32(STR71X_RCCU_CFR);
+ putreg32(reg32 | STR71X_RCCUCFR_CSUCKSEL, STR71X_RCCU_CFR);
+
+ /* Enable clocking on selected periperals */
+
+ putreg32(APB1EN_ALL, STR71X_APB1_CKDIS);
+ putreg32(APB2EN_ALL, STR71X_APB2_CKDIS);
+
+ /* Configure PLL2 */
+
+#if defined(CONFIG_STR71X_HDLC) || (defined(CONFIG_STR71X_USB) && defined(STR71X_USBIN_PLL2))
+ reg16 = getreg16(STR71X_PCU_PLL2CR);
+ reg16 &= ~(STR71X_PCUPPL2CR_MXMASK|STR71X_PCUPPL2CR_DXMASK);
+ reg16 |= (STR71X_PLL2OUT_MUL|STR71X_PLL2OUT_DIV);
+
+ /* Set the PLL2 FRQRNG bit according to the PLL2 input frequency */
+
+#if STR71X_PCU_HCLK_OSC < 3000000
+ reg16 &= ~STR71X_PCUPPL2CR_FRQRNG;
+#else
+ reg16 |= STR71X_PCUPPL2CR_FRQRNG;
+#else
+ putreg16(reg16, STR71X_PCU_PLL2CR);
+
+ /* Wait for PLL2 to lock in */
+ // while (getreg16(STR71X_PCU_PLL2CR) & STR71X_PCUPPL2CR_LOCK) == 0);
+#endif
+
+ /* Select the USB clock source */
+
+#ifdef CONFIG_STR71X_USB
+ reg16 = getreg16(STR71X_PCU_PLL2CR);
+#ifdef STR71X_USBIN_PLL2
+ /* PLL2 is the clock source to the USB */
+
+ reg16 |= STR71X_PCUPPL2CR_USBEN;
+#else
+ /* USBCLK pin is the clock source to the USB */
+
+ reg16 &= ~STR71X_PCUPPL2CR_USBEN;
+#endif
+ putreg16(reg16, STR71X_PCU_PLL2CR);
+#endif
+}
+
+