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

📄 pm_pmu.c

📁 the attached file is the power mangement for MP201
💻 C
字号:
/* *  File Name	    : linux/arch/arm/mach-mp200/pm_pmu.c *  Function	    : pm_pmu *  Release Version : Ver 1.00 *  Release Date    : 2006/03/20 * *  Copyright (C) NEC Electronics Corporation 2005-2006 * * *  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 Free Softwere Foundation; either version 2 *  of 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 warrnty 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 <linux/config.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/slab.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/errno.h>#include <asm/arch/smu.h>#include <asm/arch/pmu.h>#include "uwire.h"#include "time.h"#include "pm.h"static void (*change_flash_read_mode) (struct flash_read_param *);static struct flash_read_param flash_read_param_fullspeed;static struct flash_read_param flash_read_param_economy = {	.smu_ab0_cs0readctrl = SMU_AB0_READMODE_SINGLE0,	.smu_ab0_cs1readctrl = SMU_AB0_READMODE_SINGLE0,	.smu_ab0_flashrcr = SMU_AB0_ASYNC_READ_MODE,};/* #define  PM_DEBUG_CLK */#define PLL_KIND_NUM 5static struct pll_data pll_tbl[PLL_KIND_NUM] ={  {    .param = { 0x00000001, 0x00090000, 0x00040000 },    .mode  = MP200_PLL_248MHZ,    .lpj   = MP200_LPJ_248MHZ,  },  {     .param = { 0x00000005, 0x00050000, 0x00020000 },    .mode  = MP200_PLL_164MHZ,     .lpj   = MP200_LPJ_164MHZ,  },  {     .param = { 0x00000001, 0x01040000, 0x00000000 },    .mode  = MP200_PLL_124MHZ,    .lpj   = MP200_LPJ_124MHZ,  },  {    .param = { 0x00000001, 0x02020000, 0x00000000 },    .mode  = MP200_PLL_83MHZ,    .lpj   = MP200_LPJ_83MHZ,  },  {     .param = { 0x00000001, 0x04010000, 0x00000000 },     .mode  = MP200_PLL_50MHZ,     .lpj   = MP200_LPJ_50MHZ,  },};void (*mp200_change_pll_on_sram) (struct pll_param *);void (*mp200_change_osc_on_sram) (void);static inline int get_idx(int x) {	int i;		for(i=0;i<PLL_KIND_NUM;i++) {		if(pll_tbl[i].mode == x) {#ifdef PM_DEBUG_CLK			printk("get_idx. idx=%d mode=%d \n", i, pll_tbl[i].mode);#endif			return i;		}	}	return 0;}void mp200_pm_set_uwire_clock(void){	unsigned int hpll_p_val;	unsigned int hpll_m_val;	unsigned int hpll_n_val;	unsigned int lpll_ctrl1;	unsigned int pll1;	mp200_pmu_close_clockgate(MP200_CLOCKGATE_MWI_SCLK);	mp200_pmu_close_clockgate(MP200_CLOCKGATE_MWI_PCLK);	switch (mp200_pm_get_pll()) {	case MP200_PLL_12MHZ:		outl((DIV_12M - 1), SMU_MWI_SCLK_DIV);		break;	case MP200_PLL_164MHZ:		/* PLL is L */		lpll_ctrl1 = inl(SMU_LPLL_CTRL1);		pll1 = ((3750 + lpll_ctrl1*125) * 32768 )/1000;	/* 32.768kHz(RTC) */		outl( (pll1 / 3000) - 1, SMU_MWI_SCLK_DIV );#ifdef PM_DEBUG		printk(KERN_INFO "%s(): sclk src=%u.%3u, divisor=%u\n",		       __FUNCTION__, pll1 / 1000, pll1 % 1000, pll1 / 3000);#endif		break;	case MP200_PLL_248MHZ:	case MP200_PLL_124MHZ:	case MP200_PLL_83MHZ:	case MP200_PLL_50MHZ:		/* PLL is H */		hpll_n_val = (inl(SMU_HPLL_CTRL1) & MASK_HPLL_N) + 1;		hpll_m_val = (inl(SMU_HPLL_CTRL2) & MASK_HPLL_M) + 1;		hpll_p_val = (inl(SMU_HPLL_CTRL3) & MASK_HPLL_P);		pll1 = ((12000000/1000) * hpll_n_val) / hpll_m_val;	/* OSC(6-12MHz ) */		if( hpll_p_val != 0 ) {			pll1 >>= 1;		}		outl( (pll1 / 3000) - 1, SMU_MWI_SCLK_DIV );#ifdef PM_DEBUG		printk(KERN_INFO "%s(): sclk src=%u.%3u, divisor=%u\n",		       __FUNCTION__, pll1 / 1000, pll1 % 1000, pll1 / 3000);#endif		break;	default:		printk(KERN_INFO "%s(): Unknown SCLK Source\n", __FUNCTION__);		outl((DIV_12M - 1), SMU_MWI_SCLK_DIV);		break;	}	mp200_pmu_open_clockgate(MP200_CLOCKGATE_MWI_PCLK);}void mp200_pm_update_lpj(void){	unsigned int mode = mp200_pm_get_pll();	switch (mode) {	case MP200_PLL_248MHZ:	case MP200_PLL_164MHZ:	case MP200_PLL_124MHZ:	case MP200_PLL_83MHZ:	case MP200_PLL_50MHZ:		loops_per_jiffy = pll_tbl[get_idx(mode)].lpj;		timer_set_clock_parm(TIMER_FULLSPEED);		break;	case MP200_PLL_12MHZ:		loops_per_jiffy = MP200_LPJ_ECONOMY;		timer_set_clock_parm(TIMER_ECONOMY);		break;	default:		loops_per_jiffy = MP200_LPJ_ECONOMY;		timer_set_clock_parm(TIMER_ECONOMY);		break;	}}/* * economy  ->  fullspeed */void mp200_pm_eco_to_full(unsigned int new){	if (mp200_pm_get_pll() == new) {		return;	}#ifdef PM_DEBUG_CLK	printk("PM: %s(). change clock to [%d] from [%d]\n", 		__FUNCTION__, new, mp200_pm_get_pll());#endif	mp200_change_pll_on_sram(&pll_tbl[get_idx(new)].param);	/* update loops_per_jiffy */	mp200_pm_update_lpj();	/* change flash read mode */	change_flash_read_mode(&flash_read_param_fullspeed);	/* set uWire clock */	mp200_pm_set_uwire_clock();}/* * fullspeed  ->  economy */void mp200_pm_full_to_eco(void){	if (mp200_pm_get_pll() == MP200_PLL_12MHZ) {		return;	}	/* change flash read mode */	change_flash_read_mode(&flash_read_param_economy);#ifdef PM_DEBUG_CLK	printk("PM: %s(). change to osc from [%d] \n", 		__FUNCTION__, mp200_pm_get_pll());#endif	mp200_change_osc_on_sram();	/* update loops_per_jiffy */	mp200_pm_update_lpj();	/* set uWire clock */	mp200_pm_set_uwire_clock();}unsigned int mp200_pm_get_pll(void){	if ((inl(SMU_PLLSEL) & MASK_SMU_PLLSEL) == SMU_PLLSEL_PLL) {		if(inl(SMU_PLLSEL2) & SMU_NRM_CK_SEL) { /* low */			return MP200_PLL_164MHZ; 		}		else { /* high */			int i;			unsigned int frq_change = inl(SMU_AUTO_FRQ_CHANGE);			for (i = 0;i < PLL_KIND_NUM; i++) {				if((frq_change & SMU_PLL_NRM_DIV_MASK) 					== (pll_tbl[i].param.auto_frq_change 					    & SMU_PLL_NRM_DIV_MASK)) {					return pll_tbl[i].mode;				}			}		}	}	return MP200_PLL_12MHZ;}int mp200_pm_set_pll(unsigned int flag){	unsigned long irq_flags;	unsigned int mode;	int ret = 0;	local_irq_save(irq_flags);	switch (flag) {	case MP200_PLL_248MHZ:	case MP200_PLL_164MHZ:	case MP200_PLL_124MHZ:	case MP200_PLL_83MHZ:	case MP200_PLL_50MHZ:		mode = mp200_pm_get_pll();		if(mode != flag) {			mp200_pm_eco_to_full(flag);		}		if(mode == MP200_PLL_12MHZ) {			timer_set_clock(TIMER_FULLSPEED);		}		break;	case MP200_PLL_12MHZ:		mode = mp200_pm_get_pll();		if(mode != MP200_PLL_12MHZ) {			timer_set_clock(TIMER_ECONOMY);			mp200_pm_full_to_eco();		}		break;	default:		ret = -EINVAL;		break;	}	local_irq_restore(irq_flags);	return ret;}static void change_flash_read_mode_on_flash(struct flash_read_param *param){	unsigned int addr;	outl(param->smu_ab0_flashrcr, SMU_AB0_FLASHRCR);	outl(param->smu_ab0_flashrcr, SMU_AB0_FLASHCOMADD0);	outl(param->smu_ab0_flashrcr | SMU_AB0_VALIDBIT | SMU_AB0_RW,	     SMU_AB0_FLASHCOMADD1);	outl(FLASH_CMD_CONFIGURATION_1ST, SMU_AB0_FLASHCOMDATA0);	outl(FLASH_CMD_CONFIGURATION_2ND, SMU_AB0_FLASHCOMDATA1);	outl(param->smu_ab0_cs0readctrl, SMU_AB0_CS0READCTRL);	outl(AB0_SET_MODE | AB0_CS0, AB0_FLASHCOMSET);	outl(param->smu_ab0_cs1readctrl, SMU_AB0_CS1READCTRL);	outl(AB0_SET_MODE | AB0_CS1, AB0_FLASHCOMSET);	addr = (param->smu_ab0_flashrcr << 1) + param->flash0_addr;	outw(FLASH_CMD_CONFIGURATION_1ST, addr);	outw(FLASH_CMD_CONFIGURATION_2ND, addr);	addr = (param->smu_ab0_flashrcr << 1) + param->flash1_addr;	outw(FLASH_CMD_CONFIGURATION_1ST, addr);	outw(FLASH_CMD_CONFIGURATION_2ND, addr);}static unsigned long pm_pmu_compute_lpj(unsigned long ref, u_int div, u_int mult){	unsigned long jiffy_l, jiffy_h;		jiffy_h = ref / div;	jiffy_l = (ref % div) / 100;	jiffy_h *= mult;	jiffy_l = jiffy_l * mult / div;		return jiffy_h + jiffy_l * 100;}/* * init */static int __init mp200_pm_pmu_init(void){	void *saddr;	void *daddr;	void *flash_addr;	int i;	saddr = (void *)change_flash_read_mode_on_flash;	daddr = kmalloc(CHANGE_FLASH_READ_MODE_SIZE, GFP_KERNEL);	if (daddr == NULL) {		return -ENOMEM;	}	memcpy(daddr, saddr, CHANGE_FLASH_READ_MODE_SIZE);	change_flash_read_mode = (void (*)(struct flash_read_param *))daddr;	flash_addr = ioremap(FLASH0_BASE, FLASH_SIZE);	if (flash_addr == NULL) {		kfree(daddr);		return -EIO;	}	flash_read_param_fullspeed.flash0_addr = (unsigned int)flash_addr;	flash_read_param_economy.flash0_addr = (unsigned int)flash_addr;	flash_addr = ioremap(FLASH1_BASE, FLASH_SIZE);	if (flash_addr == NULL) {		iounmap((void *)flash_read_param_fullspeed.flash0_addr);		kfree(daddr);		return -EIO;	}	flash_read_param_fullspeed.flash1_addr = (unsigned int)flash_addr;	flash_read_param_economy.flash1_addr = (unsigned int)flash_addr;	flash_read_param_fullspeed.smu_ab0_cs0readctrl =	    inl(SMU_AB0_CS0READCTRL);	flash_read_param_fullspeed.smu_ab0_cs1readctrl =	    inl(SMU_AB0_CS1READCTRL);	flash_read_param_fullspeed.smu_ab0_flashrcr = inl(SMU_AB0_FLASHRCR);	for (i = 0;i < PLL_KIND_NUM; i++) {		pll_tbl[i].lpj = pm_pmu_compute_lpj(loops_per_jiffy, 						mp200_pm_get_pll(), 						pll_tbl[i].mode);#ifdef PM_DEBUG_CLK		printk("PM: %s(). clock[%d] - lpj[0x%08x]\n", 			__FUNCTION__, pll_tbl[i].mode, pll_tbl[i].lpj);#endif	}#ifdef PM_DEBUG	printk(KERN_INFO "[flash_read_param_fullspeed]\n");	printk(KERN_INFO "  flash0_addr         = 0x%08x\n",	       flash_read_param_fullspeed.flash0_addr);	printk(KERN_INFO "  flash1_addr         = 0x%08x\n",	       flash_read_param_fullspeed.flash1_addr);	printk(KERN_INFO "  smu_ab0_cs0readctrl = 0x%08x\n",	       flash_read_param_fullspeed.smu_ab0_cs0readctrl);	printk(KERN_INFO "  smu_ab0_cs1readctrl = 0x%08x\n",	       flash_read_param_fullspeed.smu_ab0_cs1readctrl);	printk(KERN_INFO "  smu_ab0_flashrcr    = 0x%08x\n",	       flash_read_param_fullspeed.smu_ab0_flashrcr);	printk(KERN_INFO "[flash_read_param_economy]\n");	printk(KERN_INFO "  flash0_addr         = 0x%08x\n",	       flash_read_param_economy.flash0_addr);	printk(KERN_INFO "  flash1_addr         = 0x%08x\n",	       flash_read_param_economy.flash1_addr);	printk(KERN_INFO "  smu_ab0_cs0readctrl = 0x%08x\n",	       flash_read_param_economy.smu_ab0_cs0readctrl);	printk(KERN_INFO "  smu_ab0_cs1readctrl = 0x%08x\n",	       flash_read_param_economy.smu_ab0_cs1readctrl);	printk(KERN_INFO "  smu_ab0_flashrcr    = 0x%08x\n",	       flash_read_param_economy.smu_ab0_flashrcr);#endif	return 0;}__initcall(mp200_pm_pmu_init);

⌨️ 快捷键说明

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