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

📄 ar7.c

📁 ADAM2 sources (modified by Oleg)
💻 C
字号:
/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*   Copyright (C) 2003 by Texas Instruments, Inc.  All rights reserved.       */
/*   Copyright (C) 2003 Telogy Networks.	    						       */
/*-----------------------------------------------------------------------------*/

#include "_stdio.h"
#include "env.h"
#include "hw.h"
#include "main.h"

#define ABS(x)                 	( ((signed)(x) > 0) ? (x) : (-(x)) )
#define CEIL(x,y)              	( ((x) + (y) / 2) / (y) )

#define TNETD73XX_SYSCLK_DIV	0xa8610a20
#define TNETD73XX_SYSCLK_PLL    0xa8610a30

#define  MAX_DIV_VALUE          16
#define  PLL_MUL_MAXFACTOR      15

#define  MIN_PLL_INP_FREQ       MHZ(8)
#define  MAX_PLL_INP_FREQ       MHZ(100)

unsigned int _SysFrequency;
unsigned int max_cpu_frequency;

static unsigned int get_base_clk()
{
    bit32u bootcr, freq = 1;                                      
                                                              
    /* system clock */                         
    bootcr = REG32_R(0xa8611a00, 15, 14);                 
    switch (bootcr) 
	{                                     
    	case 0:                                       
            freq = CONF_AFEXTAL_FREQ;             
			break;                                
		
		case 1:                                       
        	freq = CONF_REFXTAL_FREQ;             
            break;                                
		
		case 2:                                       
        	freq = CONF_XTAL3IN_FREQ;             
            break;                                
		
		case 3:                                       
        	if (REG32_R(0xa8611a00, 25, 25) == 1) 
            	freq = _CpuFrequency;         
			else                                  
            	freq = CONF_REFXTAL_FREQ;     
	}   
    return freq;                                                    
}

unsigned int get_mips_freq()
{
     bit32u mips_pll_setting;
     bit32u mips_div_setting;
     bit32u predivider;
     bit32u postdivider;

     unsigned int	pll_factor;
     unsigned int       base_clk;
		
     mips_div_setting = REG32(TNETD73XX_SYSCLK_DIV); /* Divisor is a 4 bit N+1 divisor */		

     predivider = (0x1f & mips_div_setting) + 1;
     postdivider = ((0x1f << 16) & mips_div_setting) + 1; 
     base_clk = get_base_clk() /(predivider * postdivider);
	
     mips_pll_setting = REG32(TNETD73XX_SYSCLK_PLL);	

	/* Get the PLL multiplication factor */
	pll_factor = ((mips_pll_setting & 0xF000) >>12) + 1;
	
	/* Check if we're in divide mode or multiply mode */
	if((mips_pll_setting & 0x1)	== 1)
	{
		if((mips_pll_setting & 0x0802) == 0x802) /* See if PLLNDIV & PLLDIV are set */
		{
			if(mips_pll_setting & 0x1000)
			{
				/* clk = base_clk * (k-1) / 4)*/
				return((base_clk * (pll_factor - 1)) >>2);
			}
			else
			{
				/* clk = base_clk * k /2 */
				return((base_clk * pll_factor) >> 1);
			}
		}
		else
		{	
			if(pll_factor == 0x10)
			{
				pll_factor = 1;
			}
			return(base_clk*pll_factor);
		}
	}
	else		/* We're in divide mode */
	{
		if(pll_factor < 0x10)
		{
			/* clk = base_clk /2 */
			return(base_clk >> 1);
		}
		else
		{
			/* clk = base_clk / 4 */
			return(base_clk >> 2);
		}
	}
	return(0); /* Should never reach here */
}

static UINT32 find_gcd(UINT32 min, UINT32 max)
{
    if (max % min == 0)
    {
        return min;
    }
    else
    {
        return find_gcd(max % min, min);
    }
}

static void find_approx(UINT32 *num, UINT32 *denom, UINT32 base_freq)
{
    UINT32 num1;
    UINT32 denom1;
    UINT32 num2;
    UINT32 denom2;
    INT32 closest;
    INT32 prev_closest;
    UINT32 temp_num;
    UINT32 temp_denom;
    UINT32 normalize;
    UINT32 gcd;
    UINT32 output;

    num1 = *num;
    denom1 = *denom;

    prev_closest = 0x7fffffff; /* maximum possible value */
    num2 = num1;
    denom2 = denom1;

    /* start with  max */
    for(temp_num = 15; temp_num >=1; temp_num--)
    {

        temp_denom = CEIL(temp_num * denom1, num1);

        if(temp_denom < 1)
        {
            break;
        }
        else
        {
            normalize = CEIL(num1,temp_num);
            closest = (ABS((num1 * (temp_denom) ) - (temp_num * denom1)))  * normalize;
        	output =  (temp_num * base_freq)/temp_denom; 
			if(closest < prev_closest && output <= max_cpu_frequency && output > SYS_MIN_F)
            {
                prev_closest = closest;
                num2 = temp_num;
                denom2 = temp_denom;
            }
        }
    }

    gcd = find_gcd(num2,denom2);
    num2 = num2 / gcd;
    denom2 = denom2 /gcd;

    *num      = num2;
    *denom    = denom2;
}

static void get_val(UINT32 output_freq, UINT32 base_freq,UINT32 *multiplier, UINT32 *divider)
{
    UINT32 temp_mul;
    UINT32 temp_div;
    UINT32 gcd;
    UINT32 min_freq;
    UINT32 max_freq;

    /* find gcd of base_freq, output_freq */
    min_freq = (base_freq < output_freq) ? base_freq : output_freq;
    max_freq = (base_freq > output_freq) ? base_freq : output_freq;
    gcd = find_gcd(min_freq , max_freq);

        /* compute values of multiplier and divider */
    temp_mul = output_freq / gcd;
    temp_div = base_freq / gcd;

    /* set multiplier such that 1 <= multiplier <= PLL_MUL_MAXFACTOR */
    if( temp_mul > PLL_MUL_MAXFACTOR )
        find_approx(&temp_mul,&temp_div, base_freq);

    *multiplier = temp_mul;
    *divider    = temp_div;
}

static UINT32 compute_prediv(UINT32 divider, UINT32 min, UINT32 max)
{
	UINT16 prediv;

	/* return the divider itself it it falls within the range of predivider*/
	if (min <= divider && divider <= max)
    	return divider;

	/* find a value for prediv such that it is a factor of divider */
	for (prediv = max; prediv >= min ; prediv--)
    	if ((divider % prediv) == 0)
        	return prediv;

	/* No such factor exists,  return min as prediv */
	return min;
}

static void get_div_prenpost(bit32u multiplier, bit32u divider, bit32u clk_in, 
							 bit32u *pre, bit32u *post)
{
	bit32u min_prediv, max_prediv, temp;
	/* required for other modules whose input has CPU freq. */
    /*compute minimum and maximum predivider values */
    min_prediv = MAX(clk_in/MAX_PLL_INP_FREQ + 1, divider/MAX_DIV_VALUE + 1);
    max_prediv = MIN(clk_in/MIN_PLL_INP_FREQ, MAX_DIV_VALUE);

    /*adjust  the value of divider so that it not less than minimum predivider value*/
    if (divider < min_prediv)
    {
        temp = CEIL(min_prediv, divider);
        if ((temp * multiplier) > PLL_MUL_MAXFACTOR) {
        } else {
            multiplier = temp * multiplier;
            divider = min_prediv;
		}
    }
    /* compute predivider  and postdivider values */
    *pre = compute_prediv(divider, min_prediv, max_prediv);
    *post = CEIL(divider, *pre);
}

bit32u get_base_frequency(bit32u clk_id)
{
	bit32u bootcr, freq=1;
	
	if (clk_id == 0) { /* system clock */
		bootcr = REG32_R(0xa8611a00, 15, 14);
		switch (bootcr) {
			case 0: freq = CONF_AFEXTAL_FREQ; break;
			case 2: freq = CONF_XTAL3IN_FREQ; break;
			case 1: freq = CONF_REFXTAL_FREQ; break;
			case 3: freq = get_base_frequency(1);
			
		}
	} else if (clk_id == 1) { /* MIPS clock */
		bootcr = REG32_R(0xa8611a00, 17, 16);
		switch (bootcr) {
			case 0: freq = CONF_AFEXTAL_FREQ; break;
			case 2: freq = CONF_XTAL3IN_FREQ; break;
			case 1:
			case 3: freq = CONF_REFXTAL_FREQ;
		}
	} else {
		sys_printf("\nInvalid clk_id");
		return 0;
	}
	
	return freq;
	
}

#if 0
int cfg_cpufreq(bit32u  freq)
{
	bit32u multiplier, divider, clk_in, pre, post, mips_async;
	volatile bit32u i;
	char sbuf[30];

	mips_async = REG32_R(0xa8611a00, 25, 25);
	if (mips_async == 0) {
		max_cpu_frequency = CPU_SYNC_MAX_F;  
		clk_in = get_base_clk();
		get_val(freq, clk_in, &multiplier, &divider);
		if (clk_in >= MAX_PLL_INP_FREQ) {
			get_div_prenpost(multiplier, divider, clk_in, &pre, &post);
		} else {
			post = divider;
			pre = 1;
		}

		EMIF_DRAMCTL |= 0x80000000;
		SioFlush();
		
		REG32_W(0xa8610a20, ((post - 1) & 0x1F) << 16 | ((pre - 1) & 0x1F));
		for(i=0;i<10100 * 75;i++); /* wait for divider to stabilize */
		
		SetRefClkPllReg(multiplier - 1);
		_CpuFrequency = (clk_in * multiplier)/(pre * post);
                _SysFrequency = _CpuFrequency;
		SioInit();
		EMIF_DRAMCTL &= ~0x80000000;

		sys_sprintf(sbuf, "%d", _CpuFrequency);
		sys_setenv("cpufrequency", sbuf);


		sys_sprintf(sbuf, "%d", _SysFrequency);
		sys_setenv("sysfrequency", sbuf);
	} 
	return 0;
}
#endif

