diff chipsetsw/drivers/drv_core/clkm/clkm.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chipsetsw/drivers/drv_core/clkm/clkm.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,511 @@
+/******************************************************************************
+            TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION           
+                                                                             
+   Property of Texas Instruments -- For  Unrestricted  Internal  Use  Only 
+   Unauthorized reproduction and/or distribution is strictly prohibited.  This 
+   product  is  protected  under  copyright  law  and  trade  secret law as an 
+   unpublished work.  Created 1987, (C) Copyright 1997 Texas Instruments.  All 
+   rights reserved.                                                            
+                  
+                                                           
+   Filename       	: clkm.c
+
+   Description    	: Set of functions useful to test the Saturn
+			  CLKM peripheral 
+
+   Project        	: drivers
+
+   Author         	: pmonteil@tif.ti.com  Patrice Monteil.
+
+   Version number   : 1.13
+
+   Date             : 05/23/03
+
+   Previous delta 	: 10/23/01 14:43:31
+
+   Sccs Id  (SID)       : '@(#) clkm.c 1.11 10/23/01 14:43:31 '
+
+*****************************************************************************/
+
+           //############################################################
+           //############################################################
+           //### Be careful: this file must be placed in Flash Memory ###
+           //###     and compiled in 16 bits length intructions       ###
+           //###        (CF. the function wait_ARM_cycles()           ###
+           //############################################################
+           //############################################################
+           
+#include "l1sw.cfg"
+#include "chipset.cfg"
+#include "board.cfg"
+#include "swconfig.cfg"
+
+#if (OP_L1_STANDALONE == 0)
+  #include "main/sys_types.h"
+#else
+  #include "sys_types.h"
+#endif
+
+#include "clkm.h" 
+
+
+#if (CHIPSET == 12)
+    #include "sys_memif.h"
+#else
+    #include "memif/mem.h"
+#endif
+
+#if (BOARD == 34)
+  #include "armio/armio.h"
+  #include "timer/timer.h"
+#endif
+
+static SYS_UWORD32 ratio_wait_loop = 0;
+
+#if (CHIPSET == 12)
+  const double dsp_div_value[CLKM_NB_DSP_DIV_VALUE] = {1, 1.5, 2, 3};
+#endif
+
+#if (BOARD == 34)
+/*
+ *  CLKM_InitARMClock()
+ *
+ * This init is for VTCX0 = 13 MHz
+ *   (use CLKM_VTCXO_26 if VTCX0 is 26 MHz)
+ * Parameters :    src : 0x0 means EXT CLK (mpu dpll) selected
+ *                       0x1 means VTCX0 selected
+ *                 div : Division factor applied to clock
+ *                         source
+ *                        (div = 3 -> divise by 3/2 in fact)
+ *             WARNING : reverse order in comparison to ULYSSE
+ *
+ * Return     : none
+ * Functionality :Initialize the ARM Clock frequency
+ */
+
+void CLKM_InitARMClock(int src, int div)
+{
+    SYS_UWORD16 cntl = * (volatile SYS_UWORD16 *) CLKM_ARM_CLK;
+    int clk_xp5, clk_div;
+
+    if (div == 3)
+    clk_xp5 = 1;
+    else
+    clk_xp5 = 0;
+
+    if (div == 2)
+    clk_div = 1;
+    else if (div == 4) 
+    clk_div = 0;
+    else
+    clk_div = 3;
+
+    cntl &= ~(MASK_ARM_MCLK_1P5 | CLKM_MCLK_DIV);
+    cntl |= ((clk_xp5 << 3) | (clk_div << 4));
+
+    * (volatile SYS_UWORD16 *) CLKM_ARM_CLK = cntl;
+    if (src)
+    CLKM_EnableDPLL(0);
+    else
+    CLKM_EnableDPLL(1);
+}
+
+/*
+ * CLKM_SetMclkDiv
+ *
+ * Set divider 
+ *
+ * Parameter : 2-bit divider as per spec (0-7)
+ * 
+ * Side-effect : compute magic delay for busy loops
+ *
+ */
+void CLKM_SetMclkDiv(int div)
+{
+    volatile SYS_UWORD16 clkm_ctrl;
+    clkm_ctrl = *((volatile SYS_UWORD16 *) CLKM_ARM_CLK); // read register
+    clkm_ctrl &= ~CLKM_MCLK_DIV;	
+    clkm_ctrl |= (div << 4);
+    *((volatile SYS_UWORD16 *) CLKM_ARM_CLK) = clkm_ctrl;
+}
+
+/*
+ * CLKM_EnableDPLL
+ *
+ * Enable or disable 48mhz PLL for ARM clock
+ *
+ * Parameter : 1 or 0
+ *
+ * Side-effect : compute magic delay for busy loops
+ *
+ */
+void CLKM_EnableDPLL(int enable)
+{
+    volatile SYS_UWORD16 clkm_ctrl;
+
+    // read CLKM register
+    clkm_ctrl = *((volatile SYS_UWORD16 *) CLKM_ARM_CLK);
+
+    if (enable) 
+    {
+        // PARAMETERS tuned for the AVENGER 2 reference design
+        // we wait before accessing external memory at wake up
+        // we have 2.5 ms margin before the first IT TDMA, we wait
+        //
+        //  5000     loop cycles
+        //  5000 * 5 arm7 cycles
+        // giving <= 1 ms at 26 MHz
+        //
+        wait_ARM_cycles(5000);
+    }
+    else 
+    {
+        // reset bit for VTCXO
+        clkm_ctrl &= ~CLKM_CLKIN_SEL;
+        *((volatile SYS_UWORD16 *) CLKM_ARM_CLK) = clkm_ctrl;
+
+        // disable clk48mhz
+        AI_ResetBit(6);
+    }
+}
+
+/*
+ * CLKM_EnableSharedMemClock
+ *
+ * Enable or disable shared mem clock 
+ *
+ * Parameter : 1 or 0
+ *
+ */
+void CLKM_EnableSharedMemClock(int enable)
+{
+    if (enable) 
+    {
+        // request shared mem clock and wait for MPU HW acknowledge
+        AI_ResetBit(4);
+        while(AI_ReadBit(5)!=1); 
+    }
+    else 
+    {
+        // disable shared mem clock
+        AI_SetBit(4);
+    }
+}
+
+/*
+ * CLKM_InitLeadClock
+ * 
+ * Parameter : onoff, mul, ndiv, div 
+ *  
+ * onoff -> (1:pll on) (0: pll off)
+ * if div = 0  -> x(plmul+1) 
+ * if div = 1  -> x(plmul+1)/2 if plmul is even
+ *                x(plmul/4)   if plmul is odd
+ * ndiv
+ */
+
+void CLKM_InitLeadClock(int onoff, int mul, int ndiv, int div)
+{
+    int pldiv, pllndiv ;
+    SYS_UWORD16 value = 0;
+
+    value |=  onoff & CLKM_PLONOFF ;
+    value |= (mul << 1) & CLKM_PLMUL;
+    value |= (ndiv << 5)& CLKM_PLLNDIV;
+    value |= (div << 6) & CLKM_PLDIV;
+
+    CLKM_INITLEADPLL(value);
+}
+
+#elif ((CHIPSET == 4) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+  /*--------------------------------------------------------------*/
+  /*  CLKM_InitARMClock()                                         */
+  /*--------------------------------------------------------------*/
+  /* Parameters :  clk_src : 0x00 means DPLL selected             */
+  /*                         0x01 means VTCX0 selected            */
+  /*                         0x03 means CLKIN selected            */
+  /*               clk_xp5 : Enable 1.5 or 2.5 division factor    */
+  /*                         (0 or 1)                             */
+  /*               clk_div : Division factor applied to clock     */
+  /*                         source                               */
+  /*             WARNING : reverse order in comparison to ULYSSE  */
+  /*                                                              */
+  /* Return     : none                                            */
+  /* Functionality :Initialize the ARM Clock frequency            */
+  /*--------------------------------------------------------------*/
+  void CLKM_InitARMClock(SYS_UWORD16 clk_src, SYS_UWORD16 clk_div, SYS_UWORD16 clk_xp5)
+  {
+    SYS_UWORD16 cntl = * (volatile SYS_UWORD16 *) CLKM_ARM_CLK;
+        
+    cntl &= ~(CLKM_CLKIN0 | CLKM_CLKIN_SEL | CLKM_ARM_MCLK_XP5 | CLKM_MCLK_DIV);
+    
+    cntl |= ((clk_src << 1) | (clk_xp5 << 3) | (clk_div << 4));
+    
+    * (volatile SYS_UWORD16 *) CLKM_ARM_CLK = cntl;
+  }
+#else
+  /*--------------------------------------------------------------
+   *  CLKM_InitARMClock()
+   *--------------------------------------------------------------
+   * Parameters :  clk_src : 0x00 means CLKIN selected
+   *	  	  	   0x01 means 32 K selected
+   *	 	  	   0x02 means External clock selected
+   *
+   * Return     :	none
+   * Functionality :Initialize the ARM Clock frequency
+   *--------------------------------------------------------------*/
+  void CLKM_InitARMClock(SYS_UWORD16 clk_src, SYS_UWORD16 clk_div)
+  {
+    SYS_UWORD16 cntl = * (volatile SYS_UWORD16 *) CLKM_ARM_CLK;
+
+    cntl &= ~(CLKM_LOW_FRQ | CLKM_CLKIN_SEL | CLKM_MCLK_DIV);
+
+    cntl |= ((clk_src << 1) | (clk_div << 4));
+
+    * (volatile SYS_UWORD16 *) CLKM_ARM_CLK = cntl;
+  }
+
+#endif
+
+
+/*-------------------------------------------------------*/ 
+/* convert_nanosec_to_cycles()                           */
+/*-------------------------------------------------------*/
+/* parameter: time in 10E-9 seconds                      */
+/* return: Number of cycles for the wait_ARM_cycles()    */
+/*         function                                      */
+/*                                                       */
+/* Description:                                          */
+/* ------------                                          */
+/* convert x nanoseconds in y cycles used by the ASM loop*/
+/* function . Before calling this function, call the     */ 
+/* initialize_wait_loop() function                       */
+/* Called when the HardWare needs time to wait           */
+/*-------------------------------------------------------*/ 
+SYS_UWORD32 convert_nanosec_to_cycles(SYS_UWORD32 time)
+{ 
+  return( time / ratio_wait_loop);  
+}
+
+
+/*-------------------------------------------------------*/
+/* initialize_wait_loop()                                */
+/*-------------------------------------------------------*/
+/*                                                       */
+/* Description:                                          */
+/* ------------                                          */
+/* Init the ratio used to convert time->Cycles according */
+/* to hardware parameters                                */
+/* measurement time for this function (ARM 39Mhz, 3 waits*/
+/* states) = 75 micoseconds                              */
+/*-------------------------------------------------------*/
+
+void initialize_wait_loop(void)
+{
+#if (BOARD == 34)
+    unsigned long ulTimeSpent=0;
+
+    // set up timer 2 for wait_ARM_cycles function calibration
+    TM_EnableTimer (2);
+    TM_ResetTimer (2, 0xFFFF, 0, 0);
+
+    // run wait_ARM_cycles() for 10000 loops
+    wait_ARM_cycles(10000);
+
+    // time spent expressed in timer cycles
+    // where 1 timer cycle = 2462 ns with prescale 0
+    // 13 MHz divided by 16 = timer clkin 
+    // prescale 0 -> divided by 2
+    ulTimeSpent = TM_ReadTimer (2);
+
+    TM_StopTimer (2);
+
+    ulTimeSpent = 0xFFFF - ulTimeSpent;
+    ulTimeSpent *= 2462;
+
+    // compute ratio_wait_loop
+    ratio_wait_loop = (unsigned long)(ulTimeSpent/10000.);
+#else
+  #define NBR_CYCLES_IN_LOOP   5   // this value is got from an oscilloscope measurement
+  
+  double src_ratio;
+  double final_ratio;
+
+  SYS_UWORD16 flash_access_size;
+  SYS_UWORD16 flash_wait_state;
+  SYS_UWORD32 nbr;
+  SYS_UWORD32 arm_clock;
+
+  //////////////////////////////////
+  //  compute the ARM clock used  //
+  //////////////////////////////////
+  {
+    SYS_UWORD16 arm_mclk_xp5;
+    SYS_UWORD16 arm_ratio;
+    SYS_UWORD16 clk_src;
+    SYS_UWORD16 clkm_cntl_arm_clk_reg = * (volatile SYS_UWORD16 *) CLKM_CNTL_ARM_CLK;
+
+    #if ((CHIPSET == 4) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+      clk_src  = (clkm_cntl_arm_clk_reg & MASK_CLKIN) >> 1;
+      switch (clk_src)
+      {
+        case 0x00: //DPLL selected 
+          // select the DPLL factor
+           #if (CHIPSET == 12)
+              if (((* (volatile SYS_UWORD16 *) C_MAP_DPLL_BASE) & DPLL_LOCK) != 0)
+           #else
+              if (((* (volatile SYS_UWORD16 *) MEM_DPLL_ADDR) & DPLL_LOCK) != 0)
+           #endif 
+          {
+             SYS_UWORD16 dpll_div;
+             SYS_UWORD16 dpll_mul;
+
+             dpll_div=DPLL_READ_DPLL_DIV;
+             dpll_mul=DPLL_READ_DPLL_MUL;
+             src_ratio = (double)(dpll_mul)/(double)(dpll_div+1);              
+          }
+          else // DPLL in bypass mode
+          {
+             SYS_UWORD16 dpll_div = DPLL_BYPASS_DIV;
+             src_ratio= (double)(1)/(double)(dpll_div+1);
+          }
+          break;
+        case 0x01: //VTCX0 selected 
+          src_ratio = 1;
+          break;
+        case 0x03: //CLKIN selected   (external clock)
+          src_ratio = 1;
+          break;
+      }
+      // define the division factor applied to clock source (CLKIN or VTCXO or DPLL)
+      arm_ratio = (clkm_cntl_arm_clk_reg & CLKM_MCLK_DIV) >> 4;
+
+      // check if the 1.5 or 2.5 division factor is enabled
+      arm_mclk_xp5  = clkm_cntl_arm_clk_reg & CLKM_ARM_MCLK_XP5;
+
+      if (arm_mclk_xp5 == 0) // division factor enable for ARM clock ?
+      {
+        if (arm_ratio == 0) 
+          arm_ratio =1; 
+      }
+      else
+        arm_ratio = ((arm_ratio>>1) & 0x0001) == 0 ? 1.5 : 2.5;
+
+
+     #else
+      src_ratio = 1;
+
+      // define the division factor applied to clock source (CLKIN or VTCXO or DPLL)
+      arm_ratio = (clkm_cntl_arm_clk_reg & CLKM_MCLK_DIV) >> 4;
+
+      // check if the 1.5 or 2.5 division factor is enabled
+      arm_mclk_xp5  = clkm_cntl_arm_clk_reg & MASK_ARM_MCLK_1P5;
+
+      if (arm_mclk_xp5 == 1) // division factor enable for ARM clock ?
+        arm_ratio = 1.5;  
+      else
+      {
+        if (arm_ratio == 0)
+          arm_ratio = 4;
+        else 
+          if (arm_ratio == 1 )
+            arm_ratio = 2;
+          else 
+            arm_ratio = 1;
+      }
+
+     #endif
+
+   final_ratio = (src_ratio / (double) arm_ratio);
+
+  }
+  //////////////////////////////////////////
+  //  compute the Flash wait states used  //
+  //////////////////////////////////////////
+
+  #if (CHIPSET == 12)
+     flash_access_size  =  1;
+  #else
+    flash_access_size  =  *((volatile SYS_UWORD16 *) MEM_REG_nCS0);
+  #endif
+  flash_access_size  = (flash_access_size >> 5) & 0x0003; // 0=>8bits, 1=>16 bits, 2 =>32 bits
+
+  // the loop file is compiled in 16 bits it means
+  //    flash 8  bits => 2 loads for 1 16 bits assembler instruction
+  //    flash 16 bits => 1 loads for 1 16 bits assembler instruction
+  //    flash/internal RAM 32 bits => 1 loads for 1 16 bits assembler instruction (ARM bus 16 bits !!)
+  
+  // !!!!!!!!! be careful: if this file is compile in 32 bits, change these 2 lines here after !!!
+  if (flash_access_size == 0) flash_access_size = 2;
+  else                        flash_access_size = 1;
+
+  #if (CHIPSET == 12)
+    /*
+     *  loop move to run in internal memory, due to page mode in external memory
+     */
+    flash_wait_state  =  0;
+  #else
+    flash_wait_state  =  *((volatile SYS_UWORD16 *) MEM_REG_nCS0);
+    flash_wait_state &=  0x001F;
+  #endif
+
+  //////////////////////////////////////
+  //  compute the length of the loop  //
+  //////////////////////////////////////
+
+  // Number of flash cycles for the assembler loop
+  nbr = NBR_CYCLES_IN_LOOP;
+
+  // Number of ARM cycles for the assembler loop
+  nbr = nbr * (flash_wait_state + 1) * (flash_access_size);
+
+  // time for the assembler loop (unit nanoseconds: 10E-9)
+  arm_clock = final_ratio * 13; // ARM clock in Mhz 
+  ratio_wait_loop = (SYS_UWORD32)((nbr*1000) / arm_clock);
+#endif
+}
+
+#if (CHIPSET != 12)
+
+/*-------------------------------------------------------*/ 
+/* wait_ARM_cycles()                                     */
+/*-------------------------------------------------------*/
+/*                                                       */
+/* Description:                                          */
+/* ------------                                          */
+/* Called when the HardWare needs time to wait.          */
+/* this function wait x cycles and is used with the      */
+/* convert_nanosec_to_cycles() & initialize_wait_loop()  */
+/*                                                       */
+/*  Exemple:  wait 10 micro seconds:                     */
+/*  initialize_wait_loop();                              */
+/*  wait_ARM_cycles(convert_nanosec_to_cycles(10000))    */
+/*                                                       */
+/*  minimum time value with cpt_loop = 0  (estimated)    */
+/*  and C-SAMPLE / flash 6,5Mhz  ~  1,5 micro seconds    */
+/*                                                       */
+/*                                                       */
+/* Be careful : in order to respect the rule about the   */
+/* conversion "time => number of cylcles in this loop"   */
+/* (Cf the functions: convert_nanosec_to_cycles() and    */
+/* initialize_wait_loop() ) respect the following rules: */
+/* This function must be placed in Flash Memory and      */
+/* compiled in 16 bits instructions length               */
+/*-------------------------------------------------------*/
+void wait_ARM_cycles(SYS_UWORD32 cpt_loop) 
+{
+  // C code:
+  // while (cpt_loop -- != 0);
+
+  asm(" CMP       A1, #0");                 
+  asm(" BEQ       END_FUNCTION");           
+
+  asm("LOOP_LINE:        ");                
+  asm(" SUB       A1, A1, #1");
+  asm(" CMP       A1, #0");
+  asm(" BNE       LOOP_LINE");
+
+  asm("END_FUNCTION:        ");  
+} 
+
+#endif /* (CHIPSET != 12)*/