void kgsl_pre_hwaccess(struct kgsl_device *device) { BUG_ON(!mutex_is_locked(&device->mutex)); switch (device->state) { case KGSL_STATE_ACTIVE: return; case KGSL_STATE_NAP: case KGSL_STATE_SLEEP: case KGSL_STATE_SLUMBER: kgsl_pwrctrl_wake(device); break; case KGSL_STATE_SUSPEND: kgsl_check_suspended(device); break; case KGSL_STATE_INIT: case KGSL_STATE_HUNG: case KGSL_STATE_DUMP_AND_RECOVER: if (test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags)) break; else KGSL_PWR_ERR(device, "hw access while clocks off from state %d\n", device->state); break; default: KGSL_PWR_ERR(device, "hw access while in unknown state %d\n", device->state); break; } }
void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->power_flags)) { KGSL_PWR_INFO(device, "power off, device %d\n", device->id); if (internal_pwr_rail_ctl(pwr->pwr_rail, false)) { KGSL_DRV_ERR(device, "call internal_pwr_rail_ctl failed\n"); return; } if (pwr->gpu_reg) regulator_disable(pwr->gpu_reg); } } else if (state == KGSL_PWRFLAGS_ON) { if (!test_and_set_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->power_flags)) { KGSL_PWR_INFO(device, "power on, device %d\n", device->id); if (internal_pwr_rail_ctl(pwr->pwr_rail, true)) { KGSL_PWR_ERR(device, "call internal_pwr_rail_ctl failed\n"); return; } if (pwr->gpu_reg) regulator_enable(pwr->gpu_reg); } } }
int kgsl_pwrctrl_init(struct kgsl_device *device) { int i, result = 0; struct clk *clk; struct platform_device *pdev = container_of(device->parentdev, struct platform_device, dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data; struct kgsl_device_pwr_data *pdata_pwr = &pdata_dev->pwr_data; const char *clk_names[KGSL_MAX_CLKS] = {pwr->src_clk_name, pdata_dev->clk.name.clk, pdata_dev->clk.name.pclk, pdata_dev->imem_clk_name.clk, pdata_dev->imem_clk_name.pclk}; /*acquire clocks */ for (i = 1; i < KGSL_MAX_CLKS; i++) { if (clk_names[i]) { clk = clk_get(&pdev->dev, clk_names[i]); if (IS_ERR(clk)) goto clk_err; pwr->grp_clks[i] = clk; } } /* Make sure we have a source clk for freq setting */ clk = clk_get(&pdev->dev, clk_names[0]); pwr->grp_clks[0] = (IS_ERR(clk)) ? pwr->grp_clks[1] : clk; /* put the AXI bus into asynchronous mode with the graphics cores */ if (pdata_pwr->set_grp_async != NULL) pdata_pwr->set_grp_async(); if (pdata_pwr->num_levels > KGSL_MAX_PWRLEVELS) { KGSL_PWR_ERR(device, "invalid power level count: %d\n", pdata_pwr->num_levels); result = -EINVAL; goto done; } pwr->num_pwrlevels = pdata_pwr->num_levels; pwr->active_pwrlevel = pdata_pwr->init_level; for (i = 0; i < pdata_pwr->num_levels; i++) { pwr->pwrlevels[i].gpu_freq = (pdata_pwr->pwrlevel[i].gpu_freq > 0) ? clk_round_rate(pwr->grp_clks[0], pdata_pwr->pwrlevel[i]. gpu_freq) : 0; pwr->pwrlevels[i].bus_freq = pdata_pwr->pwrlevel[i].bus_freq; } /* Do not set_rate for targets in sync with AXI */ if (pwr->pwrlevels[0].gpu_freq > 0) clk_set_rate(pwr->grp_clks[0], pwr-> pwrlevels[pwr->num_pwrlevels - 1].gpu_freq); pwr->gpu_reg = regulator_get(NULL, pwr->regulator_name); if (IS_ERR(pwr->gpu_reg)) pwr->gpu_reg = NULL; pwr->power_flags = 0; pwr->nap_allowed = pdata_pwr->nap_allowed; pwr->interval_timeout = pdata_pwr->idle_timeout; pwr->ebi1_clk = clk_get(NULL, "ebi1_kgsl_clk"); if (IS_ERR(pwr->ebi1_clk)) pwr->ebi1_clk = NULL; else clk_set_rate(pwr->ebi1_clk, pwr->pwrlevels[pwr->active_pwrlevel]. bus_freq); if (pdata_dev->clk.bus_scale_table != NULL) { pwr->pcl = msm_bus_scale_register_client(pdata_dev->clk. bus_scale_table); if (!pwr->pcl) { KGSL_PWR_ERR(device, "msm_bus_scale_register_client failed: " "id %d table %p", device->id, pdata_dev->clk.bus_scale_table); result = -EINVAL; goto done; } } /*acquire interrupt */ pwr->interrupt_num = platform_get_irq_byname(pdev, pwr->irq_name); if (pwr->interrupt_num <= 0) { KGSL_PWR_ERR(device, "platform_get_irq_byname failed: %d\n", pwr->interrupt_num); result = -EINVAL; goto done; } register_early_suspend(&device->display_off); return result; clk_err: result = PTR_ERR(clk); KGSL_PWR_ERR(device, "clk_get(%s) failed: %d\n", clk_names[i], result); done: return result; }