speed.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 218 行

C
218
字号
/* * * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. * TsiChung Liew (Tsi-Chung.Liew@freescale.com) * * See file CREDITS for list of people who contributed to this * project. * * 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 */#include <common.h>#include <asm/processor.h>#include <asm/immap.h>DECLARE_GLOBAL_DATA_PTR;/* * Low Power Divider specifications */#define CLOCK_LPD_MIN		(1 << 0)	/* Divider (decoded) */#define CLOCK_LPD_MAX		(1 << 15)	/* Divider (decoded) */#define CLOCK_PLL_FVCO_MAX	540000000#define CLOCK_PLL_FVCO_MIN	300000000#define CLOCK_PLL_FSYS_MAX	266666666#define CLOCK_PLL_FSYS_MIN	100000000#define MHZ			1000000void clock_enter_limp(int lpdiv){	volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;	int i, j;	/* Check bounds of divider */	if (lpdiv < CLOCK_LPD_MIN)		lpdiv = CLOCK_LPD_MIN;	if (lpdiv > CLOCK_LPD_MAX)		lpdiv = CLOCK_LPD_MAX;	/* Round divider down to nearest power of two */	for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;	/* Apply the divider to the system clock */	ccm->cdr = (ccm->cdr & 0xF0FF) | CCM_CDR_LPDIV(i);	/* Enable Limp Mode */	ccm->misccr |= CCM_MISCCR_LIMP;}/* * brief   Exit Limp mode * warning The PLL should be set and locked prior to exiting Limp mode */void clock_exit_limp(void){	volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;	volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;	/* Exit Limp mode */	ccm->misccr &= ~CCM_MISCCR_LIMP;	/* Wait for the PLL to lock */	while (!(pll->psr & PLL_PSR_LOCK)) ;}/* * get_clocks() fills in gd->cpu_clock and gd->bus_clk */int get_clocks(void){	volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;	volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;	int pllmult_nopci[] = { 20, 10, 24, 18, 12, 6, 16, 8 };	int pllmult_pci[] = { 12, 6, 16, 8 };	int vco = 0, bPci, temp, fbtemp, pcrvalue;	int *pPllmult = NULL;	u16 fbpll_mask;#ifdef CONFIG_M54455EVB	volatile u8 *cpld = (volatile u8 *)(CFG_CS2_BASE + 3);#endif	u8 bootmode;	/* To determine PCI is present or not */	if (((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x00e0) ||	    ((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x0060)) {		pPllmult = &pllmult_pci[0];		fbpll_mask = 3;		/* 11b */		bPci = 1;	} else {		pPllmult = &pllmult_nopci[0];		fbpll_mask = 7;		/* 111b */#ifdef CONFIG_PCI		gd->pci_clk = 0;#endif		bPci = 0;	}#ifdef CONFIG_M54455EVB	bootmode = (*cpld & 0x03);	if (bootmode != 3) {		/* Temporary read from CCR- fixed fb issue, must be the same clock		   as pci or input clock, causing cpld/fpga read inconsistancy */		fbtemp = pPllmult[ccm->ccr & fbpll_mask];		/* Break down into small pieces, code still in flex bus */		pcrvalue = pll->pcr & 0xFFFFF0FF;		temp = fbtemp - 1;		pcrvalue |= PLL_PCR_OUTDIV3(temp);		pll->pcr = pcrvalue;	}#endif#ifdef CONFIG_M54451EVB	/* No external logic to read the bootmode, hard coded from built */#ifdef CONFIG_CF_SBF	bootmode = 3;#else	bootmode = 2;	/* default value is 16 mul, set to 20 mul */	pcrvalue = (pll->pcr & 0x00FFFFFF) | 0x14000000;	pll->pcr = pcrvalue;	while ((pll->psr & PLL_PSR_LOCK) != PLL_PSR_LOCK);#endif#endif	if (bootmode == 0) {		/* RCON mode */		vco = pPllmult[ccm->rcon & fbpll_mask] * CFG_INPUT_CLKSRC;		if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {			/* invaild range, re-set in PCR */			int temp = ((pll->pcr & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;			int i, j, bus;			j = (pll->pcr & 0xFF000000) >> 24;			for (i = j; i < 0xFF; i++) {				vco = i * CFG_INPUT_CLKSRC;				if (vco >= CLOCK_PLL_FVCO_MIN) {					bus = vco / temp;					if (bus <= CLOCK_PLL_FSYS_MIN - MHZ)						continue;					else						break;				}			}			pcrvalue = pll->pcr & 0x00FF00FF;			fbtemp = ((i - 1) << 8) | ((i - 1) << 12);			pcrvalue |= ((i << 24) | fbtemp);			pll->pcr = pcrvalue;		}		gd->vco_clk = vco;	/* Vco clock */	} else if (bootmode == 2) {		/* Normal mode */		vco =  ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;		if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {			/* Default value */			pcrvalue = (pll->pcr & 0x00FFFFFF);			pcrvalue |= pPllmult[ccm->ccr & fbpll_mask] << 24;			pll->pcr = pcrvalue;			vco =  ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;		}		gd->vco_clk = vco;	/* Vco clock */	} else if (bootmode == 3) {		/* serial mode */		vco =  ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;		gd->vco_clk = vco;	/* Vco clock */	}	if ((ccm->ccr & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {		/* Limp mode */	} else {		gd->inp_clk = CFG_INPUT_CLKSRC;	/* Input clock */		temp = (pll->pcr & PLL_PCR_OUTDIV1_MASK) + 1;		gd->cpu_clk = vco / temp;	/* cpu clock */		temp = ((pll->pcr & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;		gd->bus_clk = vco / temp;	/* bus clock */		temp = ((pll->pcr & PLL_PCR_OUTDIV3_MASK) >> 8) + 1;		gd->flb_clk = vco / temp;	/* FlexBus clock */#ifdef CONFIG_PCI		if (bPci) {			temp = ((pll->pcr & PLL_PCR_OUTDIV4_MASK) >> 12) + 1;			gd->pci_clk = vco / temp;	/* PCI clock */		}#endif	}#ifdef CONFIG_FSL_I2C	gd->i2c1_clk = gd->bus_clk;#endif	return (0);}

⌨️ 快捷键说明

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