FreeCalypso > hg > fc-tourmaline
view src/cs/drivers/drv_core/clkm/clkm.c @ 100:609eb8031c17
mmiBook*.h: bogotab fixes
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 08 Nov 2020 22:53:20 +0000 |
parents | 4e78acac3d88 |
children |
line wrap: on
line source
/****************************************************************************** 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)*/