void mali_platform_power_mode_change(mali_power_mode power_mode) { unsigned long flags; switch (power_mode) { case MALI_POWER_MODE_ON: MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", atomic_read((atomic_t *)&bPoweroff) ? "powering on" : "already on")); if (atomic_read((atomic_t *)&bPoweroff) == 1) { MALI_DEBUG_PRINT(3,("[+]MFG enable_clock \n")); mfg_pwr_lock(flags); if (!clock_is_on(MT_CG_MFG_G3D)) { enable_clock(MT_CG_DISP0_SMI_COMMON, "MFG"); enable_clock(MT_CG_MFG_G3D, "MFG"); } mfg_pwr_unlock(flags); MALI_DEBUG_PRINT(3,("[-]MFG enable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 500, 1200/1000, 0, 0, 0); #endif atomic_set((atomic_t *)&bPoweroff, 0); } break; case MALI_POWER_MODE_LIGHT_SLEEP: case MALI_POWER_MODE_DEEP_SLEEP: MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", atomic_read((atomic_t *)&bPoweroff) ? "already off" : "powering off")); if (atomic_read((atomic_t *)&bPoweroff) == 0) { MALI_DEBUG_PRINT(3,("[+]MFG disable_clock \n")); mfg_pwr_lock(flags); if (clock_is_on(MT_CG_MFG_G3D)) { disable_clock(MT_CG_MFG_G3D, "MFG"); disable_clock(MT_CG_DISP0_SMI_COMMON, "MFG"); } mfg_pwr_unlock(flags); MALI_DEBUG_PRINT(3,("[-]MFG disable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif atomic_set((atomic_t *)&bPoweroff, 1); } break; } }
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args) { _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; MALI_IGNORE(event); /* event is not used for release code, and that is OK */ #if defined(CONFIG_MALI400_PROFILING) /* * Manually generate user space events in kernel space. * This saves user space from calling kernel space twice in this case. * We just need to remember to add pid and tid manually. */ if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT) { _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); } if (event==_MALI_UK_VSYNC_EVENT_END_WAIT) { _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC, _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); } #endif MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event)); MALI_SUCCESS; }
_mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode) { switch (power_mode) { case MALI_POWER_MODE_ON: MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", nPowermode ? "powering on" : "already on")); if (nPowermode == MALI_POWER_MODE_LIGHT_SLEEP || nPowermode == MALI_POWER_MODE_DEEP_SLEEP) { #if !defined(CONFIG_PM_RUNTIME) g3d_power_domain_control(1); #endif MALI_DEBUG_PRINT(4, ("enable clock\n")); enable_mali_clocks(dev); if (nPowermode == MALI_POWER_MODE_DEEP_SLEEP) { #ifdef CONFIG_MALI_DVFS mali_devfreq = NULL; if (!mali_devfreq_add(dev)) MALI_PRINTF(("failed to mali_devfreq_add()\n")); #endif } #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); #endif nPowermode = power_mode; } break; case MALI_POWER_MODE_DEEP_SLEEP: #ifdef CONFIG_MALI_DVFS mali_devfreq_remove(); #endif case MALI_POWER_MODE_LIGHT_SLEEP: MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", nPowermode ? "already off" : "powering off")); if (nPowermode == MALI_POWER_MODE_ON) { disable_mali_clocks(); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif #if !defined(CONFIG_PM_RUNTIME) g3d_power_domain_control(0); #endif nPowermode = power_mode; } break; } MALI_SUCCESS; }
void mali_platform_power_mode_change(mali_power_mode power_mode) { unsigned long flags; switch (power_mode) { case MALI_POWER_MODE_ON: MALI_DEBUG_PRINT(4, ("[+] MFG enable_clock \n")); spin_lock_irqsave(&mali_pwr_lock, flags); if (!clock_is_on(MT_CG_BG3D)) { enable_clock(MT_CG_BG3D, "MFG"); } spin_unlock_irqrestore(&mali_pwr_lock, flags); atomic_set(&g_is_power_enabled, 1); mali_dispatch_dvfs_work(); MALI_DEBUG_PRINT(4, ("[-] MFG enable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 500, 1200 / 1000, 0, 0, 0); #endif break; case MALI_POWER_MODE_LIGHT_SLEEP: case MALI_POWER_MODE_DEEP_SLEEP: MALI_DEBUG_PRINT(4, ("[+] MFG disable_clock \n")); atomic_set(&g_is_power_enabled, 0); mali_cancel_dvfs_work(); spin_lock_irqsave(&mali_pwr_lock, flags); if (clock_is_on(MT_CG_BG3D)) { disable_clock(MT_CG_BG3D, "MFG"); mtk_set_input_boost_duration(0); } spin_unlock_irqrestore(&mali_pwr_lock, flags); MALI_DEBUG_PRINT(4, ("[-] MFG disable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif break; } }
_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) { switch (power_mode) { case MALI_POWER_MODE_ON: MALI_DEBUG_PRINT(1, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", bPoweroff ? "powering on" : "already on")); if (bPoweroff == 1) { /** If run time power management is used, donot call this function */ #ifndef CONFIG_PM_RUNTIME g3d_power_domain_control(1); #endif MALI_DEBUG_PRINT(4,("enable clock \n")); enable_mali_clocks(); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); #endif //MALI_PRINTF(("Mali Platform powered up")); gpu_power_state=1; bPoweroff=0; } break; case MALI_POWER_MODE_LIGHT_SLEEP: case MALI_POWER_MODE_DEEP_SLEEP: MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", bPoweroff ? "already off" : "powering off")); if (bPoweroff == 0) { disable_mali_clocks(); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif #ifndef CONFIG_PM_RUNTIME g3d_power_domain_control(0); #endif //MALI_PRINTF(("Mali Platform powered down")); gpu_power_state=0; bPoweroff=1; } break; } MALI_SUCCESS; }
void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) { u32 irq_readout; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); _mali_osk_write_mem_barrier(); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); #endif } }
void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) { u32 irq_readout; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); _mali_osk_write_mem_barrier(); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); #endif } /* * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. * A timeout or a page fault on Mali-200 PP core can cause this behaviour. */ }
/* ------------- interrupt handling below ------------------ */ static _mali_osk_errcode_t mali_pp_upper_half(void *data) { struct mali_pp_core *core = (struct mali_pp_core *)data; u32 irq_readout; #if !defined(MSTAR_RIU_ENABLED) || (MSTAR_RIU_ADDRESS_TYPE == 32) irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); #else irq_readout = mali_hw_core_register_read_no_lock(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); #endif if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) { /* Mask out all IRQs from this core until IRQ is handled */ #if !defined(MSTAR_RIU_ENABLED) || (MSTAR_RIU_ADDRESS_TYPE == 32) mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); #else mali_hw_core_register_write_no_lock(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); #endif #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); #endif /* We do need to handle this in a bottom half */ _mali_osk_irq_schedulework(core->irq); return _MALI_OSK_ERR_OK; } return _MALI_OSK_ERR_FAULT; }
_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) { /* Always add process and thread identificator in the first two data elements for events from user space */ _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); return _MALI_OSK_ERR_OK; }
_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) { _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); return _MALI_OSK_ERR_OK; }
inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) { u32 cur_index = _mali_osk_atomic_inc_return(&profile_insert_index) - 1; #if MALI_TRACEPOINTS_ENABLED _mali_osk_profiling_add_event(event_id, data0); #endif if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count) { /* * Not in recording mode, or buffer is full * Decrement index again, and early out */ _mali_osk_atomic_dec(&profile_insert_index); return _MALI_OSK_ERR_FAULT; } profile_entries[cur_index].timestamp = _mali_timestamp_get(); profile_entries[cur_index].event_id = event_id; profile_entries[cur_index].data[0] = data0; profile_entries[cur_index].data[1] = data1; profile_entries[cur_index].data[2] = data2; profile_entries[cur_index].data[3] = data3; profile_entries[cur_index].data[4] = data4; _mali_osk_atomic_inc(&profile_entries_written); return _MALI_OSK_ERR_OK; }
static _mali_osk_errcode_t mali_gp_upper_half(void *data) { struct mali_gp_core *core = (struct mali_gp_core *)data; u32 irq_readout = 0; #if MALI_SHARED_INTERRUPTS mali_pm_lock(); if (MALI_TRUE == mali_pm_is_powered_on()) { #endif irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); #if MALI_SHARED_INTERRUPTS } mali_pm_unlock(); #endif if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); #endif _mali_osk_irq_schedulework(core->irq); return _MALI_OSK_ERR_OK; } return _MALI_OSK_ERR_FAULT; }
void mali_regulator_set_voltage(int min_uV, int max_uV) { int voltage; #if !MALI_DVFS_ENABLED min_uV = mali_gpu_vol; max_uV = mali_gpu_vol; #endif /* #if MALI_VOLTAGE_LOCK if (mali_vol_lock_flag == MALI_FALSE) { if (min_uV < MALI_BOTTOMLOCK_VOL || max_uV < MALI_BOTTOMLOCK_VOL) { min_uV = MALI_BOTTOMLOCK_VOL; max_uV = MALI_BOTTOMLOCK_VOL; } } else if (_mali_osk_atomic_read(&voltage_lock_status) > 0 ) { if (min_uV < mali_lock_vol || max_uV < mali_lock_vol) { #if MALI_DVFS_ENABLED int mali_vol_get; mali_vol_get = mali_vol_get_from_table(mali_lock_vol); if (mali_vol_get) { min_uV = mali_vol_get; max_uV = mali_vol_get; } #else min_uV = mali_lock_vol; max_uV = mali_lock_vol; #endif } } #endif */ _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); if( IS_ERR_OR_NULL(g3d_regulator) ) { MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); return; } MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); regulator_set_voltage(g3d_regulator,min_uV,max_uV); voltage = regulator_get_voltage(g3d_regulator); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED gVolt = voltage/1000; _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gFreq, gVolt, 0, 0, 0); #endif mali_gpu_vol = voltage; MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); }
void mali_regulator_set_voltage(int min_uV, int max_uV) { int voltage; #if !MALI_DVFS_ENABLED min_uV = mali_gpu_vol; max_uV = mali_gpu_vol; #endif _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); if( IS_ERR_OR_NULL(g3d_regulator) ) { MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); return; } MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, min_uV, max_uV, 1, 0, 0); #endif regulator_set_voltage(g3d_regulator,min_uV,max_uV); voltage = regulator_get_voltage(g3d_regulator); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, voltage, 0, 2, 0, 0); #endif mali_gpu_vol = voltage; MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); }
int mali_light_resume(struct device *device) { int ret = 0; ret = mali_clock_critical(mali_cri_light_resume, (size_t)device); #ifdef CONFIG_MALI400_PROFILING _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, get_current_frequency(), 0, 0, 0, 0); #endif return ret; }
int mali_light_suspend(struct device *device) { int ret = 0; #ifdef CONFIG_MALI400_PROFILING _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif /* clock scaling. Kasin..*/ ret = mali_clock_critical(mali_cri_light_suspend, (size_t)device); return ret; }
/* * Always give full power when start a new period, * if mali dvfs enabled, for performance consideration */ void mali_dvfs_policy_new_period(void) { /* Always give full power when start a new period */ unsigned int cur_clk_step = 0; cur_clk_step = mali_gpu_get_freq(); if (cur_clk_step != (gpu_clk->num_of_steps - 1)) { mali_gpu_set_freq(gpu_clk->num_of_steps - 1); _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gpu_clk->item[gpu_clk->num_of_steps - 1].clock, gpu_clk->item[gpu_clk->num_of_steps - 1].vol / 1000, 0, 0, 0); } }
static void do_scaling(struct work_struct *work) { mali_dvfs_threshold_table * pdvfs = pmali_plat->dvfs_table; int err = mali_perf_set_num_pp_cores(num_cores_enabled); scalingdbg(1, "set pp cores to %d\n", num_cores_enabled); MALI_DEBUG_ASSERT(0 == err); MALI_IGNORE(err); scalingdbg(1, "pdvfs[%d].freq_index=%d, pdvfs[%d].freq_index=%d\n", currentStep, pdvfs[currentStep].freq_index, lastStep, pdvfs[lastStep].freq_index); mali_clk_exected(); #ifdef CONFIG_MALI400_PROFILING _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, get_current_frequency(), 0, 0, 0, 0); #endif }
void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data) { #ifndef CONFIG_MALI_DVFS int ret = 0; int pp_change_flag = 0; u32 next_idx = 0; #if LOG_MALI_SCALING u32 last_pp = num_cores_enabled; #endif mali_decide_next_status(data, &next_idx, &pp_change_flag); if (pp_change_flag == 1) ret = enable_pp_cores(pmali_plat->sc_mpp); else if (pp_change_flag == 2) ret = enable_one_core(); else if (pp_change_flag == -1) { ret = disable_one_core(); } #if LOG_MALI_SCALING if (pp_change_flag || (next_idx != currentStep)) trace_utilization(data, currentStep, next_idx, last_pp, num_cores_enabled); #endif if (next_idx != currentStep) { ret = 1; currentStep = next_idx; } if (ret == 1) schedule_work(&wq_work); #ifdef CONFIG_MALI400_PROFILING else _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, get_current_frequency(), 0, 0, 0, 0); #endif #endif }
static void do_scaling(struct work_struct *work) { mali_dvfs_threshold_table * pdvfs = pmali_plat->dvfs_table; int err = mali_perf_set_num_pp_cores(num_cores_enabled); MALI_DEBUG_ASSERT(0 == err); MALI_IGNORE(err); if (pdvfs[currentStep].freq_index != pdvfs[lastStep].freq_index) { mali_dev_pause(); mali_clock_set(pdvfs[currentStep].freq_index); mali_dev_resume(); lastStep = currentStep; } #ifdef CONFIG_MALI400_PROFILING _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, get_current_frequency(), 0, 0, 0, 0); #endif }
int mali_light_suspend(struct device *device) { int ret = 0; #ifdef CONFIG_MALI400_PROFILING _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif if (NULL != device->driver && NULL != device->driver->pm && NULL != device->driver->pm->runtime_suspend) { /* Need to notify Mali driver about this event */ ret = device->driver->pm->runtime_suspend(device); } /* clock scaling. Kasin..*/ mali_clock_critical(mali_cri_pmu_on_off, 0); disable_clock(); return ret; }
/* ------------- interrupt handling below ------------------ */ static _mali_osk_errcode_t mali_gp_upper_half(void *data) { struct mali_gp_core *core = (struct mali_gp_core *)data; u32 irq_readout; irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) { /* Mask out all IRQs from this core until IRQ is handled */ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); #endif /* We do need to handle this in a bottom half */ _mali_osk_irq_schedulework(core->irq); return _MALI_OSK_ERR_OK; } return _MALI_OSK_ERR_FAULT; }
/* ------ local helper functions below --------- */ static void mali_pp_post_process_job(struct mali_pp_core *core) { MALI_ASSERT_GROUP_LOCKED(core->group); if (NULL != core->running_job) { u32 val0 = 0; u32 val1 = 0; #if MALI_TIMELINE_PROFILING_ENABLED int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); #endif if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) { /* We retrieved the counter that user space asked for, so return the value through the job object */ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); } else { /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index, val0); #endif } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) { /* We retrieved the counter that user space asked for, so return the value through the job object */ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); } else { /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); #endif } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); #endif /* We are no longer running a job... */ core->running_job = NULL; _mali_osk_timer_del(core->timeout_timer); } }
static void mali_pp_bottom_half(void *data) { struct mali_pp_core *core = (struct mali_pp_core *)data; u32 irq_readout; u32 irq_errors; #if MALI_TIMELINE_PROFILING_ENABLED #if 0 /* Bottom half TLP logging is currently not supported */ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); #endif #endif mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ if ( MALI_FALSE == mali_group_power_is_on(core->group) ) { MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); mali_group_unlock(core->group); #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); #endif #endif return; } irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME) { mali_pp_post_process_job(core); MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */ #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); #endif #endif return; } /* * Now lets look at the possible error cases (IRQ indicating error or timeout) * END_OF_FRAME and HANG interrupts are not considered error. */ irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); if (0 != irq_errors) { mali_pp_post_process_job(core); MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */ #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); #endif #endif return; } else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ { if (core->timeout_job_id == mali_pp_job_get_id(core->running_job)) { mali_pp_post_process_job(core); MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n", mali_pp_job_get_id(core->running_job), core->hw_core.description)); mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */ } else { mali_group_unlock(core->group); } core->core_timed_out = MALI_FALSE; #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); #endif #endif return; } else if (irq_readout & MALI200_REG_VAL_IRQ_HANG) { /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); } /* * The only way to get here is if we got a HANG interrupt, which we ignore. * Re-enable interrupts and let core continue to run */ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); mali_group_unlock(core->group); #if MALI_TIMELINE_PROFILING_ENABLED #if 0 /* Bottom half TLP logging is currently not supported */ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); #endif #endif }
void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) { u32 *frame_registers = mali_pp_job_get_frame_registers(job); u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); core->counter_src0_used = core->counter_src0; core->counter_src1_used = core->counter_src1; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME, mali_frame_registers_reset_values); _mali_osk_mem_barrier(); if (0 != sub_job) { /* * There are two frame registers which are different for each sub job. * For the first sub job, these are correctly represented in the frame register array, * but we need to patch these for all other sub jobs */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK/4]); } if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, 0, mali_wb_registers_reset_values[0] ); } if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, 0, mali_wb_registers_reset_values[0] ); } if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, 0, mali_wb_registers_reset_values[0] ); } /* This selects which performance counters we are reading */ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { /* global_config has enabled HW counters, this will override anything specified by user space */ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } } else { /* Use HW counters from job object, if any */ u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); if (0 != perf_counter_flag) { if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } } } MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); /* Adding barrier to make sure all rester writes are finished */ _mali_osk_write_mem_barrier(); /* This is the command that starts the core. */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); /* Adding barrier to make sure previous rester writes is finished */ _mali_osk_write_mem_barrier(); /* Setup the timeout timer value and save the job id for the job running on the pp core */ _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); core->timeout_job_id = mali_pp_job_get_id(job); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); #endif core->running_job = job; core->running_sub_job = sub_job; }
mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) { unsigned long rate = 0; #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED unsigned long previous_rate = 0; #endif mali_bool bis_vpll = MALI_TRUE; #ifndef CONFIG_VPLL_USE_FOR_TVENC bis_vpll = MALI_TRUE; #endif #if !MALI_DVFS_ENABLED clk = mali_gpu_clk; #endif _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); if (mali_clk_get(bis_vpll) == MALI_FALSE) return MALI_FALSE; rate = (unsigned long)clk * (unsigned long)mhz; MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); if (bis_vpll) { clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); clk_set_parent(vpll_src_clock, ext_xtal_clock); clk_set_parent(sclk_vpll_clock, fout_vpll_clock); clk_set_parent(mali_parent_clock, sclk_vpll_clock); clk_set_parent(mali_clock, mali_parent_clock); } else { clk_set_parent(mali_parent_clock, mpll_clock); clk_set_parent(mali_clock, mali_parent_clock); } if (clk_enable(mali_clock) < 0) return MALI_FALSE; #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED previous_rate = clk_get_rate(mali_clock); _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, previous_rate, 0, 0, 0, 0); #endif clk_set_rate(mali_clock, rate); rate = clk_get_rate(mali_clock); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, rate, 1, 0, 0, 0); #endif if (bis_vpll) mali_gpu_clk = (int)(rate / mhz); else mali_gpu_clk = (int)((rate + 500000) / mhz); GPU_MHZ = mhz; MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); mali_clk_put(MALI_FALSE); _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); return MALI_TRUE; }
void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) { u32 startcmd = 0; u32 *frame_registers = mali_gp_job_get_frame_registers(job); core->counter_src0_used = core->counter_src0; core->counter_src1_used = core->counter_src1; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); if (mali_gp_job_has_vs_job(job)) { startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; } if (mali_gp_job_has_plbu_job(job)) { startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; } MALI_DEBUG_ASSERT(0 != startcmd); mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); #if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH { mali_l2_cache_core_set_counter_src0(mali_l2_cache_core_get_glob_l2_core(0), 20); mali_l2_cache_core_set_counter_src1(mali_l2_cache_core_get_glob_l2_core(0), 21); } #endif if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); } } else { u32 perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); if (0 != perf_counter_flag) { if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); } if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); } } } MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); _mali_osk_write_mem_barrier(); mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); _mali_osk_write_mem_barrier(); _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); core->timeout_job_id = mali_gp_job_get_id(job); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0); #endif core->running_job = job; }
static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend) { MALI_ASSERT_GROUP_LOCKED(core->group); if (NULL != core->running_job) { u32 val0 = 0; u32 val1 = 0; #if MALI_TIMELINE_PROFILING_ENABLED u32 event_id; #endif #if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH { u32 src0, value0, src1, value1, sum, per_thousand, per_thousand_now, diff0, diff1; static u32 print_nr=0; static u32 prev0=0; static u32 prev1=0; if ( !(++print_nr&511) ) { mali_l2_cache_core_get_counter_values(mali_l2_cache_core_get_glob_l2_core(0), &src0, &value0, &src1, &value1); MALI_DEBUG_ASSERT( src0==20 ); MALI_DEBUG_ASSERT( src1==21 ); sum = value0+value1; if ( sum > 1000000 ) { per_thousand = value0 / (sum/1000); } else { per_thousand = (value0*1000) / (sum); } diff0 = value0-prev0; diff1 = value1-prev1; sum = diff0 + diff1 ; if ( sum > 1000000 ) { per_thousand_now = diff0 / (sum/1000); } else { per_thousand_now = (diff0*1000) / (sum); } prev0=value0; prev1=value1; if (per_thousand_now<=1000) { MALI_DEBUG_PRINT(2, ("Mali L2: Read hits/misses: %d/%d = %d thousand_parts total, since previous: %d\n", value0, value1, per_thousand, per_thousand_now)); } } } #endif if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); if (mali_gp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_gp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) { mali_gp_job_set_perf_counter_value0(core->running_job, val0); } else { mali_gp_job_set_perf_counter_value0(core->running_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0); #endif } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); if (mali_gp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_gp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) { mali_gp_job_set_perf_counter_value1(core->running_job, val1); } else { mali_gp_job_set_perf_counter_value1(core->running_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1); #endif } #if MALI_TIMELINE_PROFILING_ENABLED if (MALI_TRUE == suspend) { event_id = MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); } else { event_id = MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); } _mali_osk_profiling_add_event(event_id, val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); #endif mali_gp_job_set_current_heap_addr(core->running_job, mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR)); if (MALI_TRUE != suspend) { core->running_job = NULL; _mali_osk_timer_del(core->timeout_timer); } } }
int mali_platform_power_mode_change(mali_power_mode power_mode) { unsigned long flags; switch (power_mode) { case MALI_POWER_MODE_ON: MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", atomic_read((atomic_t *)&bPoweroff) ? "powering on" : "already on")); if (atomic_read((atomic_t *)&bPoweroff) == 1) { MALI_DEBUG_PRINT(2,("[+]MFG enable_clock \n")); mfg_pwr_lock(flags); if (!clock_is_on(MT_CG_MFG_PDN_BG3D_SW_CG)) { enable_clock(MT_CG_MFG_PDN_BG3D_SW_CG, "G3D_DRV"); /// enable WHPLL and set the GPU freq. to 500MHz if(get_gpu_level() != GPU_LEVEL_0){ clkmux_sel(MT_CLKMUX_MFG_MUX_SEL, MT_CG_GPU_500P5M_EN, "G3D_DRV"); } } mfg_pwr_unlock(flags); MALI_DEBUG_PRINT(2,("[-]MFG enable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 500, 1200/1000, 0, 0, 0); #endif atomic_set((atomic_t *)&bPoweroff, 0); } break; case MALI_POWER_MODE_LIGHT_SLEEP: case MALI_POWER_MODE_DEEP_SLEEP: MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", atomic_read((atomic_t *)&bPoweroff) ? "already off" : "powering off")); if (atomic_read((atomic_t *)&bPoweroff) == 0) { MALI_DEBUG_PRINT(2,("[+]MFG disable_clock \n")); mfg_pwr_lock(flags); if (clock_is_on(MT_CG_MFG_PDN_BG3D_SW_CG)) { disable_clock(MT_CG_MFG_PDN_BG3D_SW_CG, "G3D_DRV"); } mfg_pwr_unlock(flags); MALI_DEBUG_PRINT(2,("[-]MFG disable_clock \n")); #if defined(CONFIG_MALI400_PROFILING) _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_GPU | MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); #endif atomic_set((atomic_t *)&bPoweroff, 1); } break; } }
static void mali_gp_bottom_half(void *data) { struct mali_gp_core *core = (struct mali_gp_core *)data; u32 irq_readout; u32 irq_errors; #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); #endif #endif mali_group_lock(core->group); if ( MALI_FALSE == mali_group_power_is_on(core->group) ) { MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); mali_group_unlock(core->group); return; } irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) { u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) { mali_gp_post_process_job(core, MALI_FALSE); MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n")); mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); return; } } irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); if (0 != irq_errors) { mali_gp_post_process_job(core, MALI_FALSE); MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); return; } else if (MALI_TRUE == core->core_timed_out) { if (core->timeout_job_id == mali_gp_job_get_id(core->running_job)) { mali_gp_post_process_job(core, MALI_FALSE); MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job))); mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT); } else { MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out but current job is %d\n", core->timeout_job_id, mali_gp_job_get_id(core->running_job))); mali_group_unlock(core->group); } core->core_timed_out = MALI_FALSE; return; } else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) { mali_gp_post_process_job(core, MALI_TRUE); MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n")); mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); return; } else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG) { mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG); } mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); mali_group_unlock(core->group); #if MALI_TIMELINE_PROFILING_ENABLED #if 0 _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); #endif #endif }