smartreflex.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 791 行 · 第 1/2 页
C
791 行
(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", __FUNCTION__, 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; 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"); /* 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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?