resource_34xx.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,309 行 · 第 1/3 页

C
1,309
字号
				resource_request(vdd1_res,					vdd1_arm_dsp_freq[ind][2]);				break;			}		}	} else if ((type == PRCM_DSPFREQ_CONSTRAINT)) {		for (ind = 0; ind < max_vdd1_opp; ind++) {			if (vdd1_arm_dsp_freq[ind][1] >= target_value) {				resource_request(vdd1_res,					vdd1_arm_dsp_freq[ind][2]);				break;			}		}	} else if (type == PRCM_VDD1_CONSTRAINT) {		if (request_vdd2_co) {			if (vdd2_res == NULL) {				vdd2_res = resource_get("co_fwk", "vdd2_opp");				resource_request(vdd2_res, vdd2_co_val);			}		}		current_vdd1_opp = vdd1_opp_setting(target_value);		if (release_vdd2_co) {			if (vdd2_res != NULL) {				resource_release(vdd2_res);				resource_put(vdd2_res);				vdd2_res = NULL;			}		}	} else if (type == PRCM_VDD2_CONSTRAINT) {		current_vdd2_opp = vdd2_opp_setting(target_value);	}	return 0;}int activate_pd_constraint(struct shared_resource *resp,			   unsigned short current_value,			   unsigned short target_value){	struct res_handle_node *node;	DPRINTK("CUR_VAL = %d, TAR_VAL = %d\n", current_value, target_value);	if (list_empty(&resp->linked_res_handles))		return 0;	node = list_first_entry(&resp->linked_res_handles,				struct res_handle_node,				node);	switch (target_value) {	case CO_LATENCY_ON:		/* Allows only ON power doamin state */		return resource_request(node->handle, POWER_DOMAIN_ON);		break;	case CO_LATENCY_RET:		/* Allows ON and RET power domain states */		return resource_request(node->handle,					POWER_DOMAIN_RET);		break;	case CO_UNUSED:		/* Removing the constraints */		return resource_release(node->handle);		break;	default:		/* do nothing - allows all power domain states */		break;	}	return 0;}/* Validate if the power domain transition from current to target level is*//* valid							     	*/int validate_power_res(struct shared_resource *res,			unsigned short current_level,			unsigned short target_level){	DPRINTK("Current_level = %d, Target_level = %d\n",			current_level, target_level);	if ((target_level >= res->max_levels)) {		DPRINTK("Invalid target_level requested\n");		return -1;	}	/* RET to OFF and OFF to RET transitions not allowed for IVA*/	if (res->prcm_id == DOM_IVA2) {		if ((current_level < POWER_DOMAIN_ON) &&				(target_level != POWER_DOMAIN_ON)) {			DPRINTK("%d to %d transitions for"					" Power Domain IVA are not allowed\n",					current_level, target_level);			return -1;		}	}	return 0;}/* Validate if the logical resource transition is valid */int validate_logical_res(struct shared_resource *res,				unsigned short current_level,				unsigned short target_level){	if (target_level >= res->max_levels)		return -1;	return 0;}int validate_constraint(struct shared_resource *res,				unsigned short current_value,				unsigned short target_value){	if (target_value == DEFAULT_LEVEL)		return 0;	if (res->prcm_id == PRCM_ARMFREQ_CONSTRAINT) {		if ((target_value < min_arm_freq) ||				(target_value > max_arm_freq)) {			printk(KERN_ERR "Invalid ARM frequency requested\n");			return -1;		}	} else if (res->prcm_id == PRCM_DSPFREQ_CONSTRAINT) {		if ((target_value < min_dsp_freq) ||				(target_value > max_dsp_freq)) {			printk(KERN_ERR "Invalid DSP frequency requested\n");			return -1;		}	} else if (res->prcm_id == PRCM_VDD1_CONSTRAINT) {		if ((target_value < min_vdd1_opp) ||				(target_value > max_vdd1_opp)) {			printk(KERN_ERR "Invalid VDD1 OPP requested\n");			return -1;		}	} else if (res->prcm_id == PRCM_VDD2_CONSTRAINT) {		if ((target_value < min_vdd2_opp) ||				(target_value > max_vdd2_opp)) {			printk(KERN_ERR "Invalid VDD2 OPP requested\n");			return -1;		}	}	return 0;}/* Turn off unused power domains during bootup * If OFFMODE macro is enabled, all power domains are turned off during bootup * If OFFMODE macro is not enabled, all power domains except IVA and GFX * are put to retention and IVA,GFX are put to off * NEON is not put to off because it is required by VFP */int turn_power_domains_off(void){	struct shared_resource **resp;	u8 state;	u32 prcmid;	for (resp = res_list; resp < res_list + ARRAY_SIZE(res_list); resp++) {		if (list_empty(&((*resp)->users_list))) {			if ((*resp)->res_type == RES_POWER_DOMAIN) {				prcmid = (*resp)->prcm_id;				prcm_get_power_domain_state(prcmid, &state);				if (state == PRCM_ON) {				if ((prcmid == DOM_IVA2) || (prcmid == DOM_SGX))						state = PRCM_OFF;					else						state = PRCM_RET;					if (prcmid == DOM_NEON) {						if (is_sil_rev_equal_to							(OMAP3430_REV_ES1_0))							state = PRCM_RET;						state = PRCM_ON;					}					prcm_force_power_domain_state						((*resp)->prcm_id, state);				}			}		}	}	return 0;}/* Wrappers to handle Constraints */struct constraint_handle *constraint_get(const char *name,					 struct constraint_id *cnstr_id){	char *id;	struct clk *clk;	switch (cnstr_id->type) {	case RES_CLOCK_RAMPUP_CO:		clk = (struct clk *)cnstr_id->data;			if ((clk == NULL) || IS_ERR(clk))			return ERR_PTR(-ENOENT);		id = id_to_lname[DOMAIN_ID(clk->prcmid) - 1];		break;	case RES_FREQ_CO:		DPRINTK("Freq constraint %s requested\n",			(char *)cnstr_id->data);		if (vdd1_users == 0)			vdd1_res = resource_get("co_fwk", "vdd1_opp");			vdd1_users++;			id = (char *)cnstr_id->data;		break;	default:		id = (char *)cnstr_id->data;		break;	}	/* Just calls the shared resource api */	return (struct constraint_handle *) resource_get(name, id);}EXPORT_SYMBOL(constraint_get);int constraint_set(struct constraint_handle *constraint,					unsigned short constraint_level){	return resource_request((struct res_handle *)constraint,							constraint_level);}EXPORT_SYMBOL(constraint_set);int constraint_remove(struct constraint_handle *constraint){	return resource_release((struct res_handle *)constraint);}EXPORT_SYMBOL(constraint_remove);void constraint_put(struct constraint_handle *constraint){	struct  res_handle *res_h;	res_h = (struct res_handle *)constraint;	if ((strcmp("arm_freq", res_h->res->name) == 0)		|| (strcmp("dsp_freq", res_h->res->name) == 0)) {		vdd1_users--;		if (vdd1_users == 0) {			resource_release(vdd1_res);			resource_put(vdd1_res);			vdd1_res = NULL;		}	}	resource_put((struct res_handle *)constraint);}EXPORT_SYMBOL(constraint_put);void constraint_register_pre_notification(struct constraint_handle *constraint,			 struct notifier_block *nb, unsigned short target_level){	struct  res_handle *res_h;	res_h = (struct res_handle *)constraint;	if (res_h->res->prcm_id == PRCM_ARMFREQ_CONSTRAINT) {		if (!vdd1_arm_prenotifications)			resource_register_pre_notification(vdd1_res,				&nb_arm_freq_prenotify, max_vdd1_opp+1);		atomic_notifier_chain_register(&freq_arm_pre_notifier_list, nb);		vdd1_arm_prenotifications++;	} else if (res_h->res->prcm_id == PRCM_DSPFREQ_CONSTRAINT) {		if (!vdd1_dsp_prenotifications)			resource_register_pre_notification(vdd1_res,				&nb_dsp_freq_prenotify, max_vdd1_opp+1);		atomic_notifier_chain_register(&freq_dsp_pre_notifier_list, nb);		vdd1_dsp_prenotifications++;	} else {		resource_register_pre_notification(			(struct res_handle *)constraint, nb, target_level);	}}EXPORT_SYMBOL(constraint_register_pre_notification);void constraint_register_post_notification(struct constraint_handle *constraint,		struct notifier_block *nb, unsigned short target_level){	struct  res_handle *res_h;	res_h = (struct res_handle *)constraint;	if (res_h->res->prcm_id == PRCM_ARMFREQ_CONSTRAINT) {		if (!vdd1_arm_postnotifications)			resource_register_post_notification(vdd1_res,				&nb_arm_freq_postnotify, max_vdd1_opp+1);		atomic_notifier_chain_register(&freq_arm_post_notifier_list,									nb);		vdd1_arm_postnotifications++;	} else if (res_h->res->prcm_id == PRCM_DSPFREQ_CONSTRAINT) {		if (!vdd1_dsp_postnotifications)			resource_register_post_notification(vdd1_res,				&nb_dsp_freq_postnotify, max_vdd1_opp+1);		atomic_notifier_chain_register(&freq_dsp_post_notifier_list,									nb);		vdd1_dsp_postnotifications++;	} else {		resource_register_post_notification(				(struct res_handle *)constraint,				nb, target_level);	}}EXPORT_SYMBOL(constraint_register_post_notification);void constraint_unregister_pre_notification(		struct constraint_handle *constraint,		struct notifier_block *nb,		 unsigned short target_level){	struct  res_handle *res_h;	res_h = (struct res_handle *)constraint;	if (res_h->res->prcm_id == PRCM_ARMFREQ_CONSTRAINT) {		vdd1_arm_prenotifications--;		atomic_notifier_chain_unregister(&freq_arm_pre_notifier_list,									nb);		if (!vdd1_arm_prenotifications)			resource_unregister_pre_notification(vdd1_res,			&nb_arm_freq_prenotify, max_vdd1_opp+1);	} else if (res_h->res->prcm_id == PRCM_DSPFREQ_CONSTRAINT) {		vdd1_dsp_prenotifications--;		atomic_notifier_chain_unregister(&freq_dsp_pre_notifier_list,									nb);		if (!vdd1_dsp_prenotifications)			resource_unregister_pre_notification(vdd1_res,				&nb_dsp_freq_prenotify, max_vdd1_opp+1);	} else {		resource_unregister_pre_notification(				(struct res_handle *)constraint,				nb, target_level);	}}EXPORT_SYMBOL(constraint_unregister_pre_notification);void constraint_unregister_post_notification(		struct constraint_handle *constraint,		struct notifier_block *nb, unsigned short target_level){	struct  res_handle *res_h;	res_h = (struct res_handle *)constraint;	if (res_h->res->prcm_id == PRCM_ARMFREQ_CONSTRAINT) {		vdd1_arm_postnotifications--;		atomic_notifier_chain_unregister(&freq_arm_post_notifier_list,									nb);		if (!vdd1_arm_postnotifications)			resource_unregister_post_notification(vdd1_res,				&nb_arm_freq_postnotify, max_vdd1_opp+1);	} else if (res_h->res->prcm_id == PRCM_DSPFREQ_CONSTRAINT) {		vdd1_dsp_postnotifications--;		atomic_notifier_chain_unregister(&freq_dsp_post_notifier_list,									nb);		if (!vdd1_dsp_postnotifications)			resource_unregister_post_notification(vdd1_res,				&nb_dsp_freq_postnotify, max_vdd1_opp+1);		} else {		resource_unregister_post_notification(			(struct res_handle *)constraint,							nb, target_level);	}}EXPORT_SYMBOL(constraint_unregister_post_notification);int constraint_get_level(struct constraint_handle *constraint){	return resource_get_level((struct res_handle *)constraint);}EXPORT_SYMBOL(constraint_get_level);#include <linux/proc_fs.h>#include <linux/seq_file.h>static void *omap_shared_res_start(struct seq_file *m, loff_t *pos){	return *pos < 1 ? (void *)1 : NULL;}static void *omap_shared_res_next(struct seq_file *m, void *v, loff_t *pos){	++*pos;	return NULL;}static void omap_shared_res_stop(struct seq_file *m, void *v){}int omap_shared_res_show(struct seq_file *m, void *v){	struct shared_resource **resp;	struct users_list *user;	for (resp = res_list; resp < res_list + ARRAY_SIZE(res_list); resp++) {		seq_printf(m, "Number of users for domain %s: %lu\n",				(*resp)->name, (*resp)->no_of_users);		list_for_each_entry(user, &((*resp)->users_list), node) {			seq_printf(m, "User: %s  Level: %lu\n",					user->usr_name, user->level);		}	}	return 0;}static struct seq_operations omap_shared_res_op = {	.start = omap_shared_res_start,	.next  = omap_shared_res_next,	.stop  = omap_shared_res_stop,	.show  = omap_shared_res_show};static int omap_ck_open(struct inode *inode, struct file *file){	return seq_open(file, &omap_shared_res_op);}static struct file_operations proc_shared_res_ops = {	.open		= omap_ck_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= seq_release,};/* This API creates a proc entry for shared resources. */int proc_entry_create(void){	struct proc_dir_entry *entry;	/* Create a proc entry for shared resources */	entry = create_proc_entry("shared_resources", 0, NULL);	if (entry) {		entry->proc_fops = &proc_shared_res_ops;		printk(KERN_ERR "create_proc_entry succeeded\n");		}	else		printk(KERN_ERR "create_proc_entry failed\n");	return 0;}__initcall(proc_entry_create);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?