1) device power management introduction
three levels of resource management:
clock, power, and valtage
clock:
a) interface clock _ICLK
b) function clock _FCLK
2) module-level clock management
|--master satandby protocol:CM_
__CLKCTRL[x].STBYST
|--slave standby protocol: Cm_
__CLKCTRL[x].IDLEST
3) module wake-up request:
slave module --> wake-up request --> PRCM
PRCM --> activates the module clocks and acknowledges the module wake-up request.
4) clock domain
CM__CLKSTCTRl[x] CLKACTIVITY_
clock domain state transitions
CM__CLKSTCTRL[x] CLKTRCTRL
5) Clock domain HW_ATTO Mode sequences
主要数据结构:
- struct power_state {
-
struct powerdomain *pwrdm;
-
u32 next_state;
-
#ifdef CONFIG_SUSPEND
-
u32 saved_state;
-
u32 saved_logic_state;
-
#endif
-
struct list_head node;
-
};
pwrst_list 构建:
- static int __init omap4_pm_init(void)
-
{
-
int ret;
-
int ram_addr;
-
-
if (!cpu_is_omap44xx())
-
return -ENODEV;
-
-
/*
-
* Keep volt/device off disabled by default
-
* on 446x.
-
*/
-
if (cpu_is_omap446x())
-
volt_off_mode = 0;
-
else
-
volt_off_mode = 1;
-
-
enable_off_mode = 0;
-
-
pr_err("Power Management for TI OMAP4.\n");
-
mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
-
cpu0_pwrdm = pwrdm_lookup("cpu0_pwrdm");
-
cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm");
-
core_pwrdm = pwrdm_lookup("core_pwrdm");
-
per_pwrdm = pwrdm_lookup("l4per_pwrdm");
-
-
-
#ifdef CONFIG_PM
-
prcm_setup_regs();
-
prcm_clear_statdep_regs();
-
-
ret = request_irq(OMAP44XX_IRQ_PRCM,
-
(irq_handler_t)prcm_interrupt_handler,
-
IRQF_DISABLED, "prcm", NULL);
-
if (ret) {
-
printk(KERN_ERR "request_irq failed to register for 0x%x\n",
-
OMAP44XX_IRQ_PRCM);
-
goto err2;
-
}
-
-
so_ram_address = (void *)dma_alloc_so_coherent(NULL, 1024,
-
(dma_addr_t *)&ram_addr, GFP_KERNEL);
-
-
if (!so_ram_address) {
-
printk ("omap4_pm_init: failed to allocate SO mem.\n");
-
return -ENOMEM;
-
}
-
-
ret = pwrdm_for_each(pwrdms_setup, NULL); //对于每个power domain 创建power stat
-
if (ret) {
-
pr_err("Failed to setup powerdomains\n");
-
goto err2;
-
}
-
-
mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
-
if (!mpu_pwrdm) {
-
printk(KERN_ERR "Failed to get lookup for MPU pwrdm's\n");
-
goto err2;
-
}
-
-
(void) clkdm_for_each(clkdms_setup, NULL);
-
-
/* Get handles for VDD's for enabling/disabling SR */
-
vdd_mpu = omap_voltage_domain_get("mpu");
-
if (IS_ERR(vdd_mpu)) {
-
printk(KERN_ERR "Failed to get handle for VDD MPU\n");
-
goto err2;
-
}
-
-
vdd_iva = omap_voltage_domain_get("iva");
-
if (IS_ERR(vdd_iva)) {
-
printk(KERN_ERR "Failed to get handle for VDD IVA\n");
-
goto err2;
-
}
-
-
vdd_core = omap_voltage_domain_get("core");
-
if (IS_ERR(vdd_core)) {
-
printk(KERN_ERR "Failed to get handle for VDD CORE\n");
-
goto err2;
-
}
-
-
omap4_mpuss_init();
-
omap4_pm_off_mode_enable(enable_off_mode);
-
#endif
-
-
#ifdef CONFIG_SUSPEND
-
suspend_set_ops(&omap_pm_ops);
-
#endif /* CONFIG_SUSPEND */
-
-
omap4_idle_init();
-
omap4_trigger_ioctrl();
-
-
err2:
-
return ret;
-
}
- static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
-
{
-
struct power_state *pwrst;
-
-
if (!pwrdm->pwrsts)
-
return 0;
-
-
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
-
if (!pwrst)
-
return -ENOMEM;
-
pwrst->pwrdm = pwrdm;
-
if ((!strcmp(pwrdm->name, mpu_pwrdm->name)) ||
-
(!strcmp(pwrdm->name, core_pwrdm->name)) ||
-
(!strcmp(pwrdm->name, cpu0_pwrdm->name)) ||
-
(!strcmp(pwrdm->name, cpu1_pwrdm->name)))
-
pwrst->next_state = PWRDM_POWER_ON; //
-
else
-
pwrst->next_state = PWRDM_POWER_RET;
-
list_add(&pwrst->node, &pwrst_list);
-
/* 核心的power domain 的电源状态设置为 PWRDM_POWER_ON, 其他的设置成 PWRDM_POWER_RET × /
-
return omap4_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-
}
- omap4 power domain 的定义
- static struct powerdomain *powerdomains_omap[] __initdata = {
-
-
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
&wkup_omap2_pwrdm,
-
&gfx_omap2_pwrdm,
-
#endif
-
-
#ifdef CONFIG_ARCH_OMAP2
-
&dsp_pwrdm,
-
&mpu_24xx_pwrdm,
-
&core_24xx_pwrdm,
-
#endif
-
-
#ifdef CONFIG_ARCH_OMAP2430
-
&mdm_pwrdm,
-
#endif
-
-
#ifdef CONFIG_ARCH_OMAP3
-
&iva2_pwrdm,
-
&mpu_3xxx_pwrdm,
-
&neon_pwrdm,
-
&core_3xxx_pre_es3_1_pwrdm,
-
&core_3xxx_es3_1_pwrdm,
-
&cam_pwrdm,
-
&dss_pwrdm,
-
&per_pwrdm,
-
&emu_pwrdm,
-
&sgx_pwrdm,
-
&usbhost_pwrdm,
-
&dpll1_pwrdm,
-
&dpll2_pwrdm,
-
&dpll3_pwrdm,
-
&dpll4_pwrdm,
-
&dpll5_pwrdm,
-
#endif
-
-
#ifdef CONFIG_ARCH_OMAP4
-
&core_44xx_pwrdm,
-
&gfx_44xx_pwrdm,
-
&abe_44xx_pwrdm,
-
&dss_44xx_pwrdm,
-
&tesla_44xx_pwrdm,
-
&wkup_44xx_pwrdm,
-
&cpu0_44xx_pwrdm,
-
&cpu1_44xx_pwrdm,
-
&emu_44xx_pwrdm,
-
&mpu_443x_pwrdm,
-
&mpu_446x_pwrdm,
-
&ivahd_44xx_pwrdm,
-
&cam_44xx_pwrdm,
-
&l3init_44xx_pwrdm,
-
&l4per_44xx_pwrdm,
-
&always_on_core_44xx_pwrdm,
-
&cefuse_44xx_pwrdm,
-
#endif
-
NULL
-
};
power domain list 的构建:
static void __init omap_4430sdp_init_irq(void) 调用
void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1)
调用
pwrdm_init(powerdomains_omap, &omap4_pwrdm_functions);
- void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_functions * custom_funcs)
-
{
-
struct powerdomain **p = NULL;
-
-
/*Initialise the global latency constraint mutex */
-
mutex_init(&global_wakeuplat_mutex);
-
-
if (!custom_funcs) {
-
printk(KERN_ERR "No custom pwrdm functions registered\n");
-
BUG();
-
}
-
-
arch_pwrdm = custom_funcs;
-
-
if (pwrdm_list) {
-
for (p = pwrdm_list; *p; p++)
-
_pwrdm_register(*p); //这个函数将把list 建起了
-
}
-
}
阅读(1219) | 评论(0) | 转发(0) |