/* * linux/arch/arm/mach-omap3/smartreflex.c * * OMAP34XX SmartReflex Voltage Control * * Copyright (C) 2008 Nokia Corporation * Kalle Jokiniemi * * Copyright (C) 2007 Texas Instruments, Inc. * Lesly A M * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "prm.h" #include "smartreflex.h" #include "prm-regbits-34xx.h" /* XXX: These should be relocated where-ever the OPP implementation will be */ u32 current_vdd1_opp; u32 current_vdd2_opp; struct omap_sr { int srid; int is_sr_reset; int is_autocomp_active; struct clk *clk; u32 clk_length; u32 req_opp_no; u32 opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue; u32 opp5_nvalue; u32 senp_mod, senn_mod; void __iomem *srbase_addr; void __iomem *vpbase_addr; }; #define SR_REGADDR(offs) (sr->srbase_addr + offset) static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) { __raw_writel(value, SR_REGADDR(offset)); } static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask, u32 value) { u32 reg_val; reg_val = __raw_readl(SR_REGADDR(offset)); reg_val &= ~mask; reg_val |= value; __raw_writel(reg_val, SR_REGADDR(offset)); } static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset) { return __raw_readl(SR_REGADDR(offset)); } static int sr_clk_enable(struct omap_sr *sr) { if (clk_enable(sr->clk) != 0) { printk(KERN_ERR "Could not enable %s\n", sr->clk->name); return -1; } /* set fclk- active , iclk- idle */ sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK, SR_CLKACTIVITY_IOFF_FON); return 0; } static void 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->clk); sr->is_sr_reset = 1; } static struct omap_sr sr1 = { .srid = SR1, .is_sr_reset = 1, .is_autocomp_active = 0, .clk_length = 0, .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE), }; static struct omap_sr sr2 = { .srid = SR2, .is_sr_reset = 1, .is_autocomp_active = 0, .clk_length = 0, .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE), }; 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 u32 cal_test_nvalue(u32 sennval, u32 senpval) { u32 senpgain, senngain; u32 rnsenp, rnsenn; /* Calculating the gain and reciprocal of the SenN and SenP values */ cal_reciprocal(senpval, &senpgain, &rnsenp); cal_reciprocal(sennval, &senngain, &rnsenn); return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) | (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) | (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) | (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT)); } static void sr_set_clk_length(struct omap_sr *sr) { struct clk *osc_sys_ck; u32 sys_clk = 0; osc_sys_ck = clk_get(NULL, "osc_sys_ck"); sys_clk = clk_get_rate(osc_sys_ck); clk_put(osc_sys_ck); switch (sys_clk) { case 12000000: sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK; break; case 13000000: sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK; break; case 19200000: sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK; break; case 26000000: sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK; break; case 38400000: sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK; break; default : printk(KERN_ERR "Invalid sysclk value: %d\n", sys_clk); break; } } static void sr_set_efuse_nvalues(struct omap_sr *sr) { if (sr->srid == SR1) { sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) & OMAP343X_SR1_SENNENABLE_MASK) >> OMAP343X_SR1_SENNENABLE_SHIFT; sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) & OMAP343X_SR1_SENPENABLE_MASK) >> OMAP343X_SR1_SENPENABLE_SHIFT; sr->opp5_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP5_VDD1); sr->opp4_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP4_VDD1); sr->opp3_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP3_VDD1); sr->opp2_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP2_VDD1); sr->opp1_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP1_VDD1); } else if (sr->srid == SR2) { sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) & OMAP343X_SR2_SENNENABLE_MASK) >> OMAP343X_SR2_SENNENABLE_SHIFT; sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) & OMAP343X_SR2_SENPENABLE_MASK) >> OMAP343X_SR2_SENPENABLE_SHIFT; sr->opp3_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP3_VDD2); sr->opp2_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP2_VDD2); sr->opp1_nvalue = omap_ctrl_readl( OMAP343X_CONTROL_FUSE_OPP1_VDD2); } } /* Hard coded nvalues for testing purposes, may cause device to hang! */ static void sr_set_testing_nvalues(struct omap_sr *sr) { if (sr->srid == SR1) { sr->senp_mod = 0x03; /* SenN-M5 enabled */ sr->senn_mod = 0x03; /* calculate nvalues for each opp */ sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330); sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0); sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200); sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0); sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100); } else if (sr->srid == SR2) { sr->senp_mod = 0x03; sr->senn_mod = 0x03; sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200); sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0); sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d); } } static void sr_set_nvalues(struct omap_sr *sr) { if (SR_TESTING_NVALUES) sr_set_testing_nvalues(sr); else sr_set_efuse_nvalues(sr); } 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_write_mod_reg(vpconfig, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); prm_write_mod_reg(PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN | PRM_VP1_VSTEPMIN_VSTEPMIN, OMAP3430_GR_MOD, OMAP3_PRM_VP1_VSTEPMIN_OFFSET); prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX | PRM_VP1_VSTEPMAX_VSTEPMAX, OMAP3430_GR_MOD, OMAP3_PRM_VP1_VSTEPMAX_OFFSET); prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX | PRM_VP1_VLIMITTO_VDDMIN | PRM_VP1_VLIMITTO_TIMEOUT, OMAP3430_GR_MOD, OMAP3_PRM_VP1_VLIMITTO_OFFSET); /* Trigger initVDD value copy to voltage processor */ prm_set_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); /* Clear initVDD copy trigger bit */ prm_clear_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); } else if (srid == SR2) { vpconfig = PRM_VP2_CONFIG_ERROROFFSET | PRM_VP2_CONFIG_ERRORGAIN | PRM_VP2_CONFIG_INITVOLTAGE | PRM_VP2_CONFIG_TIMEOUTEN; prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); prm_write_mod_reg(PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN | PRM_VP2_VSTEPMIN_VSTEPMIN, OMAP3430_GR_MOD, OMAP3_PRM_VP2_VSTEPMIN_OFFSET); prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX | PRM_VP2_VSTEPMAX_VSTEPMAX, OMAP3430_GR_MOD, OMAP3_PRM_VP2_VSTEPMAX_OFFSET); prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX | PRM_VP2_VLIMITTO_VDDMIN | PRM_VP2_VLIMITTO_TIMEOUT, OMAP3430_GR_MOD, OMAP3_PRM_VP2_VLIMITTO_OFFSET); /* Trigger initVDD value copy to voltage processor */ prm_set_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); /* Reset initVDD copy trigger bit */ prm_clear_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); } } static void sr_configure(struct omap_sr *sr) { u32 sr_config; u32 senp_en , senn_en; if (sr->clk_length == 0) sr_set_clk_length(sr); senp_en = sr->senp_mod; senn_en = sr->senn_mod; 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 int sr_enable(struct omap_sr *sr, u32 target_opp_no) { u32 nvalue_reciprocal; 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; } } if (nvalue_reciprocal == 0) { printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n", target_opp_no); return SR_FALSE; } 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_set_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); } else if (sr->srid == SR2) { /* Enable VP2 */ prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); } /* SRCONFIG - enable SR */ sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); return SR_TRUE; } 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) { /* Disable VP1 */ prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); } else if (sr->srid == SR2) { /* Disable VP2 */ prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); } } 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) printk(KERN_WARNING "SR%d: VDD autocomp is already active\n", srid); sr->is_autocomp_active = 1; if (!sr_enable(sr, target_opp_no)) { printk(KERN_WARNING "SR%d: VDD autocomp not activated\n", srid); sr->is_autocomp_active = 0; if (sr->is_sr_reset == 1) sr_clk_disable(sr); } } 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 { printk(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) { /* Enable SR clks */ sr_clk_enable(sr); if (srid == SR1) target_opp_no = get_opp_no(current_vdd1_opp); else if (srid == SR2) target_opp_no = get_opp_no(current_vdd2_opp); sr_configure(sr); if (!sr_enable(sr, target_opp_no)) sr_clk_disable(sr); } } } 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 (sr->is_sr_reset == 0) { sr->is_sr_reset = 1; /* SRCONFIG - disable SR */ sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE); /* Disable SR clk */ sr_clk_disable(sr); if (sr->srid == SR1) { /* Disable VP1 */ prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP1_CONFIG_OFFSET); } else if (sr->srid == SR2) { /* Disable VP2 */ prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD, OMAP3_PRM_VP2_CONFIG_OFFSET); } } } } /* Voltage Scaling using SR VCBYPASS */ int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel) { 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_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK, (vsel << OMAP3430_VC_CMD_ON_SHIFT), OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_0_OFFSET); reg_addr = R_VDD1_SR_CONTROL; } else if (vdd == PRCM_VDD2) { sr_status = sr_stop_vddautocomap(SR2); prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK, (vsel << OMAP3430_VC_CMD_ON_SHIFT), OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_1_OFFSET); reg_addr = R_VDD2_SR_CONTROL; } vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) | (reg_addr << OMAP3430_REGADDR_SHIFT) | (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT); prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD, OMAP3_PRM_VC_BYPASS_VAL_OFFSET); vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD, OMAP3_PRM_VC_BYPASS_VAL_OFFSET); while ((vc_bypass_value & OMAP3430_VALID) != 0x0) { loop_cnt++; if (retries_cnt > 10) { printk(KERN_INFO "Loop count exceeded in check SR I2C" "write\n"); return SR_FAIL; } if (loop_cnt > 50) { retries_cnt++; loop_cnt = 0; udelay(10); } vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_VC_BYPASS_VAL_OFFSET); } 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 kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", sr1.is_autocomp_active); } static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj, struct kobj_attribute *attr, 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 kobj_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 kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", sr2.is_autocomp_active); } static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj, struct kobj_attribute *attr, 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 kobj_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; if (omap_rev() > OMAP3430_REV_ES1_0) { current_vdd1_opp = PRCM_VDD1_OPP3; current_vdd2_opp = PRCM_VDD2_OPP3; } else { current_vdd1_opp = PRCM_VDD1_OPP1; current_vdd2_opp = PRCM_VDD1_OPP1; } if (cpu_is_omap34xx()) { sr1.clk = clk_get(NULL, "sr1_fck"); sr2.clk = clk_get(NULL, "sr2_fck"); } sr_set_clk_length(&sr1); sr_set_clk_length(&sr2); /* Call the VPConfig, VCConfig, set N Values. */ sr_set_nvalues(&sr1); sr_configure_vp(SR1); sr_set_nvalues(&sr2); sr_configure_vp(SR2); /* Enable SR on T2 */ ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg, R_DCDC_GLOBAL_CFG); RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX; ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg, R_DCDC_GLOBAL_CFG); printk(KERN_INFO "SmartReflex driver initialized\n"); ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr); if (ret) printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr); if (ret) printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); return 0; } late_initcall(omap3_sr_init);