📄 syscon.c
字号:
//=============================================================================// // FILE: syscon_drv.c// // DESCRIPTION: Syscon Driver for VeriSuite// // Copyright(c) Cirrus Logic Corporation, 2002 All Rights Reserved ////=============================================================================#include "vs_types.h"#include "driver_api.h"#include "syscon.h"#include "regs_syscon.h"//=============================================================================// External assembly functions.//=============================================================================extern void FlushICache(void);extern void FlushDCache(void);//=============================================================================// Static function prototypes//=============================================================================static int SetBusClocks(ClockRates PLLClock, FClockDivide FDiv, HClockDivide HDiv, PClockDivide PDiv);static int WriteLockedReg(volatile unsigned int *Addr, unsigned int Value);static int BitSetLockedReg(volatile unsigned int *Addr, unsigned int Mask);static int BitClearLockedReg(volatile unsigned int *Addr, unsigned int Mask);static int SetBusMode(BusMode Mode);static int SetFCLKDiv(FClockDivide FDiv);static int SetHCLKDiv(HClockDivide HDiv);static int SetPCLKDiv(PClockDivide PDiv);//----------------------------------------------------------------------------// GLOBALS//----------------------------------------------------------------------------// // Global used to tell if we have initialized syscon yet.//static int g_Initialized=0;//------------------------------------------------------------------------------// SysconInit//------------------------------------------------------------------------------// Just setup the clocks to a known good state.// Currently FCLK = 128 HCLK = 32//------------------------------------------------------------------------------INT SysconInit(cSyscon * pSyscon){ // // Initialize Function pointers. // pSyscon->SetBusClocks = SetBusClocks; pSyscon->WriteLockedReg = WriteLockedReg; pSyscon->BitSetLockedReg = BitSetLockedReg; pSyscon->BitClearLockedReg = BitClearLockedReg; pSyscon->SetBusMode = SetBusMode; // // Do any initialization for clocks. // if (g_Initialized == 0) { // // Write the clock set 2 register with a USB compatible rate. // PLL2 output is 384000000 // USBDIV should be 8 // SysConCSC->CLKSET2.Value = 0x700cc317; } // // Set the bus mode to asynchronous. // SetBusMode(ASYNC_BUS); return(0);}//-----------------------------------------------------------------------------// SetBusMode//-----------------------------------------------------------------------------// Write a value to a locked register.//-----------------------------------------------------------------------------static int SetBusMode(BusMode Mode){ switch (Mode) { case FAST_BUS: { __asm { mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0xc0000000 mcr p15, 0, r0, c1, c0, 0 } break; } case ASYNC_BUS: { __asm { mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #0xc0000000 mcr p15, 0, r0, c1, c0, 0 } break; } case SYNC_BUS: { __asm { mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0xc0000000 orr r0, r0, #0x40000000 mcr p15, 0, r0, c1, c0, 0 } break; } default: { return(-1); break; } } return(0);}//-----------------------------------------------------------------------------// WriteLockedReg//-----------------------------------------------------------------------------// Write a value to a locked register.//-----------------------------------------------------------------------------static int WriteLockedReg(volatile unsigned int *Addr, unsigned int Value){ SysConCSC->SYSLOCK.Value = 0xaa; *Addr = Value; return(0);}//-----------------------------------------------------------------------------// BitSetLockedReg//-----------------------------------------------------------------------------// Set a bit pattern in a locked register.//-----------------------------------------------------------------------------static int BitSetLockedReg(volatile unsigned int *Addr, unsigned int Mask){ unsigned long Temp; Temp = *Addr; // // Unlock register and set bits. // SysConCSC->SYSLOCK.Value = 0xaa; *Addr = Temp | Mask; return(0);}//-----------------------------------------------------------------------------// BitClearLockedReg//-----------------------------------------------------------------------------// Clear a bit pattern in a locked register.//-----------------------------------------------------------------------------static int BitClearLockedReg(volatile unsigned int *Addr, unsigned int Mask){ unsigned long Temp; Temp = *Addr; // // Unlock register and clear out bits. // SysConCSC->SYSLOCK.Value = 0xaa; *Addr = Temp & (~Mask); return(0);}static unsigned int ClkSet1Values[][2]={ {CLK_EXT, 0x00000000}, // Bypass {CLK_500, 0x0080f45f}, {CLK_490, 0x0080fb59}, {CLK_475, 0x0080ad1b}, {CLK_450, 0x0080ad5e}, {CLK_442, 0x0080abb5}, // MIR compatible Rate MIRDIV 0x203 {CLK_425, 0x0080acbc}, {CLK_400, 0x0080a3d7}, {CLK_375, 0x0080a2d2}, {CLK_368, 0x0080a314}, // MIR compatible Rate MIRDIV 0x202 {CLK_350, 0x0080a336}, {CLK_325, 0x0080b2d7}, {CLK_300, 0x0080b2d9}, {CLK_250, 0x0081f45f}, {CLK_225, 0x0081ad5e}, {CLK_222, 0x0081ebff}, // MIR compatible Rate MIRDIV 0x203 {CLK_210, 0x0081b334}, {CLK_200, 0x0081f297}, {CLK_180, 0x0081db5e}, {CLK_166, 0x0081fa5a}, {CLK_150, 0x0081b2d9}, {CLK_125, 0x0082f45f}, {CLK_100, 0x0082f297}, {CLK_75 , 0x0082b2d9}};#define MAX_CLK_SET (sizeof(ClkSet1Values)/(sizeof(unsigned int)<<1)) //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// Sets up clocks user specified FCLK and HCLKDIV.//-----------------------------------------------------------------------------static int SetBusClocks(ClockRates PLLClock, FClockDivide FDiv, HClockDivide HDiv, PClockDivide PDiv){ int i; unsigned int ClkSet1; if(PLLClock != CLK_NOCHANGE) { // // Check if the Clock rate is supported. // for (i=0; i< MAX_CLK_SET; i++) { if (PLLClock == ClkSet1Values[i][0]) { break; } } // // Failed to find a "good" value for the clocks. // if (i == MAX_CLK_SET) { return(-1); } // // Get the base PLL Value. // ClkSet1 = ClkSet1Values[i][1]; ClkSet1 |= (FDiv << SYSCON_CLKSET1_FCLKDIV_SHIFT); ClkSet1 |= (HDiv << SYSCON_CLKSET1_HCLKDIV_SHIFT); ClkSet1 |= (PDiv << SYSCON_CLKSET1_PCLKDIV_SHIFT); } else { if(FDiv !=FCLK_NOCHANGE) { ClkSet1 = SetFCLKDiv(FDiv); } if(HDiv !=HCLK_NOCHANGE) { ClkSet1 = SetHCLKDiv(HDiv); } if(PDiv !=PCLK_NOCHANGE) { ClkSet1 = SetPCLKDiv(PDiv); } } // // Write the clock set register which will cause the part to sleep for bit. // SysConCSC->CLKSET1.Value = ClkSet1; // // Now flush the pipe because we are supposed to.. // __asm { nop nop nop nop nop } return(0);}static int SetFCLKDiv(FClockDivide FDiv){ unsigned int ClkSet1; ClkSet1 = SysConCSC->CLKSET1.Value; ClkSet1 = ClkSet1 & 0xF1FFFFFF; // ClkSet1 |= (FDiv << SYSCON_CLKSET1_FCLKDIV_SHIFT); return(ClkSet1);}static int SetHCLKDiv(HClockDivide HDiv){ unsigned int ClkSet1; ClkSet1 = SysConCSC->CLKSET1.Value; ClkSet1 = ClkSet1 & 0xFF8FFFFF; // ClkSet1 |= (HDiv << SYSCON_CLKSET1_HCLKDIV_SHIFT); return(ClkSet1);}static int SetPCLKDiv(PClockDivide PDiv){ unsigned int ClkSet1; ClkSet1 = SysConCSC->CLKSET1.Value; ClkSet1 = ClkSet1 & 0xFFF3FFFF; // ClkSet1 |= (PDiv << SYSCON_CLKSET1_PCLKDIV_SHIFT); return(ClkSet1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -