summaryrefslogblamecommitdiff
path: root/nuttx/arch/arm/src/str71x/str71x_prccu.c
blob: 61cee03dde2459373f735b6f36d5dc5e95a6103f (plain) (tree)
1
2
3
4


                                                                                 
                                                               



































                                                                                  
 
                   






                       
                    
                            

                                                                                 
                           

                                                                                  












                                             





                                            





                                        


                                                             





                                        


                                                             





                                        


                                                             





                                        
                             



                                             
        

















                                        








                                             





                                        


                                 


















































































                                                                       






                                         
                              
































































                                                   
                              






















                                                   






























                                                                                    

                 
 


                                                                                     


                                                                  
                             



                                                                              
                                      
                                     
                   
                                     









                                                                    
                         
                                                
     
                                                                            



                                
                                                                 


                                                                 










                                                     


                                
                                                                 





                                                                  
                                   
















                                                                                             
                             






                                                                     
      


                                     
                                                                        



















                                                 
/********************************************************************************
 * arch/arm/src/str71x/str71x_prccu.c
 *
 *   Copyright (C) 2008-2009 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 <stdint.h>
#include <assert.h>
#include <debug.h>

#include <nuttx/irq.h>
#include <nuttx/arch.h>

#include "chip.h"
#include "up_arch.h"
#include "str71x_internal.h"

/********************************************************************************
 * Pre-procesor Definitions
 ********************************************************************************/

/* 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
#  ifndef CONFIG_STR71X_GPIO0
#    error "I2C1 requires GPIO0"
#  endif
#  ifdef CONFIG_STR71X_BSPI0
#    error "I2C1 is incompatible with BSPI0"
#  endif
#  define APB1EN_I2C1 (0)
#endif

#ifndef CONFIG_STR71X_UART0
#  define APB1EN_UART0 STR71X_APB1_UART0
#else
#  ifndef CONFIG_STR71X_GPIO0
#    error "CONFIG_STR71X_UART0 requires CONFIG_STR71X_GPIO0"
#  endif
#  define APB1EN_UART0 (0)
#endif

#ifndef CONFIG_STR71X_UART1
#  define APB1EN_UART1 STR71X_APB1_UART1
#else
#  ifndef CONFIG_STR71X_GPIO0
#    error "CONFIG_STR71X_UART1 requires CONFIG_STR71X_GPIO0"
#  endif
#  define APB1EN_UART1 (0)
#endif

#ifndef CONFIG_STR71X_UART2
#  define APB1EN_UART2 STR71X_APB1_UART2
#else
#  ifndef CONFIG_STR71X_GPIO0
#    error "CONFIG_STR71X_UART2 requires CONFIG_STR71X_GPIO0"
#  endif
#  define APB1EN_UART2 (0)
#endif

#ifndef CONFIG_STR71X_UART3
#  define APB1EN_UART3 STR71X_APB1_UART3
#else
#  ifndef CONFIG_STR71X_GPIO0
#    error "UART3 requires GPIO0"
#  endif
#  ifdef CONFIG_STR71X_BSPI0
#    error "UART3 is incompatible with BSPI0"
#  endif
#  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
#  ifndef CONFIG_STR71X_GPIO0
#    error "BSPI0 requires GPIO0"
#  endif
#  ifdef CONFIG_STR71X_UART3
#    error "BSPI0 is incompatible with UART3"
#  endif
#  ifdef CONFIG_STR71X_I2C1
#    error "BSPI0 is incompatible with I2C1"
#  endif
#  define APB1EN_BSPI0 (0)
#endif

#ifndef CONFIG_STR71X_BSPI1
#  define APB1EN_BSPI1 STR71X_APB1_BSPI1
#else
#  ifndef CONFIG_STR71X_GPIO0
#    error "BSPI1 requires GPIO0"
#  endif
#  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)


#if STR71X_PLL1OUT_MUL == 12
#  define PLL1MUL STR71X_RCCUPLL1CR_MUL12
#elif STR71X_PLL1OUT_MUL == 16
#  define PLL1MUL STR71X_RCCUPLL1CR_MUL16
#elif STR71X_PLL1OUT_MUL == 20
#  define PLL1MUL STR71X_RCCUPLL1CR_MUL20
#elif STR71X_PLL1OUT_MUL == 24
#  define PLL1MUL STR71X_RCCUPLL1CR_MUL24
#else
#  error "Unsupporetd value for STR71X_PLL1OUT_MUL"
#endif

#if STR71X_PLL1OUT_DIV == 1
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV1
#elif STR71X_PLL1OUT_DIV == 2
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV2
#elif STR71X_PLL1OUT_DIV == 3
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV3
#elif STR71X_PLL1OUT_DIV == 4
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV4
#elif STR71X_PLL1OUT_DIV == 5
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV5
#elif STR71X_PLL1OUT_DIV == 6
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV6
#elif STR71X_PLL1OUT_DIV == 7
#  define PLL1DIV STR71X_RCCUPLL1CR_DIV7
#else
#  error "Unsupported value for STR71X_PLL1OUT_DIV"
#endif

#if STR71X_APB1_DIV == 1
#  define APB1DIV STR71X_PCUPDIVR_APB1DIV1
#elif STR71X_APB1_DIV == 2
#  define APB1DIV STR71X_PCUPDIVR_APB1DIV2
#elif STR71X_APB1_DIV == 4
#  define APB1DIV STR71X_PCUPDIVR_APB1DIV4
#elif STR71X_APB1_DIV == 8
#  define APB1DIV STR71X_PCUPDIVR_APB1DIV8
#else
#  error "Unsupported value for STR71X_APB1_DIV"
#endif

#if STR71X_APB2_DIV == 1
#  define APB2DIV STR71X_PCUPDIVR_APB2DIV1
#elif STR71X_APB2_DIV == 2
#  define APB2DIV STR71X_PCUPDIVR_APB2DIV2
#elif STR71X_APB2_DIV == 4
#  define APB2DIV STR71X_PCUPDIVR_APB2DIV4
#elif STR71X_APB2_DIV == 8
#  define APB2DIV STR71X_PCUPDIVR_APB2DIV8
#else
#  error "Unsupported value for STR71X_APB2_DIV"
#endif

#if STR71X_MCLK_DIV == 1
#  define MCLKDIV STR71X_PCUMDIVR_DIV1
#elif STR71X_MCLK_DIV == 2
#  define MCLKDIV STR71X_PCUMDIVR_DIV2
#elif STR71X_MCLK_DIV == 4
#  define MCLKDIV STR71X_PCUMDIVR_DIV4
#elif STR71X_MCLK_DIV == 8
#  define MCLKDIV STR71X_PCUMDIVR_DIV8
#else
#  error "Unsupported value for STR71X_MCLK_DIV"
#endif

#if STR71X_PLL2OUT_MUL == 12
#  define PLL2MUL STR71X_PCUPPL2CR_MUL12
#elif STR71X_PLL2OUT_MUL == 16
#  define PLL2MUL STR71X_PCUPPL2CR_MUL16
#elif STR71X_PLL2OUT_MUL == 20
#  define PLL2MUL STR71X_PCUPPL2CR_MUL20
#elif STR71X_PLL2OUT_MUL == 28
#  define PLL2MUL STR71X_PCUPPL2CR_MUL28
#else
#  error "Unsupporetd value for STR71X_PLL2OUT_MUL"
#endif

#if STR71X_PLL2OUT_DIV == 1
#  define PLL2DIV STR71X_PCUPPL2CR_DIV1
#elif STR71X_PLL2OUT_DIV == 2
#  define PLL2DIV STR71X_PCUPPL2CR_DIV2
#elif STR71X_PLL2OUT_DIV == 3
#  define PLL2DIV STR71X_PCUPPL2CR_DIV3
#elif STR71X_PLL2OUT_DIV == 4
#  define PLL2DIV STR71X_PCUPPL2CR_DIV4
#elif STR71X_PLL2OUT_DIV == 5
#  define PLL2DIV STR71X_PCUPPL2CR_DIV5
#elif STR71X_PLL2OUT_DIV == 6
#  define PLL2DIV STR71X_PCUPPL2CR_DIV6
#elif STR71X_PLL2OUT_DIV == 7
#  define PLL2DIV STR71X_PCUPPL2CR_DIV7
#else
#  error "Unsupported value for STR71X_PLL2OUT_DIV"
#endif

/********************************************************************************
 * 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_t reg32;
  uint16_t 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 |= (APB1DIV|APB2DIV);
  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 |= MCLKDIV;
  putreg16(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_CLK2 > 3000000
  putreg32(PLL1MUL|PLL1DIV, STR71X_RCCU_PLL1CR);
#else
  putreg32(PLL1MUL|PLL1DIV|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);
  reg32 |= STR71X_RCCUCFR_CK216;

  /* Should the main oscillator divided down by 2? */

#ifdef STR71X_PLL1IN_DIV2
  reg32 |= STR71X_RCCUCFR_DIV2;
#else
  reg32 &= ~STR71X_RCCUCFR_DIV2;
#endif
  putreg32(reg32, 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 |= (PLL2MUL|PLL2DIV);

  /* 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;
#endif
  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
}