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