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

📄 proc.c

📁 SMDK2440 boot code, base on vivi
💻 C
字号:
/* * vivi/arch/s3c2410/proc.c: 橇肺技辑窍绊 包访等 仇甸 * * Copyright (C) 2002-2004 MIZI Research, Inc. * All Rights Reserved. * * Author: Janghoon Lyu <nandy@mizi.com> * Date  : $Date: 2004/04/06 02:35:46 $ * * $Revision: 1.17 $ * $Id: proc.c,v 1.17 2004/04/06 02:35:46 nandy 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 <vstring.h>#include <param.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;};/* * cpu_clk = FIN  */struct cpu_clk_t s3c2410_clks[] = {	/*	mdiv	sdiv	pdiv */	{  33,  0x52,   0x2,    0x3 },	{  45,  0x52,   0x1,    0x3 },	{  50,  0xa1,   0x3,    0x3 },	{  48,  0x28,   0x1,    0x2 },	{  56,  0x8e,   0x2,    0x3 },	{  67,  0x52,   0x2,    0x2 },	{  79,  0x47,   0x1,    0x2 },	{  84,  0x69,   0x2,    0x2 },	{  90,  0x70,   0x2,    0x2 },	{ 101,	0x74,	0x2,	0x2 },	{ 113,	0x69,	0x1,	0x2 },	{ 118,	0x96,	0x2,	0x2 },	{ 124,  0x74,   0x1,    0x2 },	{ 135,  0x52,   0x2,    0x1 },	{ 147,  0x5a,   0x2,    0x1 },	{ 152,  0x44,   0x1,    0x1 },	{ 158,  0x47,   0x1,    0x1 },	{ 170,  0x4d,   0x1,    0x1 },	{ 180,  0x52,   0x1,    0x1 },	{ 186,  0x55,   0x1,    0x1 },	{ 192,  0x58,   0x1,    0x1 },	{ 202,  0xa1,   0x3,    0x1 },	{  51,  0x5c,   0x4,    0x2 },	{ 100,  0x5c,   0x4,    0x1 },	{ 200,	0x5c,	0x4,	0x0 },	{ 203,	 0x3,	0x4,	0x1 },	/* not tested */	{   0,	   0,	  0,	  0 }};static inline unsigned longcal_bus_clk(unsigned long cpu_clk, unsigned long ratio, int who){	if (!who) {	/* PCLK */		switch (ratio) {			case 0:				return (cpu_clk);			case 1:			case 2:				return (cpu_clk/2);			case 3:				return (cpu_clk/4);			default:				return 0;		}	} else {	/* HCLK */		switch (ratio) {			case 0:			case 1:				return (cpu_clk);			case 2:			case 3:				return (cpu_clk/2);			default:				return 0;		}	}}/*  * 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;}/* * 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 (((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;	if (get_param_ulong("baudrate", &baudrate)) {		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);#elif defined(CONFIG_SERIAL_UART2)	UBRDIV2 = ((clock / (baudrate * 16)) - 1);#endif}/* * change cpu clock and bus clock */intchange_sys_clks(unsigned long cpu_clk, unsigned long ratio){	int ret = 0;	/* Step 1: change a cpu clock */	ret = set_cpu_clk(cpu_clk);	if (ret) 		return -1;		/* Step 2: change bus clocks */	if (ratio > 3 || ratio < 0)		return -1;	CLKDIVN = ratio;	/* Step 3: change a memory clock */	/* change_memctl_regs(); */	/* Step 4: change a uart baudrate */	change_baudrate(get_bus_clk(GET_PCLK));	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);}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);	}	TCON &= ~(TCON_4_ONOFF | TCON_4_UPDATE | TCON_4_AUTO);	TCNTB4 = ticks;	TCON |= (TCON_4_UPDATE | COUNT_4_OFF);	/* load counter value */	TCON &= ~(TCON_4_UPDATE);	TCON |= (COUNT_4_ON);			/* start timer */	while (!(INTPND & INT_TIMER4)) ;		TCON &= ~(COUNT_4_ON);			/* 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;	}}void arch_udelay(unsigned int usec){	time_delay(usec, 0);}void arch_mdelay(unsigned int msec){	time_delay(msec, 1);}#ifdef CONFIG_NETunsigned long timestamp = 0;unsigned long lastdec;unsigned long arch_get_time_sec(unsigned long base){	unsigned long now = TCNTO3;	if (lastdec >= now) {		timestamp += lastdec - now;		} else {		timestamp += lastdec + 0x0000ffff - now;		}	lastdec = now;	return (timestamp - base);}unsigned intarch_get_rand_seed(void){	return TCNTO3;}#endif /* CONFIG_NET */void init_time(void){	TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0));#ifdef CONFIG_NET	/* check GPB3 is TOUT3 or not */	if ((GPBCON & 0x000000c0) == 0x00000080) {		printk("GPB3 was configured as TOUT3.\n");	} else {		/* disable timer 3 interrupt */		INTMSK |= INT_TIMER3;		/* stop timer 3 */		TCON &= ~(TCON_3_AUTO | TCON_3_INVERT | TCON_3_MAN | TCON_3_ONOFF);		TCNTB3 = 0x0000ffff;		lastdec = 0x0000ffff;		TCON |= TIMER3_MANUP;		TCON &= ~TIMER3_MANUP;	    TCON |= TIMER3_ATLOAD_ON;		/* start timer 3 */		TCON |= TIMER3_ON;	}#endif /* CONFIG_NET */}/** * Purpose: reset processor's resource */void reset_proc_res(void){	/* disable timer 3 interrupt */	INTMSK |= INT_TIMER3;	/* stop timer 3 */	TCON &= ~(TCON_3_AUTO | TCON_3_INVERT | TCON_3_MAN | TCON_3_ONOFF);}/* * 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){	char mode;	if (argc == 2) {		mode = *argv[1];	} else {		mode = 'h';	}	if (mode == 's') {		processor_reset(0);	} else {		WTDAT = 0x100;		WTCNT = 0x100;		WTCON = 0x8021;	}}user_command_t reset_cmd = {	"reset",	command_reset,	NULL};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 2:		if (strncmp("help", argv[1], 4) == 0) {			display_cpu_help();			return;		}		if (strncmp("info", argv[1], 4) == 0) {			print_cpu_info();			return;		}		break;	case 4:		if (strncmp("set", argv[1], 3) == 0) {			unsigned long clock = simple_strtoul(argv[2], NULL, 0);			unsigned long ratio = simple_strtoul(argv[3], NULL, 0);			int ret = 0;			ret = change_sys_clks(clock, ratio);			if (ret)				printk("Failed. Can not change cpu clock\n");			else				printk("OK\n");			return;		}		break;	default:		display_cpu_help();		return;	}}user_command_t cpu_cmd = {	"cpu",	command_cpu,	NULL};

⌨️ 快捷键说明

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