📄 lh7a404_csc_driver.c
字号:
/***********************************************************************
* $Workfile: lh7a404_csc_driver.c $
* $Revision: 1.4 $
* $Author: WellsK $
* $Date: Apr 15 2004 15:13:24 $
*
* Project: LH7A404 CSC driver
*
* Description:
* This file contains driver support for the CSC module on the
* LH7A404
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/source/lh7a404_csc_driver.c-arc $
*
* Rev 1.4 Apr 15 2004 15:13:24 WellsK
* Switched inline assembly to IAR instrinsic functions to improve
* portability among different versioned IAR toolchains.
*
* Rev 1.3 Apr 12 2004 16:57:24 WellsK
* Added support for IAR toolchain.
*
* Rev 1.2 Jan 05 2004 11:20:36 WellsK
* Modified the csc_clock_set function - it will now switch into
* FASTBUS mode prior to changing to any clock speed and then
* switch into SYNC mode if the bus divider is not 1.
*
* Rev 1.1 Sep 02 2003 15:11:24 WellsK
* Corrected an operator precedence problem with the
* csc_set_pgmclk_divisor() function.
*
* Rev 1.0 Jul 01 2003 11:06:20 WellsK
* Initial revision.
*
*
***********************************************************************
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
**********************************************************************/
#include "lh7a404_csc_driver.h"
#include "abl_arm922t_arch.h"
#ifdef __ICCARM__
#include "inarm.h"
#endif
/***********************************************************************
* CSC driver local data
**********************************************************************/
/* Maps field bit locations in CSC PWRSR status to csc_status_types */
const INT_32 pwrsr_bit_index[CHIPMAN + 1] = {0, 6, 7, 8, 9, 10, 11,
12, 13, 14, 16, 24};
/* Maps field sizes in CSC PWRSR status to csc_status_types */
const INT_32 pwrsr_bit_size[CHIPMAN + 1] = {6, 1, 1, 1, 1, 1, 1, 1,
1, 1, 8, 8};
#ifdef __ICCARM__
/* New clock mode flags for IAR compiler only */
static volatile UNS_32 new_clk_mode;
#endif
/***********************************************************************
* CSC driver private functions and macros
**********************************************************************/
#ifdef __ghs__
/* 5 inline assmbly NOPS used with GHS compilers */
asm void nops5(void)
{
NOP
NOP
NOP
NOP
NOP
}
/* Bus mode change inline assembly code used with GHS compilers */
asm void change_clkbus_mode(UNS_32 clk_mode, UNS_32 bus_mode)
{
%con clk_mode %con bus_mode
STMFD [sp]!, {r1-r2}
MRC ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
MOV r2, #clk_mode
AND r1, r1, #bus_mode
ORR r1, r1, r2
MCR ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
LDMFD [sp]!, {r1-r2}
%con clk_mode %reg bus_mode
STMFD [sp]!, {r1-r2}
MRC ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
MOV r2, #clk_mode
AND r1, r1, bus_mode
ORR r1, r1, r2
MCR ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
LDMFD [sp]!, {r1-r2}
%reg clk_mode %con bus_mode
STMFD [sp]!, {r1-r2}
MRC ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
MOV r2, clk_mode
AND r1, r1, #bus_mode
ORR r1, r1, r2
MCR ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
LDMFD [sp]!, {r1-r2}
%reg clk_mode %reg bus_mode
STMFD [sp]!, {r1-r2}
MRC ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
MOV r2, clk_mode
AND r1, r1, bus_mode
ORR r1, r1, r2
MCR ARM922T_MMU_CP, 0, r1, ARM922T_MMU_REG_CONTROL, c0, 0
LDMFD [sp]!, {r1-r2}
%error
}
#endif
/***********************************************************************
*
* Function: csc_get_cpuclk
*
* Purpose: Get the CPU clock speed in Hz
*
* Processing:
* Read the programmed PLL frequency settings from the CLKSET
* register. Mask out the main PLL components and compute the
* frequency from the masked components. Return the computed
* frequency.
*
* Parameters: None
*
* Outputs: None
*
* Returns: The CPU clock speed in Hz
*
* Notes: None
*
**********************************************************************/
UNS_32 csc_get_cpuclk(void)
{
UNS_32 m1, m2, p, ps;
register UNS_32 tmp;
/* Get clock values from CLKSET register */
tmp = CLKSC->clkset;
/* Get programmed PLL values */
m1 = (tmp >> 7) & 0x0000000F;
m2 = (tmp >> 11) & 0x000001F;
p = (tmp >> 2) & 0x0000001F;
ps = (tmp >> 18) & 0x00000003;
/* Compute CPU clock speed */
tmp = (((((m2 + 2) * CLOCK_MAINOSC) >> ps) / (p + 2)) * (m1 + 2));
return tmp;
}
/***********************************************************************
*
* Function: csc_get_hclk
*
* Purpose: Get the AHB bus clock speed in Hz
*
* Processing:
* Get the CPU clock speed by calling the csc_get_cpuclk function.
* Mask out the AHB bus divider value from the CLKSET register.
* Compute the AHB bus speed by dividing the CPU clock frequency
* by the masked AHB bus divider + 1. Return the computed AHB bus
* frequency.
*
* Parameters: None
*
* Outputs: None
*
* Returns: The AHB bus clock speed in Hz
*
* Notes: None
*
**********************************************************************/
UNS_32 csc_get_hclk(void)
{
UNS_32 hclkdiv;
/* Get HCLK divider value from CLKSET register */
hclkdiv = CLKSC->clkset & 0x00000003;
return (csc_get_cpuclk() / (hclkdiv + 1));
}
/***********************************************************************
*
* Function: csc_get_pclk
*
* Purpose: Get the APB bus clock speed in Hz
*
* Processing:
* Get the AHB bus speed by calling the csc_get_hclk function.
* Mask out the APB bus divider value from the CLKSET register.
* Compute the APB bus speed by dividing the AHB bus frequency
* by 1 shifted left by the (APB bus divider + 1). Return the
* computed APB bus frequency.
*
* Parameters: None
*
* Outputs: None
*
* Returns: The APB bus clock speed in Hz
*
* Notes: None
*
**********************************************************************/
UNS_32 csc_get_pclk(void)
{
UNS_32 pclkdiv;
/* Get HCLK divider value from CLKSET register */
pclkdiv = 1 << (((CLKSC->clkset & 0x30000) >> 16) + 1);
return (csc_get_hclk() / pclkdiv);
}
/***********************************************************************
* CSC driver public functions
**********************************************************************/
/***********************************************************************
*
* Function: csc_enter_low_power_state
*
* Purpose: Enter the chip low power state
*
* Processing:
* If the passed argument was HALT, than check the status of the
* DMA system. If any DMA channels are active, then enable (or
* re-enable the static memory controller clock). If all of the DMA
* channels are inactive, then disable the static memory controller
* clock to save more power. Go into halt mode by reading the CSC
* halt register. After halt, perform five NOP commands to clear
* the CPU pipeline. If the passed argument was STANDBY, go into
* standby mode by reading the CSC standby register. After standby,
* perform five NOP commands to clear the CPU pipeline. Restore the
* original state (with or without the SMCROM bit) to the CLKSET
* register in the CSC.
*
* Parameters:
* state : Must be STANDBY or HALT
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* If the LCD frame buffer is not located in SDRAM or internal
* memory, the HALT function may cause system lockup in the static
* memory controller clock is disabled. Use with care or change
* this function to *not* disable the static memory controller
* clock when placed into HALT mode.
*
**********************************************************************/
void csc_enter_low_power_state(CSC_POWER_T state)
{
volatile UNS_32 tmp, oldcscstate;
volatile UNS_32 *tmpptr;
if (state == HALT)
{
oldcscstate = CLKSC->clkset;
if ((CLKSC->pwrcnt & CSC_PWRCNT_DMA_ALL) != 0)
{
csc_clock_set(oldcscstate & ~CSC_SMCROM);
}
else
{
csc_clock_set(oldcscstate | CSC_SMCROM);
}
/* System will go into halt state */
tmpptr = &CLKSC->halt;
}
else
{
/* System will go into standby state */
tmpptr = &CLKSC->stby;
}
/* Go into halt or standby state by reading the register */
tmp = *tmpptr ;
/* NOPs to clear the pipeline after coming out of standby */
#ifdef __ICCARM__
__no_operation();
__no_operation();
__no_operation();
__no_operation();
__no_operation();
#endif
#ifdef __GNUC__
asm ("NOP");
asm ("NOP");
asm ("NOP");
asm ("NOP");
asm ("NOP");
#endif
#ifdef __ghs__
nops5();
#endif
#ifdef __arm
__asm
{
NOP
NOP
NOP
NOP
NOP
}
#endif
/* Restore the original clock state */
csc_clock_set(oldcscstate);
}
/***********************************************************************
*
* Function: csc_clear_interrupt
*
* Purpose: Clear a CSC interrupt
*
* Processing:
* Based on the passed interrupts argument, clear the battery low,
* media change, or 64Hz tick interrupt.
*
* Parameters:
* interrupts : Must be BATTLOWINT, MEDCHGINT, or TICKINT
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void csc_clear_interrupt(CSC_INT_CLEAR_T interrupts)
{
switch (interrupts)
{
case BATTLOWINT:
/* Clear battery low interrupt */
CLKSC->bleoi = 0x0;
break;
case MEDCHGINT:
/* Clear media change interrupt */
CLKSC->mceoi = 0x0;
break;
case TICKINT:
/* Clear 64Hz tick interrupt */
CLKSC->teoi = 0x0;
break;
default:
break;
}
}
/***********************************************************************
*
* Function: csc_clear_misc_status
*
* Purpose: Clear misc CSC status bits
*
* Processing:
* Write to the CSC STFCLR register to clear the miscellaneous
* status bits.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void csc_clear_misc_status(void)
{
/* Clear new battery, user reset, power fail, and cold start status
flag */
CLKSC->stfclr = 0x0;
}
/***********************************************************************
*
* Function: csc_get_status
*
* Purpose: Return a status value from the PWRSR register in the CSC
*
* Processing:
* Based on the passed argument, read the CSC status register and
* shift the value by the appropriate number of bits and then
* mask off the most significant bits to leave the desired bit(s).
*
* Parameters:
* status : Must be an enumeration of type CSC_STATUS_T
*
* Outputs: None
*
* Returns: The value of the bitfield for the selected status
*
* Notes: None
*
**********************************************************************/
INT_32 csc_get_status(CSC_STATUS_T status)
{
/* Read PWRSR status register, shift, mask, and return to caller */
return ((CLKSC->pwrsr >> pwrsr_bit_index[status]) &
_BITMASK(pwrsr_bit_size[status]));
}
/***********************************************************************
*
* Function: csc_get_clock
*
* Purpose: Get CPU, AHB Bus, or APB bus clock speed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -