pm_34xx.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,647 行 · 第 1/3 页
C
1,647 行
static struct subsys_attribute domain_print = { .attr = { .name = __stringify(debug_domain), .mode = 0644, }, .show = omap_pm_domain_show, .store = omap_pm_domain_store,};/*sysfs interface to chg the frame buffer timer*/static ssize_t omap_pm_fb_timeout_show(struct kset *subsys, char *buf){ return sprintf(buf, "%hu\n", fb_timeout_val);}static ssize_t omap_pm_fb_timeout_store(struct kset *subsys, const char *buf, size_t n){ unsigned short value; if (sscanf(buf, "%hu", &value) != 1) { printk(KERN_ERR "fb_timeout_store: Invalid value\n"); return -EINVAL; } fb_timeout_val = value; set_blank_interval(fb_timeout_val); return n;}static struct subsys_attribute fb_timeout = { .attr = { .name = __stringify(fb_timeout_value), .mode = 0644, }, .show = omap_pm_fb_timeout_show, .store = omap_pm_fb_timeout_store,};/* Sysfs interface to set the opp for vdd1 and vdd2 */static ssize_t omap_pm_vdd1_opp_show(struct kset *subsys, char *buf){ return sprintf(buf, "%x\n", (unsigned int)get_opp_no( current_vdd1_opp));}static ssize_t omap_pm_vdd1_opp_store(struct kset *subsys, const char *buf, size_t n){ sscanf(buf, "%u", &target_opp_no); if ((target_opp_no < 1) || (target_opp_no > 5)) { printk(KERN_ERR "\nError : Invalid OPP value for VDD1.\n"); return -EINVAL; } if (target_opp_no == get_opp_no(current_vdd1_opp)) { DPRINTK("Target and current opp values are same\n"); } else { if (target_opp_no != 1) { if (vdd1_opp_co == NULL) vdd1_opp_co = constraint_get("pm_fwk", &cnstr_id1); constraint_set(vdd1_opp_co, target_opp_no); } else { if (vdd1_opp_co != NULL) { constraint_remove(vdd1_opp_co); constraint_put(vdd1_opp_co); vdd1_opp_co = NULL; } } } return n;}static struct subsys_attribute vdd1_opp = { .attr = { .name = __stringify(vdd1_opp_value), .mode = 0644, }, .show = omap_pm_vdd1_opp_show, .store = omap_pm_vdd1_opp_store,};static ssize_t omap_pm_vdd2_opp_show(struct kset *subsys, char *buf){ return sprintf(buf, "%x\n", (unsigned int)get_opp_no(current_vdd2_opp));}static ssize_t omap_pm_vdd2_opp_store(struct kset *subsys, const char *buf, size_t n){ sscanf(buf, "%u", &target_opp_no); if ((target_opp_no < 1) || (target_opp_no > 3)) { printk(KERN_ERR "\nError : Invalid OPP value for VDD2.\n"); return -EINVAL; } if (target_opp_no == get_opp_no(current_vdd2_opp)) { DPRINTK("Target and current opp values are same\n"); } else { if (target_opp_no != 1) { if (vdd2_opp_co == NULL) vdd2_opp_co = constraint_get("pm_fwk", &cnstr_id2); constraint_set(vdd2_opp_co, target_opp_no); } else { if (vdd2_opp_co != NULL) { constraint_remove(vdd2_opp_co); constraint_put(vdd2_opp_co); vdd2_opp_co = NULL; } } } return n;}static struct subsys_attribute vdd2_opp = { .attr = { .name = __stringify(vdd2_opp_value), .mode = 0644, }, .show = omap_pm_vdd2_opp_show, .store = omap_pm_vdd2_opp_store,};/* PRCM Interrupt Handler */irqreturn_t prcm_interrupt_handler (int irq, void *dev_id){ u32 wkst_wkup = PM_WKST_WKUP; u32 wkst1_core = PM_WKST1_CORE; u32 wkst3_core = PM_WKST3_CORE; u32 wkst_usbhost = PM_WKST_USBHOST; u32 wkst_per = PM_WKST_PER; u32 errst_vc = PRM_VC_TIMEOUTERR_ST | PRM_VC_RAERR_ST | PRM_VC_SAERR_EN; u32 fclk = 0; u32 iclk = 0; if (PM_WKST_WKUP & PM_MPUGRPSEL_WKUP) { /* Resetting UART1 inactivity timeout, during IO_PAD wakeup */ if (wkst_wkup & 0x100) { awake_time_end = jiffies + msecs_to_jiffies(UART_TIME_OUT); } iclk = CM_ICLKEN_WKUP; fclk = CM_FCLKEN_WKUP; CM_ICLKEN_WKUP |= wkst_wkup & PM_MPUGRPSEL_WKUP; CM_FCLKEN_WKUP |= wkst_wkup & PM_MPUGRPSEL_WKUP; PM_WKST_WKUP = wkst_wkup & PM_MPUGRPSEL_WKUP; while (PM_WKST_WKUP & PM_MPUGRPSEL_WKUP); CM_ICLKEN_WKUP = iclk; CM_FCLKEN_WKUP = fclk; } if (PM_WKST1_CORE & PM_MPUGRPSEL1_CORE) { iclk = CM_ICLKEN1_CORE; fclk = CM_FCLKEN1_CORE; CM_ICLKEN1_CORE |= wkst1_core & PM_MPUGRPSEL1_CORE; CM_FCLKEN1_CORE |= wkst1_core & PM_MPUGRPSEL1_CORE; PM_WKST1_CORE = wkst1_core & PM_MPUGRPSEL1_CORE; while (PM_WKST1_CORE & PM_MPUGRPSEL1_CORE); CM_ICLKEN1_CORE = iclk; CM_FCLKEN1_CORE = fclk; } if (PM_WKST3_CORE & PM_MPUGRPSEL3_CORE) { iclk = CM_ICLKEN3_CORE; fclk = CM_FCLKEN3_CORE; CM_ICLKEN3_CORE |= wkst3_core & PM_MPUGRPSEL3_CORE; CM_FCLKEN3_CORE |= wkst3_core & PM_MPUGRPSEL3_CORE; PM_WKST3_CORE = wkst3_core & PM_MPUGRPSEL3_CORE; while (PM_WKST3_CORE & PM_MPUGRPSEL3_CORE); CM_ICLKEN3_CORE = iclk; CM_FCLKEN3_CORE = fclk; } if (PM_WKST_USBHOST & PM_MPUGRPSEL_USBHOST) { iclk = CM_ICLKEN_USBHOST; fclk = CM_FCLKEN_USBHOST; CM_ICLKEN_USBHOST |= wkst_usbhost & PM_MPUGRPSEL_USBHOST; CM_FCLKEN_USBHOST |= wkst_usbhost & PM_MPUGRPSEL_USBHOST; PM_WKST_USBHOST = wkst_usbhost & PM_MPUGRPSEL_USBHOST; while (PM_WKST_USBHOST & PM_MPUGRPSEL_USBHOST); CM_ICLKEN_USBHOST = iclk; CM_FCLKEN_USBHOST = fclk; } if (PM_WKST_PER & PM_MPUGRPSEL_PER) { iclk = CM_ICLKEN_PER; fclk = CM_FCLKEN_PER; CM_ICLKEN_PER |= wkst_per & PM_MPUGRPSEL_PER; CM_FCLKEN_PER |= wkst_per & PM_MPUGRPSEL_PER; PM_WKST_PER = wkst_per & PM_MPUGRPSEL_PER; while (PM_WKST_PER & PM_MPUGRPSEL_PER); CM_ICLKEN_PER = iclk; CM_FCLKEN_PER = fclk; } if (!(wkst_wkup | wkst1_core | wkst3_core | wkst_usbhost | wkst_per)) { if (!(PRM_IRQSTATUS_MPU & errst_vc)) { printk(KERN_ERR "%x,%x,%x,%x\n", PRM_IRQSTATUS_MPU, wkst_wkup, wkst1_core, wkst_per); printk(KERN_ERR "Spurious PRCM interrupt\n"); } } if (PRM_IRQSTATUS_MPU & PRM_VC_TIMEOUTERR_ST) { printk(KERN_ERR "PRCM : Voltage Controller timeout\n"); printk(KERN_ERR "PRM_IRQSTATUS_MPU = 0x%x\n", PRM_IRQSTATUS_MPU) ; printk(KERN_ERR "PRM_VC_TIMEOUTERR_ST = 0x%x\n", PRM_VC_TIMEOUTERR_ST) ; } if (PRM_IRQSTATUS_MPU & PRM_VC_RAERR_ST) { printk(KERN_ERR "PRCM : Voltage Controller register address " "acknowledge error\n"); } if (PRM_IRQSTATUS_MPU & PRM_VC_SAERR_ST) { printk(KERN_ERR "PRCM : Voltage Controller slave address " "acknowledge error\n"); } if (PRM_IRQSTATUS_MPU) { PRM_IRQSTATUS_MPU |= 0x3; while (PRM_IRQSTATUS_MPU); } return IRQ_HANDLED;}#include <linux/proc_fs.h>#include <linux/seq_file.h>static void *omap_pm_prepwst_start(struct seq_file *m, loff_t *pos){ return *pos < 1 ? (void *)1 : NULL;}static void *omap_pm_prepwst_next(struct seq_file *m, void *v, loff_t *pos){ ++*pos; return NULL;}static void omap_pm_prepwst_stop(struct seq_file *m, void *v){}char *pstates [4] = { "OFF", "RET", "INACT", "ON" };int omap_pm_prepwst_show(struct seq_file *m, void *v){ u32 arr_rdptr, arr_cnt; seq_printf(m, "\nPrevious power state for MPU+CORE\n\n"); arr_rdptr = arr_wrptr; arr_cnt = LAST_IDLE_STATE_ARR_SIZE; while (arr_cnt--) { if (arr_rdptr == 0) arr_rdptr = LAST_IDLE_STATE_ARR_SIZE; arr_rdptr--; seq_printf(m, "MPU = %x - %s, CORE = %x - %s, IVA = %x - %s," "fclks: %x, iclks: %x\n", last_idle_state[arr_wrptr].mpu_state, pstates [last_idle_state[arr_wrptr].mpu_state & 0x3], last_idle_state[arr_wrptr].core_state, pstates [last_idle_state[arr_wrptr].core_state & 0x3], last_idle_state[arr_wrptr].iva_state, pstates [last_idle_state[arr_wrptr].iva_state & 0x3], last_idle_state[arr_wrptr].fclks, last_idle_state[arr_wrptr].iclks ); } seq_printf(m, "\nMPU RET CNT = %d, MPU OFF CNT = %d," " CORE RET CNT = %d, CORE OFF CNT = %d\n\n", mpu_ret_cnt, mpu_off_cnt, core_ret_cnt, core_off_cnt); return 0;}static struct seq_operations omap_pm_prepwst_op = { .start = omap_pm_prepwst_start, .next = omap_pm_prepwst_next, .stop = omap_pm_prepwst_stop, .show = omap_pm_prepwst_show};static int omap_pm_prepwst_open(struct inode *inode, struct file *file){ return seq_open(file, &omap_pm_prepwst_op);}static struct file_operations proc_pm_prepwst_ops = { .open = omap_pm_prepwst_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};/* This API creates a proc entry for shared resources. */int create_pmproc_entry(void){ struct proc_dir_entry *entry; /* Create a proc entry for shared resources */ entry = create_proc_entry("pm_prepwst", 0, NULL); if (entry) { entry->proc_fops = &proc_pm_prepwst_ops; printk(KERN_ERR "create_proc_entry succeeded\n"); } else printk(KERN_ERR "create_proc_entry failed\n"); return 0;}int __init omap3_pm_init(void){ int l, m, ret; printk(KERN_ERR "Power Management for TI OMAP.\n"); _omap_sram_idle = omap_sram_push(omap34xx_suspend, omap34xx_suspend_sz); pm_set_ops(&omap_pm_ops); /* In case of cold boot, clear scratchpad */ if (RM_RSTST_CORE & 0x1) clear_scratchpad_contents(); prcm_init(); memret1 = (struct res_handle *)resource_get("corememresret1", "core_mem1ret"); memret2 = (struct res_handle *)resource_get("corememresret2", "core_mem2ret"); logret1 = (struct res_handle *)resource_get("corelogicret", "core_logicret"); /* Registering PRCM Interrupts to MPU, for Wakeup events */ ret = request_irq(PRCM_MPU_IRQ, (irq_handler_t)prcm_interrupt_handler, IRQF_DISABLED, "prcm", NULL); if (ret) { printk(KERN_ERR "request_irq failed to register for 0x%x\n", PRCM_MPU_IRQ); return -1; } /* Adjust the system OPP based during bootup using * KConfig option */ if (p_vdd1_clk == NULL) { p_vdd1_clk = clk_get(NULL, "virt_vdd1_prcm_set"); if (p_vdd1_clk == NULL) { printk(KERN_ERR "Unable to get the VDD1 clk\n"); return -1; } } if (p_vdd2_clk == NULL) { p_vdd2_clk = clk_get(NULL, "virt_vdd2_prcm_set"); if (p_vdd2_clk == NULL) { printk(KERN_ERR "Unable to get the VDD2 clk\n"); return -1; } } /* Configure OPP for VDD1 based on compile time setting */ vdd1_opp_no = PRCM_VDD1_OPP3; vdd2_opp_no = PRCM_VDD2_OPP3; prcm_do_voltage_scaling(PRCM_VDD2_OPP3, PRCM_VDD2_OPP2); /* Request for VDD1 and VDD2 OPP constraints */ /* Currently by default VDD2 OPP level 3 is requested */ if (vdd1_opp_no != PRCM_VDD1_OPP1) { vdd1_opp_co = constraint_get("pm_fwk", &cnstr_id1); constraint_set(vdd1_opp_co, get_opp_no(vdd1_opp_no)); } if (vdd2_opp_no != PRCM_VDD2_OPP1) { vdd2_opp_co = constraint_get("pm_fwk", &cnstr_id2); constraint_set(vdd2_opp_co, get_opp_no(vdd2_opp_no)); } omap_init_power_states(); cpuidle_register_driver(&omap3_idle_driver); PRM_IRQSTATUS_MPU = 0x3FFFFFD; PRM_IRQENABLE_MPU = 0x1; /* Enabling the IO_PAD PRCM interrupts */ PRM_IRQENABLE_MPU |= 0x200; /* Enabling the VOLTAGE CONTROLLER PRCM interrupts */ PRM_IRQENABLE_MPU |= PRM_VC_TIMEOUTERR_EN | PRM_VC_RAERR_EN| PRM_VC_SAERR_EN; l = subsys_create_file(&power_subsys, &sleep_idle_state); if (l) printk(KERN_ERR "subsys_create_file failed: %d\n", l); l = subsys_create_file(&power_subsys, &off_enable); if (l) printk(KERN_ERR "subsys_create_file failed for off: %d\n", l); /*For register dump*/ l = subsys_create_file(&power_subsys, &domain_print); if (l) printk(KERN_ERR "subsys_create_file failed for print: %d\n", l); /* Sysfs entry for setting Display timeout*/ m = subsys_create_file(&power_subsys, &fb_timeout); if (m) printk(KERN_ERR "subsys_create_file failed: %d\n", m); /* Sysfs entry for setting opp for vdd1 */ m = subsys_create_file(&power_subsys, &vdd1_opp); if (m) printk(KERN_ERR "subsys_create_file failed: %d\n", m); /* Sysfs entry for setting opp for vdd2 */ m = subsys_create_file(&power_subsys, &vdd2_opp); if (m) printk(KERN_ERR "subsys_create_file failed: %d\n", m); /* Set the default value of frame buffer timeout*/ set_blank_interval(fb_timeout_val); create_pmproc_entry(); return 0;}/** * clear_scratchpad_contents - Clears the scratchpad contents * * Clears the scratchpad contents in case of cold boot. Called during bootup. */void clear_scratchpad_contents(void){ u32 max_offset = SCRATCHPAD_ROM_OFFSET; u32 offset = 0; u32 v_addr = io_p2v(SCRATCHPAD_ROM); /* Check if it is a cold reboot */ if (PRM_RSTST & 0x1) { for ( ; offset <= max_offset; offset += 0x4) __raw_writel(0x0, (v_addr + offset)); PRM_RSTST |= 0x1; }}/** * save_scratchpad_contents * * Populate the scratchpad structure with restore structure. */void save_scratchpad_contents(void){ u32 *scratchpad_address; u32 *restore_address; u32 *sdram_context_address; /* Get virtual address of SCRATCHPAD */ scratchpad_address = (u32 *) io_p2v(SCRATCHPAD); /* Get Restore pointer to jump to while waking up from OFF */ restore_address = get_restore_pointer(); /* Convert it to physical address */ restore_address = (u32 *) io_v2p(restore_address); /* Get address where registers are saved in SDRAM */ sdram_context_address = (u32 *) io_v2p(context_mem); /* Booting configuration pointer*/ *(scratchpad_address++) = 0x0; /* Public restore pointer */ /* On ES 2.0, if scratchpad is populated with valid * pointer, warm reset does not work * So populate scratchpad restore address only in * cpuidle and suspend calls */ scratchpad_restore_addr = scratchpad_address; restore_pointer_address = (u32) restore_address; *(scratchpad_address++) = 0x0; /* Secure ram restore pointer */ *(scratchpad_address++) = 0x0; /* SDRC Module semaphore */ *(scratchpad_address++) = 0x0; /* PRCM Block Offset */ *(scratchpad_address++) = 0x2C; /* SDRC Block Offset */ *(scratchpad_address++) = 0x64; /* Empty */ /* Offset 0x8*/ *(scratchpad_address++) = 0x0; *(scratchpad_address++) = 0x0; /* Offset 0xC*/ *(scratchpad_address++) = 0x0; /* Offset 0x10*/ *(scratchpad_address++) = 0x0; /* Offset 0x14*/ *(scratchpad_address++) = 0x0; /* Offset 0x18*/ /* PRCM Block */ *(scratchpad_address++) = PRM_CLKSRC_CTRL; *(scratchpad_address++) = PRM_CLKSEL; *(scratchpad_address++) = CM_CLKSEL_CORE; *(scratchpad_address++) = CM_CLKSEL_WKUP; *(scratchpad_address++) = CM_CLKEN_PLL; *(scratchpad_address++) = CM_AUTOIDLE_PLL; *(scratchpad_address++) = CM_CLKSEL1_PLL; *(scratchpad_address++) = CM_CLKSEL2_PLL; *(scratchpad_address++) = CM_CLKSEL3_PLL; *(scratchpad_address++) = CM_CLKEN_PLL_MPU; *(scratchpad_address++) = CM_AUTOIDLE_PLL_MPU; *(scratchpad_address++) = CM_CLKSEL1_PLL_MPU; *(scratchpad_address++) = CM_CLKSEL2_PLL_MPU; *(scratchpad_address++) = 0x0; /* SDRC Block */ *(scratchpad_address++) = ((SDRC_CS_CFG & 0xFFFF) << 16) | (SDRC_SYS_CONFIG & 0xFFFF); *(scratchpad_address++) = ((SDRC_ERR_TYPE & 0xFFFF) << 16) | (SDRC_SHARING & 0xFFFF); *(scratchpad_address++) = SDRC_DLL_A_CTRL; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = SDRC_PWR; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = SDRC_MCFG_0; *(scratchpad_address++) = SDRC_MR0 & 0xFFFF; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = SDRC_ACTIM_CTRL_A_0; *(scratchpad_address++) = SDRC_ACTIM_CTRL_B_0; *(scratchpad_address++) = SDRC_RFR_CTRL_0; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = SDRC_MCFG_1; *(scratchpad_address++) = SDRC_MR1 & 0xFFFF; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = SDRC_ACTIM_CTRL_A_1; *(scratchpad_address++) = SDRC_ACTIM_CTRL_B_1; *(scratchpad_address++) = SDRC_RFR_CTRL_1; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = 0x0; *(scratchpad_address++) = (u32) sdram_context_address;}__initcall(omap3_pm_init);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?