⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proc.c

📁 使用Linux ARM GCC编译器来编译
💻 C
字号:
/* * vivi/arch/s3c2410/proc.c * * Copyright (C) 2002 MIZI Research, Inc. * * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *  * Author: Janghoon Lyu <nandy@mizi.com> * Date  : $Date: 2004/02/04 06:22:25 $ * * $Revision: 1.1.1.1 $ * $Id: proc.c,v 1.1.1.1 2004/02/04 06:22:25 laputa Exp $ * * * History * * 2002-07-12: Janghoon Lyu <nandy@mizi.com> *    - Initial code * */#include "config.h"#include "machine.h"#include "mmu.h"#include "command.h"#include "vivi_string.h"#include "printk.h"#include "priv_data.h"#include <types.h>#include <string.h>#define GET_PCLK		0#define GET_HCLK		1struct cpu_clk_t {	unsigned long clock;	unsigned long mdiv;	unsigned long pdiv;	unsigned long sdiv;};struct mem_clk_t {	unsigned long clock;	unsigned long bankcon6;	unsigned long bankcon7;	unsigned long refresh;};static int timer_load_val = 0;/* macro to read the 16 bit timer */static inline ulong READ_TIMER(void){	return (TCNTO4 & 0xffff);}static ulong timestamp;static ulong lastdec;/* * cpu_clk = FIN  */struct cpu_clk_t s3c2410_clks[] = {	/*	mdiv	pdiv	sdiv */	{  50,	0x5c,	0x4,	0x0 },	{ 200,	0x5c,	0x4,	0x1 },	{ 203,	 0x3,	0x4,	0x1 },	/* not tested */	{ 202,	0xa1,	0x3,	0x1 },  /* not tested */	{ 284,	0x86,	0x1,	0x1 },	{ 290,	0x89,	0x1,	0x1 },	{ 400,	0x5c,	0x1,	0x1 },	{ 474,	0x96,	0x2,	0x0 },	{ 508,	0x77,	0x1,	0x0 },	{ 533,	0xd6,	0x3,	0x0 },	{   0,	   0,	  0,	  0 }};/* * Memory Clock Change  */struct mem_clk_t s3c2410_memclks[] = {	/*FClK  Bcon6       Bcon7        Ref */	{ 284,	0x00018005, 0x00018005, 0x009c0379},	{ 290,	0x00018005, 0x00018005, 0x009c0379},	{ 400,	0x00018005, 0x00018005, 0x009c0379},	{   0,	   0,	  0,	  0 }};static inline unsigned longcal_bus_clk(unsigned long cpu_clk, unsigned long ratio, int who){	unsigned long hclk = 0,pclk = 0;	switch( (ratio&0x6) >> 1 ) {		case 0:  			hclk = cpu_clk;			break;		case 1:			hclk = cpu_clk/2;			break;		case 2:			hclk = cpu_clk/4;			break;		case 3:			hclk = cpu_clk/3;			break;	}	switch ( ratio&0x1) {		case 0:			pclk = hclk;			break;		case 1:			pclk = hclk/2;			break;	}	return ( who ? hclk: pclk );}/*  * Note: this code is not tested. * * set_cpu_clk(): *   clk: cpu clock to set. unit is mega hertz  *   ratio:  */static int set_cpu_clk(unsigned long clk){	struct cpu_clk_t *clks = s3c2410_clks;	while (clks->clock != 0) {		if (clk == clks->clock)		    break;		clks++;	}	if (clks->clock == 0) {		printk("Can not find cpu clock table\n");		return -2;	}		MPLLCON = ((clks->mdiv << 12) | (clks->pdiv << 4) | (clks->sdiv));	return 0;}static intchange_memctl_regs(unsigned long clk) {	struct mem_clk_t * memclks = s3c2410_memclks;	while ( memclks->clock !=0) {		if (clk == memclks->clock)			break;		memclks++;	}	if (memclks->clock == 0) {		printk("Can not find mem  clock table\n");		return -2;	}	BANKCON6 = memclks->bankcon6;	BANKCON7 = memclks->bankcon7;	REFRESH  = memclks->refresh;	return 0;}#define REFRESH_PERIOD 78  /* 7.8us */static intchange_refresh(unsigned long hclk){	hclk = hclk /10000000;	REFRESH = (REFRESH & ~0x7ff) | (2049-(unsigned int)(hclk * REFRESH_PERIOD));	return 0;}/* * cpu clock = (((mdiv + 8) * FIN) / ((pdiv + 2) * (1 << sdiv))) *  FIN = Input Frequency (to CPU) */static inline unsigned longget_cpu_clk(void){	unsigned long val = MPLLCON;	return ((2*(GET_MDIV(val) + 8) * FIN) / \		((GET_PDIV(val) + 2) * (1 << GET_SDIV(val))));}static unsigned longget_bus_clk(int who){	unsigned long cpu_clk = get_cpu_clk();	unsigned long ratio = CLKDIVN;	return (cal_bus_clk(cpu_clk, ratio, who));}static void print_cpu_info(void){	long armrev = 0;	unsigned long mpll = MPLLCON;		__asm__("mrc	p15, 0, %0, c0, c0, 0" : "=r" (armrev));	printk("\nProcessor Information (Revision: 0x%08lx)\n", armrev);	printk("--------------------------------------------\n");	printk("Processor clock: %d Hz\n", get_cpu_clk());	printk("AHB bus clock  : %d Hz\n", get_bus_clk(GET_HCLK));	printk("APB bus clock  : %d Hz\n", get_bus_clk(GET_PCLK));	printk("\nRegister values\n");	printk("MPLLCON: 0x%08lx", mpll);	printk("  (MDIV: 0x%04x, PDIV: 0x%02x, SDIV: 0x%02x)\n",		GET_MDIV(mpll), GET_PDIV(mpll), GET_SDIV(mpll));	printk("CLKDIVN: 0x%08lx\n\n", CLKDIVN);}/* * A clock is the PCLK clock. */static void change_baudrate(unsigned long clock){	unsigned long baudrate;	int ret;	baudrate = get_param_value("baudrate", &ret);	if (ret) {		printk("There is no 'baudrate' parameter\n");		return;	}	#if defined(CONFIG_SERIAL_UART0)	UBRDIV0 = ((clock / (baudrate * 16)) - 1);#elif defined(CONFIG_SERIAL_UART1)	UBRDIV1 = ((clock / (baudrate * 16)) - 1);#endif}void change_clk_divider(int divider ){	int hdivn =2, pdivn = 0;	switch (divider) {		case 111:hdivn = 1; pdivn = 1; break;		case 122:hdivn = 2; pdivn = 2; break;		case 124:hdivn = 2; pdivn = 4; break;		case 133:hdivn = 3; pdivn = 3; break;		case 136:hdivn = 3; pdivn = 6; break;		case 144:hdivn = 4; pdivn = 4; break;		case 148:hdivn = 8; pdivn = 8; break;		default:			 printk(" Wrong divider %d \n");	}	//if ( hdivn !=0 ) 	//	MMU_SetAsyncBusMode();//	else//		MMU_SetFastBusMode();}/* * change cpu clock and bus clock * Changed By SW.LEE * */int change_sys_clks(unsigned long cpu_clk, unsigned long ratio){	int ret = 0;	printk("CPU Clock Change From %d Mhz  To %d Mhz \n",				get_cpu_clk()/1000000,cpu_clk);	if (ratio > 7) {		printk("Wrong Clock Ration %d \n",ratio);	}	else	{		CLKDIVN = ratio;	}		ret = set_cpu_clk(cpu_clk);	if (ret) return -1;	//	change_memctl_regs(cpu_clk);	change_refresh(get_bus_clk(GET_HCLK)); 	change_baudrate(get_bus_clk(GET_PCLK));	{ 		/* To avoid showing broken characters to console */		int delay;		for (delay =0; delay < 0x10000; delay ++)			;	}	return 0;}/* * change a uart baudrate  */void change_uart_baudrate(void){	change_baudrate(get_bus_clk(GET_PCLK));}static inline int get_clk_divider(void){	int val = GET_DIVIDER_TIMER4(TCFG1);	return (2 << (val));}unsigned long get_clock_tick_rate(void){	unsigned long prescale = GET_PRESCALE_TIMER4(TCFG0);	unsigned long divider = (unsigned long)get_clk_divider();	unsigned freq = get_bus_clk(GET_PCLK);	if (!divider)		return 0;	return (freq / (prescale + 1) / divider);}ulong get_timer_masked (void){	ulong now = READ_TIMER();	if (lastdec >= now) {		/* normal mode */		timestamp += lastdec - now;	} else {		/* we have an overflow ... */		timestamp += lastdec + timer_load_val - now;	}	lastdec = now;	return timestamp;}ulong get_timer (ulong base){	return get_timer_masked () - base;}static void time_wait(unsigned int sec, int unit){	unsigned long ticks, clock_tick_rate;	/* clear interupt bit */	SRCPND |= INT_TIMER4;	INTPND |= INT_TIMER4;	INTMSK &= ~INT_TIMER4;			/* enable timer 4 interrupt */	clock_tick_rate = get_clock_tick_rate();	if (clock_tick_rate == 0) {		printk("Can not get a clock tick rate\n");		return;	}	if (unit == 0) {		ticks = (clock_tick_rate * (sec)) / (1000 * 1000);	} else {		ticks = (clock_tick_rate * (sec)) / (1000);	}	TCNTB4 = ticks;	TCON = (TCON_4_UPDATE | COUNT_4_OFF);	/* load counter value */	TCON = (COUNT_4_ON);			/* start timer */	while (!(INTPND & INT_TIMER4)) ;		TCON = (COUNT_4_OFF);			/* stop timer */	INTMSK |= INT_TIMER4;			/* mask timer 4 interrupt */	/* clear interupt bit */	SRCPND |= INT_TIMER4;	INTPND |= INT_TIMER4;}static voidtime_delay(unsigned int sec, int unit){	/*unsigned int remain = sec;	while (remain > 0) {		if (remain > 40) {			sec = 40;		} else {			sec = remain;		}		time_wait(sec, unit);		remain -= sec;	}*/	ulong end;	ulong start = get_timer(0);	if (unit) {	    end = start + (sec * timer_load_val)/(10);	} else {	    if (sec<1000) {	        end = start + (sec * timer_load_val)/(10*1000);	    } else {	        end = start + (sec/1000 * timer_load_val)/10;	    }	}	while (get_timer_masked() < end)		/*NOP*/;}void arch_udelay(unsigned int usec){	time_delay(usec, 0);}void arch_mdelay(unsigned int msec){	time_delay(msec, 1);}void init_time(void){	//TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0));		/* use PWM Timer 4 because it has no output */	/* prescaler for Timer 4 is 16 */	TCFG0 = 0x0f00;	//if (timer_load_val == 0)	{		/*		 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2		 * (default) and prescaler = 16. Should be 10390		 * @33.25MHz and 15625 @ 50 MHz		 */		timer_load_val = get_bus_clk(GET_PCLK)/(2 * 16 * 100);	}		/* load value for 10 ms timeout */	lastdec = TCNTB4 = timer_load_val;	/* auto load, manual update of Timer 4 */	//TCON = (TCON & ~0x0700000) | 0x600000;	/* auto load, start Timer 4 */	//TCON = (TCON & ~0x0700000) | 0x500000;	TCON = (TCON_4_AUTO | TCON_4_UPDATE | COUNT_4_OFF);	/* load counter value */	TCON = (TCON_4_AUTO | COUNT_4_ON);			/* start timer */		timestamp = 0;}/* * Perform a soft reset of the system.  Put the CPU into the * same state as it would be if it had been reset, and branch * to what would be the reset vector. * * loc: location to jump to for soft reset */void processor_reset(unsigned long loc){	cache_clean_invalidate();	tlb_invalidate();__asm__(	"mov	ip, #0\n"	"mcr	p15, 0, ip, c7, c7, 0\n"	/* invalidate I,D caches */	"mcr	p15, 0, ip, c7, c10, 4\n"	/* drain WB */	"mcr	p15, 0, ip, c8, c7, 0\n"	/* invalidate I & D TLBs */	"mrc	p15, 0, ip, c1, c0, 0\n"	/* ctrl register */	"bic	ip, ip, #0x000f\n"		/* ............wcam */	"bic	ip, ip, #0x1100\n"		/* ...i...s........ */	"mcr	p15, 0, ip, c1, c0, 0\n"	/* ctrl register */	"mov	pc, %0\n"	: : "r" (loc) );}void command_reset(int argc, const char **argv){	processor_reset(0);}user_command_t reset_cmd = {	"reset",	command_reset,	NULL,	"reset\t\t\t\t-- Reset the system"};static void display_cpu_help(void){	printk("Usage:\n");	printk("cpu info\t\t\t-- Display cpu informatin\n");	printk("cpu set <clock> <ratio>\t\t-- Change cpu clock and bus clock\n");}static void command_cpu(int argc, const char **argv){	switch (argc) {	case 1:		goto print_usage;		break;	case 2:		if (strncmp("help", argv[1], 4) == 0) {			display_cpu_help();			break;		}		if (strncmp("info", argv[1], 4) == 0) {			print_cpu_info();			break;		}		goto print_usage;	case 4:		if (strncmp("set", argv[1], 3) == 0) {			unsigned long clock = strtoul(argv[2], NULL, 0, NULL);			unsigned long ratio = strtoul(argv[3], NULL, 0, NULL);			int ret = 0;			ret = change_sys_clks(clock, ratio);			if (ret)				printk("Failed. Can not change cpu clock\n");			else				printk("OK\n");			break;		}	default:		goto print_usage;		break;	}	return;print_usage:	display_cpu_help();}user_command_t cpu_cmd = {	"cpu",	command_cpu,	NULL,	"cpu [{cmds}] \t\t\t-- Manage cpu clocks"};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -