Files
commandergenius/project/jni/application/quake/source/cpu.c

157 lines
4.1 KiB
C

/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include "cpu.h"
/* Define this to the CPU frequency */
#define CPU_FREQ 336000000 /* CPU clock: 336 MHz */
#define CFG_EXTAL 12000000 /* EXT clock: 12 Mhz */
// SDRAM Timings, unit: ns
#define SDRAM_TRAS 45 /* RAS# Active Time */
#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
#define SDRAM_TPC 20 /* RAS# Precharge Time */
#define SDRAM_TRWL 7 /* Write Latency Time */
#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
//#define SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */
#include "jz4740.h"
static unsigned long jz_dev=0;
static volatile unsigned long *jz_cpmregl, *jz_emcregl;
volatile unsigned short *jz_emcregs;
static inline int sdram_convert(unsigned int pllin,unsigned int *sdram_freq)
{
register unsigned int ns, tmp;
ns = 1000000000 / pllin;
/* Set refresh registers */
tmp = SDRAM_TREF/ns;
tmp = tmp/64 + 1;
if (tmp > 0xff) tmp = 0xff;
*sdram_freq = tmp;
return 0;
}
static int
pll_init(unsigned int clock)
{
register unsigned int cfcr, plcr1;
unsigned int sdramclock = 0;
int n2FR[33] = {
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
9
};
//int div[5] = {1, 4, 4, 4, 4}; /* divisors of I:S:P:L:M */
int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
int nf, pllout2;
cfcr = CPM_CPCCR_CLKOEN |
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
(n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
pllout2 = (cfcr & CPM_CPCCR_PCS) ? clock : (clock / 2);
/* Init UHC clock */
// REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
jz_cpmregl[0x6C>>2] = pllout2 / 48000000 - 1;
nf = clock * 2 / CFG_EXTAL;
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
CPM_CPPCR_PLLEN; /* enable PLL */
/* init PLL */
// REG_CPM_CPCCR = cfcr;
// REG_CPM_CPPCR = plcr1;
jz_cpmregl[0] = cfcr;
jz_cpmregl[0x10>>2] = plcr1;
sdram_convert(clock,&sdramclock);
if (sdramclock > 0) {
// REG_EMC_RTCOR = sdramclock;
// REG_EMC_RTCNT = sdramclock;
jz_emcregs[0x8C>>1] = sdramclock;
jz_emcregs[0x88>>1] = sdramclock;
}
}
void
cpu_init()
{
jz_dev = open("/dev/mem", O_RDWR);
jz_cpmregl=(unsigned long *)mmap(0, 0x80, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x10000000);
jz_emcregl=(unsigned long *)mmap(0, 0x90, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x13010000);
jz_emcregs=(unsigned short *)jz_emcregl;
}
void
cpu_deinit()
{
cpu_set_clock( GP2X_MAX_CLOCK );
munmap((void *)jz_cpmregl, 0x80);
munmap((void *)jz_emcregl, 0x90);
close(jz_dev);
// fcloseall();
sync();
}
static void
loc_set_clock(int clock_in_mhz )
{
if (clock_in_mhz >= GP2X_MIN_CLOCK && clock_in_mhz <= GP2X_MAX_CLOCK) {
pll_init( clock_in_mhz * 1000000 );
}
}
static unsigned int loc_clock_in_mhz = GP2X_DEF_CLOCK;
void
cpu_set_clock(unsigned int clock_in_mhz)
{
if (clock_in_mhz == loc_clock_in_mhz) return;
loc_clock_in_mhz = clock_in_mhz;
loc_set_clock(clock_in_mhz);
return;
}
unsigned int
cpu_get_clock()
{
return loc_clock_in_mhz;
}