int cfg_cpufreq(bit32u sysf, bit32u cpuf, bit32u dbg_opt)
{
	bit32u multiplier, divider, clk_in, pre, post, mips_async;
	volatile bit32u i;
	char sbuf[30];

	if (dbg_opt == TRUE) {
		sys_printf("CPU Freq: %d", _CpuFrequency);
		sys_printf("\nSYS Freq: %d\n", _SysFrequency);
		return 0;
	}
	mips_async = REG32_R(0xa8611a00, 25, 25);
	if (mips_async == 0) {
		max_cpu_frequency = CPU_SYNC_MAX_F;

		if (sysf == -1) sysf = cpuf;
		
		if (sysf > max_cpu_frequency) sysf = max_cpu_frequency;
		if (sysf < SYS_MIN_F)         sysf = SYS_MIN_F;
		clk_in = get_base_frequency(0);
		get_val(sysf, clk_in, &multiplier, &divider);
		if (clk_in >= MAX_PLL_INP_FREQ) {
			get_div_prenpost(multiplier, divider, clk_in, &pre, &post);
		} else {
			post = divider;
			pre = 1;
		}
		
		EMIF_DRAMCTL |= 0x80000000;
		SioFlush();
		/*REG32_W(0xa8610a20, ((post - 1) & 0x1F) << 16 | ((pre - 1) & 0x1F));*/
		REG32_W(0xa8610a20, ((pre - 1) & 0x1F) << 16 | ((post - 1) & 0x1F));
		/* wait */for(i = 0; i < 10100 * 75; i++);
		SetRefClkPllReg(multiplier - 1, 0);
		_SysFrequency = _CpuFrequency = (clk_in * multiplier)/(pre * post);
		REG32_RMW(0xa861080c, 12, 0, ((_SysFrequency / MHZ(1)) * 78) / 10);
		/* wait */for(i = 0; i < 10100 * 75; i++);
		SioInit();
		EMIF_DRAMCTL &= ~0x80000000;
		
	} else {
		EMIF_DRAMCTL |= 0x80000000;
		SioFlush();

		if (cpuf != -1) {
		max_cpu_frequency = CPU_ASYNC_MAX_F;
			if (cpuf > max_cpu_frequency) cpuf = max_cpu_frequency;
			if (cpuf < SYS_MIN_F)         cpuf = SYS_MIN_F;
		clk_in = get_base_frequency(1);
			get_val(cpuf, clk_in, &multiplier, &divider);
		
			/*REG32_W(0xa8610a40, ((divider -1) & 0x1F) << 16);*/
			REG32_W(0xa8610a40, ((divider -1) & 0x1F));
		/* wait */for(i = 0; i < 10100 * 75; i++);
		
		SetRefClkPllReg(multiplier - 1, 1);

		_CpuFrequency = (clk_in * multiplier)/divider;
		}
		
		if (sysf != -1) {
		clk_in = get_base_frequency(0);
			if (sysf > SYS_MAX_F) sysf = SYS_MAX_F;
			if (sysf < SYS_MIN_F) sysf = SYS_MIN_F;

			get_val(sysf, clk_in, &multiplier, &divider);
		if (clk_in >= MAX_PLL_INP_FREQ) {
			get_div_prenpost(multiplier, divider, clk_in, &pre, &post);
		} else {
			post = divider;
			pre = 1;
		}
		/*REG32_W(0xa8610a20, ((post - 1) & 0x1F) << 16 | ((pre - 1) & 0x1F));*/
		REG32_W(0xa8610a20, ((pre - 1) & 0x1F) << 16 | ((post - 1) & 0x1F));
		/* wait */for(i = 0; i < 10100 * 75; i++);
		
		SetRefClkPllReg(multiplier - 1, 0);
		
		_SysFrequency =  (clk_in * multiplier)/(pre * post);
		REG32_RMW(0xa861080c, 12, 0, ((_CpuFrequency / MHZ(1)) * 78) / 10);
		/* wait */for(i = 0; i < 10100 * 75; i++);
		}
		
		SioInit();
		EMIF_DRAMCTL &= ~0x80000000;
	}

		sys_sprintf(sbuf, "%d", _CpuFrequency);
		sys_setenv("cpufrequency",sbuf);
                sys_sprintf(sbuf, "%d", _SysFrequency);
		sys_setenv("sysfrequency",sbuf);
	return 0;
}


void platform_init()
{
    RESET_PRCR |= UART0_RESET;
    RESET_PRCR |= GPIO_RESET;

#if (CONF_CPMAC_IF == 0)
/* #ifdef INTERNAL_PHY by Oleg changed back to original */
    GPIO_EN = 0xf3fc3ff0;
#else
    GPIO_EN = 0xfffc3ff0;
#endif

#if (CONF_CPMAC_IF == 0)
/* #ifdef INTERNAL_PHY by Oleg changed back to original */
    RESET_PRCR &= (~EMAC_PHY_RESET);
    RESET_PRCR |= EMAC_PHY_RESET;
#endif
    
    RESET_PRCR |= MDIO_RESET;
#if (CONF_CPMAC_IF == 0)
/* #ifdef INTERNAL_PHY by Oleg changed back to original */
    RESET_PRCR |= EMACA_RESET;
#endif
    RESET_PRCR |= EMACB_RESET;
}

⌨️ 快捷键说明

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