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