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 + -
显示快捷键?