smartreflex.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 791 行 · 第 1/2 页

C
791
字号
/* * linux/arch/arm/mach-omap3/smartreflex.c * * OMAP34XX SmartReflex Voltage Control * * Copyright (C) 2007 Texas Instruments, Inc. * Lesly A M <x0080970@ti.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/kernel.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/err.h>#include <linux/clk.h>#include <linux/sysfs.h>#include <asm/arch/prcm.h>#include <asm/arch/power_companion.h>#include <asm/io.h>#include "prcm-regs.h"#include "smartreflex.h"/* #define DEBUG_SR 1 */#  define DPRINTK(fmt, args...)struct omap_sr{	int srid;	int is_sr_reset;	int is_autocomp_active;	struct clk *fck;	u32 req_opp_no;	u32 opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue, opp5_nvalue;	u32 senp_mod, senn_mod;	u32 srbase_addr;	u32 vpbase_addr;};static struct omap_sr sr1 = {	.srid = SR1,	.is_sr_reset = 1,	.is_autocomp_active = 0,	.srbase_addr = OMAP34XX_SR1_BASE,};static struct omap_sr sr2 = {	.srid = SR2,	.is_sr_reset = 1,	.is_autocomp_active = 0,	.srbase_addr = OMAP34XX_SR2_BASE,};static inline void sr_write_reg(struct omap_sr *sr, int offset, u32 value){	omap_writel(value, sr->srbase_addr + offset);}static inline void sr_modify_reg(struct omap_sr *sr, int offset, u32 mask,								u32 value){	u32 reg_val;	reg_val = omap_readl(sr->srbase_addr + offset);	reg_val &= ~mask;	reg_val |= value;	omap_writel(reg_val, sr->srbase_addr + offset);}static inline u32 sr_read_reg(struct omap_sr *sr, int offset){	return omap_readl(sr->srbase_addr + offset);}static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen){	u32 gn, rn, mul;	for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {		mul = 1 << (gn + 8);		rn = mul / sensor;		if (rn < R_MAXLIMIT) {			*sengain = gn;			*rnsen = rn;		}	}}static int sr_clk_enable(struct omap_sr *sr){	if (clk_enable(sr->fck) != 0) {		printk(KERN_ERR "Could not enable sr%d_fck\n", sr->srid);		goto clk_enable_err;	}	/* set fclk- active , iclk- idle */	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,						SR_CLKACTIVITY_IOFF_FON);	return 0;clk_enable_err:	return -1;}static int sr_clk_disable(struct omap_sr *sr){	/* set fclk, iclk- idle */	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,						SR_CLKACTIVITY_IOFF_FOFF);	clk_disable(sr->fck);	sr->is_sr_reset = 1;	return 0;}static void sr_set_nvalues(struct omap_sr *sr){	u32 senpval, sennval;	u32 senpgain, senngain;	u32 rnsenp, rnsenn;	if (sr->srid == SR1) {		/* since E-Fuse Values are not available, calculating the		 * reciprocal of the SenN and SenP values for SR1		 */		sr->senp_mod = 0x03;        /* SenN-M5 enabled */		sr->senn_mod = 0x03;		/* for OPP5 */		senpval = 0x848 + 0x330;		sennval = 0xacd + 0x330;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp5_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP4 */		senpval = 0x727 + 0x2a0;		sennval = 0x964 + 0x2a0;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp4_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP3 */		senpval = 0x655 + 0x200;		sennval = 0x85b + 0x200;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp3_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP2 */		senpval = 0x3be + 0x1a0;		sennval = 0x506 + 0x1a0;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp2_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP1 */		senpval = 0x28c + 0x100;		sennval = 0x373 + 0x100;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp1_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		sr_clk_enable(sr);		sr_write_reg(sr, NVALUERECIPROCAL, sr->opp3_nvalue);		sr_clk_disable(sr);	} else if (sr->srid == SR2) {		/* since E-Fuse Values are not available, calculating the		 * reciprocal of the SenN and SenP values for SR2		 */		sr->senp_mod = 0x03;		sr->senn_mod = 0x03;		/* for OPP3 */		senpval = 0x579 + 0x200;		sennval = 0x76f + 0x200;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp3_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP2 */		senpval = 0x390 + 0x1c0;		sennval = 0x4f5 + 0x1c0;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp2_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));		/* for OPP1 */		senpval = 0x25d;		sennval = 0x359;		cal_reciprocal(senpval, &senpgain, &rnsenp);		cal_reciprocal(sennval, &senngain, &rnsenn);		sr->opp1_nvalue =				((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |				(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |				(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |				(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));	}}static void sr_configure_vp(int srid){	u32 vpconfig;	if (srid == SR1) {		vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN			| PRM_VP1_CONFIG_INITVOLTAGE | PRM_VP1_CONFIG_TIMEOUTEN;		PRM_VP1_CONFIG = vpconfig;		PRM_VP1_VSTEPMIN = PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN |						PRM_VP1_VSTEPMIN_VSTEPMIN;		PRM_VP1_VSTEPMAX = PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |						PRM_VP1_VSTEPMAX_VSTEPMAX;		PRM_VP1_VLIMITTO = PRM_VP1_VLIMITTO_VDDMAX |			PRM_VP1_VLIMITTO_VDDMIN | PRM_VP1_VLIMITTO_TIMEOUT;		PRM_VP1_CONFIG |= PRM_VP1_CONFIG_INITVDD;		PRM_VP1_CONFIG &= ~PRM_VP1_CONFIG_INITVDD;	} else if (srid == SR2) {		vpconfig = PRM_VP2_CONFIG_ERROROFFSET | PRM_VP2_CONFIG_ERRORGAIN			| PRM_VP2_CONFIG_INITVOLTAGE | PRM_VP2_CONFIG_TIMEOUTEN;		PRM_VP2_CONFIG = vpconfig;		PRM_VP2_VSTEPMIN = PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN |						PRM_VP2_VSTEPMIN_VSTEPMIN;		PRM_VP2_VSTEPMAX = PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |						PRM_VP2_VSTEPMAX_VSTEPMAX;		PRM_VP2_VLIMITTO = PRM_VP2_VLIMITTO_VDDMAX |			PRM_VP2_VLIMITTO_VDDMIN | PRM_VP2_VLIMITTO_TIMEOUT;		PRM_VP2_CONFIG |= PRM_VP2_CONFIG_INITVDD;		PRM_VP2_CONFIG &= ~PRM_VP2_CONFIG_INITVDD;	}}static void sr_configure_vc(void){	PRM_VC_SMPS_SA =		(R_SRI2C_SLAVE_ADDR << PRM_VC_SMPS_SA1_SHIFT) |		(R_SRI2C_SLAVE_ADDR << PRM_VC_SMPS_SA0_SHIFT);	PRM_VC_SMPS_VOL_RA = (R_VDD2_SR_CONTROL << PRM_VC_SMPS_VOLRA1_SHIFT) |				(R_VDD1_SR_CONTROL << PRM_VC_SMPS_VOLRA0_SHIFT);	PRM_VC_CMD_VAL_0 = (PRM_VC_CMD_VAL0_ON << PRM_VC_CMD_ON_SHIFT) |			(PRM_VC_CMD_VAL0_ONLP << PRM_VC_CMD_ONLP_SHIFT) |			(PRM_VC_CMD_VAL0_RET << PRM_VC_CMD_RET_SHIFT) |			(PRM_VC_CMD_VAL0_OFF << PRM_VC_CMD_OFF_SHIFT);	PRM_VC_CMD_VAL_1 = (PRM_VC_CMD_VAL1_ON << PRM_VC_CMD_ON_SHIFT) |			(PRM_VC_CMD_VAL1_ONLP << PRM_VC_CMD_ONLP_SHIFT) |			(PRM_VC_CMD_VAL1_RET << PRM_VC_CMD_RET_SHIFT) |			(PRM_VC_CMD_VAL1_OFF << PRM_VC_CMD_OFF_SHIFT);	PRM_VC_CH_CONF = PRM_VC_CH_CONF_CMD1 | PRM_VC_CH_CONF_RAV1;	PRM_VC_I2C_CFG = PRM_VC_I2C_CFG_MCODE | PRM_VC_I2C_CFG_HSEN							| PRM_VC_I2C_CFG_SREN;	/* Setup voltctrl and other setup times */	PRM_VOLTCTRL |= PRM_VOLTCTRL_AUTO_RET;}static void sr_configure(struct omap_sr *sr){	u32 sys_clk, sr_clk_length = 0;	u32 sr_config;	u32 senp_en , senn_en;	senp_en = sr->senp_mod;	senn_en = sr->senn_mod;	sys_clk = prcm_get_system_clock_speed();	switch (sys_clk) {	case 12000:		sr_clk_length = SRCLKLENGTH_12MHZ_SYSCLK;		break;	case 13000:		sr_clk_length = SRCLKLENGTH_13MHZ_SYSCLK;		break;	case 19200:		sr_clk_length = SRCLKLENGTH_19MHZ_SYSCLK;		break;	case 26000:		sr_clk_length = SRCLKLENGTH_26MHZ_SYSCLK;		break;	case 38400:		sr_clk_length = SRCLKLENGTH_38MHZ_SYSCLK;		break;	default :		printk(KERN_ERR "Invalid sysclk value\n");		break;	}	DPRINTK(KERN_DEBUG "SR : sys clk %lu\n", sys_clk);	if (sr->srid == SR1) {		sr_config = SR1_SRCONFIG_ACCUMDATA |			(sr_clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |			SRCONFIG_MINMAXAVG_EN |			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |			SRCONFIG_DELAYCTRL;		sr_write_reg(sr, SRCONFIG, sr_config);		sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |					SR1_AVGWEIGHT_SENNAVGWEIGHT);		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),			(SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));	} else if (sr->srid == SR2) {		sr_config = SR2_SRCONFIG_ACCUMDATA |			(sr_clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |			SRCONFIG_MINMAXAVG_EN |			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |			SRCONFIG_DELAYCTRL;		sr_write_reg(sr, SRCONFIG, sr_config);		sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |					SR2_AVGWEIGHT_SENNAVGWEIGHT);		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),

⌨️ 快捷键说明

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