view src/cs/drivers/drv_core/clkm/clkm.c @ 696:2d310cfce661
targets/*.h: sync with Tourmaline: new preprocessor symbols
CONFIG_TARGET_LEO_RFFE and ABB_SLEEP_RESTRICTION
author |
Mychaela Falconia <falcon@freecalypso.org> |
date |
Wed, 09 Jun 2021 17:05:01 +0000 (2021-06-09) |
parents |
945cf7f506b2 |
children |
|
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)*/