Hi, Good comments. I'll tighten the patch-set into only two patches: regdefs and implementation. Some other comments below. On ti, 2008-06-10 at 15:20 -0700, ext Tony Lindgren wrote: > > + > > + > > +/* #define DEBUG_SR 1 */ > > +#ifdef DEBUG_SR > > +# define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__ ,\ > > + ## args) > > +#else > > +# define DPRINTK(fmt, args...) > > +#endif > > Please use the standard linux debugging functions instead. Will do. > > > > +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, > > +}; > > Please format struct data like linux code typically does, that is > align the values with tabs before the equal sign. OK. > > > > +static struct omap_sr sr2 = { > > + .srid = SR2, > > + .is_sr_reset = 1, > > + .is_autocomp_active = 0, > > + .srbase_addr = OMAP34XX_SR2_BASE, > > +}; > > + > > Here too. > > > > +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); > > +} > > + > > + > > The read and write registers are better done using __raw_readl/writel() > instead. Unless the register address is static, the function adds the > IO offset every time unnecessarily. > > So please set the sr->srbase_addr = io_v2p(SOME_PHYS_ADDR) during init > and change the read and write to use __raw_readl/writel() instead. did you mean "sr->srbase_addr = io_p2v(SOME_PHYS_ADDR)" ? > > > > +#ifndef USE_EFUSE_VALUES > > +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; > > + } > > + } > > +} > > +#endif > > + > > +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; > > +} > > Please don't add non-standard clk_enable/disable functions. Please use > the standard clock api instead so you can just call clk_enable/disable(). > > If you need to customize the clock, please just create a custom clock > with it's custom enable/disable function. See the new mcbsp code for > example. I'll look into this and see which would work better. > > > > +static void sr_set_nvalues(struct omap_sr *sr) > > +{ > > +#ifdef USE_EFUSE_VALUES > > + u32 n1, n2; > > +#else > > + u32 senpval, sennval; > > + u32 senpgain, senngain; > > + u32 rnsenp, rnsenn; > > +#endif > > + > > + if (sr->srid == SR1) { > > +#ifdef USE_EFUSE_VALUES > > + /* Read values for VDD1 from EFUSE */ > > +#else > > These ifdefs look ugly, what if you had two functions, one for efuse > values and the other one for non-efuse values? Yes, these are corrected in patch 3/3, but I'll tighten the patch-set into two patches, so these won't be lying around in any patch. > > > > > + /* since E-Fuse Values are not available, calculating the > > + * reciprocal of the SenN and SenP values for SR1 > > + */ > > Please use standard Linux commenting style, see > Documentation/CodingStyle Chapter 8: Commenting... Still learning ;) > > > > + 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); > > + > > Looks like instead of this copy and paste code for the values should > be set by some function or a loop? > I agree. Regards, Kalle > Regards, > > Tony > > > > > > +#endif > > + } else if (sr->srid == SR2) { > > +#ifdef USE_EFUSE_VALUES > > + /* Read values for VDD2 from EFUSE */ > > +#else > > + /* 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)); > > + > > +#endif > > + } > > + > > +} > > + > > +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 */ > > +#ifdef CONFIG_SYSOFFMODE > > + PRM_VOLTCTRL = PRM_VOLTCTRL_AUTO_OFF | PRM_VOLTCTRL_AUTO_RET; > > + PRM_CLKSETUP = PRM_CLKSETUP_DURATION; > > + PRM_VOLTSETUP1 = (PRM_VOLTSETUP_TIME2 << PRM_VOLTSETUP_TIME2_OFFSET) | > > + (PRM_VOLTSETUP_TIME1 << PRM_VOLTSETUP_TIME1_OFFSET); > > + PRM_VOLTOFFSET = PRM_VOLTOFFSET_DURATION; > > + PRM_VOLTSETUP2 = PRM_VOLTSETUP2_DURATION; > > +#else > > + PRM_VOLTCTRL |= PRM_VOLTCTRL_AUTO_RET; > > +#endif > > + > > +} > > + > > + > > +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), > > + (SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT)); > > + > > + } > > + sr->is_sr_reset = 0; > > +} > > + > > +static void sr_enable(struct omap_sr *sr, u32 target_opp_no) > > +{ > > + u32 nvalue_reciprocal, current_nvalue; > > + > > + sr->req_opp_no = target_opp_no; > > + > > + if (sr->srid == SR1) { > > + switch (target_opp_no) { > > + case 5: > > + nvalue_reciprocal = sr->opp5_nvalue; > > + break; > > + case 4: > > + nvalue_reciprocal = sr->opp4_nvalue; > > + break; > > + case 3: > > + nvalue_reciprocal = sr->opp3_nvalue; > > + break; > > + case 2: > > + nvalue_reciprocal = sr->opp2_nvalue; > > + break; > > + case 1: > > + nvalue_reciprocal = sr->opp1_nvalue; > > + break; > > + default: > > + nvalue_reciprocal = sr->opp3_nvalue; > > + break; > > + } > > + } else { > > + switch (target_opp_no) { > > + case 3: > > + nvalue_reciprocal = sr->opp3_nvalue; > > + break; > > + case 2: > > + nvalue_reciprocal = sr->opp2_nvalue; > > + break; > > + case 1: > > + nvalue_reciprocal = sr->opp1_nvalue; > > + break; > > + default: > > + nvalue_reciprocal = sr->opp3_nvalue; > > + break; > > + } > > + } > > + > > + current_nvalue = sr_read_reg(sr, NVALUERECIPROCAL); > > + > > + if (current_nvalue == nvalue_reciprocal) { > > + DPRINTK("System is already at the desired voltage level\n"); > > + return; > > + } > > + > > + sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal); > > + > > + /* Enable the interrupt */ > > + sr_modify_reg(sr, ERRCONFIG, > > + (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST), > > + (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST)); > > + > > + if (sr->srid == SR1) { > > + /* Enable VP1 */ > > + PRM_VP1_CONFIG |= PRM_VP1_CONFIG_VPENABLE; > > + } else if (sr->srid == SR2) { > > + /* Enable VP2 */ > > + PRM_VP2_CONFIG |= PRM_VP2_CONFIG_VPENABLE; > > + } > > + > > + /* SRCONFIG - enable SR */ > > + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); > > + > > +} > > + > > +static void sr_disable(struct omap_sr *sr) > > +{ > > + sr->is_sr_reset = 1; > > + > > + /* SRCONFIG - disable SR */ > > + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE); > > + > > + if (sr->srid == SR1) { > > + /* Enable VP1 */ > > + PRM_VP1_CONFIG &= ~PRM_VP1_CONFIG_VPENABLE; > > + } else if (sr->srid == SR2) { > > + /* Enable VP2 */ > > + PRM_VP2_CONFIG &= ~PRM_VP2_CONFIG_VPENABLE; > > + } > > +} > > + > > + > > +void sr_start_vddautocomap(int srid, u32 target_opp_no) > > +{ > > + struct omap_sr *sr = NULL; > > + > > + if (srid == SR1) > > + sr = &sr1; > > + else if (srid == SR2) > > + sr = &sr2; > > + > > + if (sr->is_sr_reset == 1) { > > + sr_clk_enable(sr); > > + sr_configure(sr); > > + } > > + > > + if (sr->is_autocomp_active == 1) > > + DPRINTK(KERN_WARNING "SR%d: VDD autocomp is already active\n", > > + srid); > > + > > + sr->is_autocomp_active = 1; > > + sr_enable(sr, target_opp_no); > > +} > > +EXPORT_SYMBOL(sr_start_vddautocomap); > > + > > +int sr_stop_vddautocomap(int srid) > > +{ > > + struct omap_sr *sr = NULL; > > + > > + if (srid == SR1) > > + sr = &sr1; > > + else if (srid == SR2) > > + sr = &sr2; > > + > > + if (sr->is_autocomp_active == 1) { > > + sr_disable(sr); > > + sr_clk_disable(sr); > > + sr->is_autocomp_active = 0; > > + return SR_TRUE; > > + } else { > > + DPRINTK(KERN_WARNING "SR%d: VDD autocomp is not active\n", > > + srid); > > + return SR_FALSE; > > + } > > + > > +} > > +EXPORT_SYMBOL(sr_stop_vddautocomap); > > + > > +void enable_smartreflex(int srid) > > +{ > > + u32 target_opp_no = 0; > > + struct omap_sr *sr = NULL; > > + > > + if (srid == SR1) > > + sr = &sr1; > > + else if (srid == SR2) > > + sr = &sr2; > > + > > + if (sr->is_autocomp_active == 1) { > > + if (sr->is_sr_reset == 1) { > > + if (srid == SR1) { > > + /* Enable SR clks */ > > + CM_FCLKEN_WKUP |= SR1_CLK_ENABLE; > > + target_opp_no = get_opp_no(current_vdd1_opp); > > + > > + } else if (srid == SR2) { > > + /* Enable SR clks */ > > + CM_FCLKEN_WKUP |= SR2_CLK_ENABLE; > > + target_opp_no = get_opp_no(current_vdd2_opp); > > + } > > + > > + sr_configure(sr); > > + > > + sr_enable(sr, target_opp_no); > > + } > > + } > > +} > > + > > +void disable_smartreflex(int srid) > > +{ > > + struct omap_sr *sr = NULL; > > + > > + if (srid == SR1) > > + sr = &sr1; > > + else if (srid == SR2) > > + sr = &sr2; > > + > > + if (sr->is_autocomp_active == 1) { > > + if (srid == SR1) { > > + /* Enable SR clk */ > > + CM_FCLKEN_WKUP |= SR1_CLK_ENABLE; > > + > > + } else if (srid == SR2) { > > + /* Enable SR clk */ > > + CM_FCLKEN_WKUP |= SR2_CLK_ENABLE; > > + } > > + > > + if (sr->is_sr_reset == 0) { > > + > > + sr->is_sr_reset = 1; > > + /* SRCONFIG - disable SR */ > > + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, > > + ~SRCONFIG_SRENABLE); > > + > > + if (sr->srid == SR1) { > > + /* Disable SR clk */ > > + CM_FCLKEN_WKUP &= ~SR1_CLK_ENABLE; > > + /* Enable VP1 */ > > + PRM_VP1_CONFIG &= ~PRM_VP1_CONFIG_VPENABLE; > > + > > + } else if (sr->srid == SR2) { > > + /* Disable SR clk */ > > + CM_FCLKEN_WKUP &= ~SR2_CLK_ENABLE; > > + /* Enable VP2 */ > > + PRM_VP2_CONFIG &= ~PRM_VP2_CONFIG_VPENABLE; > > + } > > + } > > + } > > +} > > + > > + > > +/* Voltage Scaling using SR VCBYPASS */ > > +int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel) > > +{ > > + int ret; > > + int sr_status = 0; > > + u32 vdd, target_opp_no; > > + u32 vc_bypass_value; > > + u32 reg_addr = 0; > > + u32 loop_cnt = 0, retries_cnt = 0; > > + > > + vdd = get_vdd(target_opp); > > + target_opp_no = get_opp_no(target_opp); > > + > > + if (vdd == PRCM_VDD1) { > > + sr_status = sr_stop_vddautocomap(SR1); > > + > > + PRM_VC_CMD_VAL_0 = (PRM_VC_CMD_VAL_0 & ~PRM_VC_CMD_ON_MASK) | > > + (vsel << PRM_VC_CMD_ON_SHIFT); > > + reg_addr = R_VDD1_SR_CONTROL; > > + > > + } else if (vdd == PRCM_VDD2) { > > + sr_status = sr_stop_vddautocomap(SR2); > > + > > + PRM_VC_CMD_VAL_1 = (PRM_VC_CMD_VAL_1 & ~PRM_VC_CMD_ON_MASK) | > > + (vsel << PRM_VC_CMD_ON_SHIFT); > > + reg_addr = R_VDD2_SR_CONTROL; > > + } > > + > > + vc_bypass_value = (vsel << PRM_VC_BYPASS_DATA_SHIFT) | > > + (reg_addr << PRM_VC_BYPASS_REGADDR_SHIFT) | > > + (R_SRI2C_SLAVE_ADDR << PRM_VC_BYPASS_SLAVEADDR_SHIFT); > > + > > + PRM_VC_BYPASS_VAL = vc_bypass_value; > > + > > + PRM_VC_BYPASS_VAL |= PRM_VC_BYPASS_VALID; > > + > > + DPRINTK("%s : PRM_VC_BYPASS_VAL %X\n", __func__, PRM_VC_BYPASS_VAL); > > + DPRINTK("PRM_IRQST_MPU %X\n", PRM_IRQSTATUS_MPU); > > + > > + while ((PRM_VC_BYPASS_VAL & PRM_VC_BYPASS_VALID) != 0x0) { > > + ret = loop_wait(&loop_cnt, &retries_cnt, 10); > > + if (ret != PRCM_PASS) { > > + printk(KERN_INFO "Loop count exceeded in check SR I2C" > > + "write\n"); > > + return ret; > > + } > > + } > > + > > + omap_udelay(T2_SMPS_UPDATE_DELAY); > > + > > + if (sr_status) { > > + if (vdd == PRCM_VDD1) > > + sr_start_vddautocomap(SR1, target_opp_no); > > + else if (vdd == PRCM_VDD2) > > + sr_start_vddautocomap(SR2, target_opp_no); > > + } > > + > > + return SR_PASS; > > +} > > + > > +/* Sysfs interface to select SR VDD1 auto compensation */ > > +static ssize_t omap_sr_vdd1_autocomp_show(struct kset *subsys, char *buf) > > +{ > > + return sprintf(buf, "%d\n", sr1.is_autocomp_active); > > +} > > + > > +static ssize_t omap_sr_vdd1_autocomp_store(struct kset *subsys, > > + const char *buf, size_t n) > > +{ > > + u32 current_vdd1opp_no; > > + unsigned short value; > > + > > + if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) { > > + printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n"); > > + return -EINVAL; > > + } > > + > > + current_vdd1opp_no = get_opp_no(current_vdd1_opp); > > + > > + if (value == 0) > > + sr_stop_vddautocomap(SR1); > > + else > > + sr_start_vddautocomap(SR1, current_vdd1opp_no); > > + > > + return n; > > +} > > + > > +static struct subsys_attribute sr_vdd1_autocomp = { > > + .attr = { > > + .name = __stringify(sr_vdd1_autocomp), > > + .mode = 0644, > > + }, > > + .show = omap_sr_vdd1_autocomp_show, > > + .store = omap_sr_vdd1_autocomp_store, > > +}; > > + > > +/* Sysfs interface to select SR VDD2 auto compensation */ > > +static ssize_t omap_sr_vdd2_autocomp_show(struct kset *subsys, char *buf) > > +{ > > + return sprintf(buf, "%d\n", sr2.is_autocomp_active); > > +} > > + > > +static ssize_t omap_sr_vdd2_autocomp_store(struct kset *subsys, > > + const char *buf, size_t n) > > +{ > > + u32 current_vdd2opp_no; > > + unsigned short value; > > + > > + if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) { > > + printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n"); > > + return -EINVAL; > > + } > > + > > + current_vdd2opp_no = get_opp_no(current_vdd2_opp); > > + > > + if (value == 0) > > + sr_stop_vddautocomap(SR2); > > + else > > + sr_start_vddautocomap(SR2, current_vdd2opp_no); > > + > > + return n; > > +} > > + > > +static struct subsys_attribute sr_vdd2_autocomp = { > > + .attr = { > > + .name = __stringify(sr_vdd2_autocomp), > > + .mode = 0644, > > + }, > > + .show = omap_sr_vdd2_autocomp_show, > > + .store = omap_sr_vdd2_autocomp_store, > > +}; > > + > > + > > + > > +static int __init omap3_sr_init(void) > > +{ > > + int ret = 0; > > + u8 RdReg; > > + > > +#ifdef CONFIG_ARCH_OMAP34XX > > + sr1.fck = clk_get(NULL, "sr1_fck"); > > + if (IS_ERR(sr1.fck)) > > + printk(KERN_ERR "Could not get sr1_fck\n"); > > + > > + sr2.fck = clk_get(NULL, "sr2_fck"); > > + if (IS_ERR(sr2.fck)) > > + printk(KERN_ERR "Could not get sr2_fck\n"); > > +#endif /* #ifdef CONFIG_ARCH_OMAP34XX */ > > + > > + /* Call the VPConfig, VCConfig, set N Values. */ > > + sr_set_nvalues(&sr1); > > + sr_configure_vp(SR1); > > + > > + sr_set_nvalues(&sr2); > > + sr_configure_vp(SR2); > > + > > + sr_configure_vc(); > > + > > + /* Enable SR on T2 */ > > + ret = t2_in(PM_RECEIVER, &RdReg, R_DCDC_GLOBAL_CFG); > > + RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX; > > + ret |= t2_out(PM_RECEIVER, RdReg, R_DCDC_GLOBAL_CFG); > > + > > + > > + printk(KERN_INFO "SmartReflex driver initialized\n"); > > + > > + ret = subsys_create_file(&power_subsys, &sr_vdd1_autocomp); > > + if (ret) > > + printk(KERN_ERR "subsys_create_file failed: %d\n", ret); > > + > > + ret = subsys_create_file(&power_subsys, &sr_vdd2_autocomp); > > + if (ret) > > + printk(KERN_ERR "subsys_create_file failed: %d\n", ret); > > + > > + return 0; > > +} > > + > > +arch_initcall(omap3_sr_init); > > diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h > > new file mode 100644 > > index 0000000..62907ef > > --- /dev/null > > +++ b/arch/arm/mach-omap2/smartreflex.h > > @@ -0,0 +1,136 @@ > > +/* > > + * linux/arch/arm/mach-omap3/smartreflex.h > > + * > > + * Copyright (C) 2007 Texas Instruments, Inc. > > + * Lesly A M <x0080970@xxxxxx> > > + * > > + * 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. > > + */ > > + > > + > > +/* SR Modules */ > > +#define SR1 1 > > +#define SR2 2 > > + > > +#define SR_FAIL 1 > > +#define SR_PASS 0 > > + > > +#define SR_TRUE 1 > > +#define SR_FALSE 0 > > + > > +#define GAIN_MAXLIMIT 16 > > +#define R_MAXLIMIT 256 > > + > > +#define SR1_CLK_ENABLE (0x1 << 6) > > +#define SR2_CLK_ENABLE (0x1 << 7) > > + > > +/* PRM_VP1_CONFIG */ > > +#define PRM_VP1_CONFIG_ERROROFFSET (0x00 << 24) > > +#define PRM_VP1_CONFIG_ERRORGAIN (0x20 << 16) > > + > > +#define PRM_VP1_CONFIG_INITVOLTAGE (0x30 << 8) /* 1.2 volt */ > > +#define PRM_VP1_CONFIG_TIMEOUTEN (0x1 << 3) > > +#define PRM_VP1_CONFIG_INITVDD (0x1 << 2) > > +#define PRM_VP1_CONFIG_FORCEUPDATE (0x1 << 1) > > +#define PRM_VP1_CONFIG_VPENABLE (0x1 << 0) > > + > > +/* PRM_VP1_VSTEPMIN */ > > +#define PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN (0x01F4 << 8) > > +#define PRM_VP1_VSTEPMIN_VSTEPMIN (0x01 << 0) > > + > > +/* PRM_VP1_VSTEPMAX */ > > +#define PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX (0x01F4 << 8) > > +#define PRM_VP1_VSTEPMAX_VSTEPMAX (0x04 << 0) > > + > > +/* PRM_VP1_VLIMITTO */ > > +#define PRM_VP1_VLIMITTO_VDDMAX (0x3C << 24) > > +#define PRM_VP1_VLIMITTO_VDDMIN (0x0 << 16) > > +#define PRM_VP1_VLIMITTO_TIMEOUT (0xFFFF << 0) > > + > > +/* PRM_VP2_CONFIG */ > > +#define PRM_VP2_CONFIG_ERROROFFSET (0x00 << 24) > > +#define PRM_VP2_CONFIG_ERRORGAIN (0x20 << 16) > > + > > +#define PRM_VP2_CONFIG_INITVOLTAGE (0x30 << 8) /* 1.2 volt */ > > +#define PRM_VP2_CONFIG_TIMEOUTEN (0x1 << 3) > > +#define PRM_VP2_CONFIG_INITVDD (0x1 << 2) > > +#define PRM_VP2_CONFIG_FORCEUPDATE (0x1 << 1) > > +#define PRM_VP2_CONFIG_VPENABLE (0x1 << 0) > > + > > +/* PRM_VP2_VSTEPMIN */ > > +#define PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN (0x01F4 << 8) > > +#define PRM_VP2_VSTEPMIN_VSTEPMIN (0x01 << 0) > > + > > +/* PRM_VP2_VSTEPMAX */ > > +#define PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX (0x01F4 << 8) > > +#define PRM_VP2_VSTEPMAX_VSTEPMAX (0x04 << 0) > > + > > +/* PRM_VP2_VLIMITTO */ > > +#define PRM_VP2_VLIMITTO_VDDMAX (0x2C << 24) > > +#define PRM_VP2_VLIMITTO_VDDMIN (0x0 << 16) > > +#define PRM_VP2_VLIMITTO_TIMEOUT (0xFFFF << 0) > > + > > +/* SRCONFIG */ > > +#define SR1_SRCONFIG_ACCUMDATA (0x1F4 << 22) > > +#define SR2_SRCONFIG_ACCUMDATA (0x1F4 << 22) > > + > > +#define SRCLKLENGTH_12MHZ_SYSCLK 0x3C > > +#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 > > +#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 > > +#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 > > +#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 > > + > > +#define SRCONFIG_SRCLKLENGTH_SHIFT 12 > > +#define SRCONFIG_SENNENABLE_SHIFT 5 > > +#define SRCONFIG_SENPENABLE_SHIFT 3 > > + > > +#define SRCONFIG_SRENABLE (0x01 << 11) > > +#define SRCONFIG_SENENABLE (0x01 << 10) > > +#define SRCONFIG_ERRGEN_EN (0x01 << 9) > > +#define SRCONFIG_MINMAXAVG_EN (0x01 << 8) > > + > > +#define SRCONFIG_DELAYCTRL (0x01 << 2) > > +#define SRCONFIG_CLKCTRL (0x00 << 0) > > + > > +/* AVGWEIGHT */ > > +#define SR1_AVGWEIGHT_SENPAVGWEIGHT (0x03 << 2) > > +#define SR1_AVGWEIGHT_SENNAVGWEIGHT (0x03 << 0) > > + > > +#define SR2_AVGWEIGHT_SENPAVGWEIGHT (0x01 << 2) > > +#define SR2_AVGWEIGHT_SENNAVGWEIGHT (0x01 << 0) > > + > > +/* NVALUERECIPROCAL */ > > +#define NVALUERECIPROCAL_SENPGAIN_SHIFT 20 > > +#define NVALUERECIPROCAL_SENNGAIN_SHIFT 16 > > +#define NVALUERECIPROCAL_RNSENP_SHIFT 8 > > +#define NVALUERECIPROCAL_RNSENN_SHIFT 0 > > + > > +/* ERRCONFIG */ > > +#define SR_CLKACTIVITY_MASK (0x03 << 20) > > +#define SR_ERRWEIGHT_MASK (0x07 << 16) > > +#define SR_ERRMAXLIMIT_MASK (0xFF << 8) > > +#define SR_ERRMINLIMIT_MASK (0xFF << 0) > > + > > +#define SR_CLKACTIVITY_IOFF_FOFF (0x00 << 20) > > +#define SR_CLKACTIVITY_IOFF_FON (0x02 << 20) > > + > > +#define ERRCONFIG_VPBOUNDINTEN (0x1 << 31) > > +#define ERRCONFIG_VPBOUNDINTST (0x1 << 30) > > + > > +#define SR1_ERRWEIGHT (0x07 << 16) > > +#define SR1_ERRMAXLIMIT (0x02 << 8) > > +#define SR1_ERRMINLIMIT (0xFA << 0) > > + > > +#define SR2_ERRWEIGHT (0x07 << 16) > > +#define SR2_ERRMAXLIMIT (0x02 << 8) > > +#define SR2_ERRMINLIMIT (0xF9 << 0) > > + > > +extern u32 current_vdd1_opp; > > +extern u32 current_vdd2_opp; > > +extern struct kset power_subsys; > > + > > +extern inline int loop_wait(u32 *lcnt, u32 *rcnt, u32 delay); > > +extern void omap_udelay(u32 udelay); > > + > > -- > > 1.5.4.3 > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > the body of a message to majordomo@xxxxxxxxxxxxxxx > > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html