FreeCalypso > hg > leo2moko-debug
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)*/