Re: [PATCH 1/3] ARM: OMAP: SmartReflex driver, reference source and header files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux