_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core ) { _mali_osk_errcode_t err; _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; if( pmm == NULL ) { /* PMM state has not been created, this is because the PMU resource has not been * created yet. * This probably means that the PMU resource has not been specfied as the first * resource in the config file */ MALI_PRINT_ERROR( ("PMM: Cannot register core %s because the PMU resource has not been\n initialized. Please make sure the PMU resource is the first resource in the\n resource configuration.\n", pmm_trace_get_core_name(core)) ); MALI_ERROR(_MALI_OSK_ERR_FAULT); } MALI_PMM_LOCK(pmm); /* Check if the core is registered more than once in PMM */ MALI_DEBUG_ASSERT( (pmm->cores_registered & core) == 0 ); MALIPMM_DEBUG_PRINT( ("PMM: core registered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) ); #if !MALI_PMM_NO_PMU /* Make sure the core is powered up */ err = mali_platform_powerup( core ); #else err = _MALI_OSK_ERR_OK; #endif if( _MALI_OSK_ERR_OK == err ) { #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif /* Assume a registered core is now powered up and idle */ pmm->cores_registered |= core; pmm->cores_idle |= core; pmm->cores_powered |= core; pmm_update_system_state( pmm ); #if MALI_PMM_TRACE _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered ); #endif } else { MALI_PRINT_ERROR( ("PMM: Error(%d) powering up registered core: (0x%x) %s\n", err, core, pmm_trace_get_core_name(core)) ); } MALI_PMM_UNLOCK(pmm); return err; }
void malipmm_core_unregister( mali_pmm_core_id core ) { _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; MALI_DEBUG_ASSERT_POINTER(pmm); MALI_PMM_LOCK(pmm); /* Check if the core is registered in PMM */ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, core ); MALIPMM_DEBUG_PRINT( ("PMM: core unregistered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) ); { #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif #if !MALI_PMM_NO_PMU /* Turn off the core */ if( mali_platform_powerdown( core ) != _MALI_OSK_ERR_OK ) { MALI_PRINT_ERROR( ("PMM: Error powering down unregistered core: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) ); } #endif /* Remove the core from the system */ pmm->cores_registered &= (~core); pmm->cores_idle &= (~core); pmm->cores_powered &= (~core); pmm->cores_pend_down &= (~core); pmm->cores_pend_up &= (~core); pmm->cores_ack_down &= (~core); pmm->cores_ack_up &= (~core); pmm_update_system_state( pmm ); #if MALI_PMM_TRACE _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered ); #endif } MALI_PMM_UNLOCK(pmm); }
void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool received ) { const char *ename; const char *dname; const char *tname; const char *format = "PMM Trace: Event %s { (%d) %s, %d ticks, (0x%x) %s }"; MALI_DEBUG_ASSERT_POINTER(event); tname = (received) ? "received" : "sent"; if( event->id >= MALI_PMM_EVENT_INTERNALS ) { ename = pmm_trace_events_internal[((int)event->id) - MALI_PMM_EVENT_INTERNALS]; } else if( event->id >= MALI_PMM_EVENT_UKS ) { ename = pmm_trace_events_uk[((int)event->id) - MALI_PMM_EVENT_UKS]; } else { ename = pmm_trace_events[event->id]; } switch( event->id ) { case MALI_PMM_EVENT_OS_POWER_UP: case MALI_PMM_EVENT_OS_POWER_DOWN: dname = "os event"; break; case MALI_PMM_EVENT_JOB_SCHEDULED: case MALI_PMM_EVENT_JOB_QUEUED: case MALI_PMM_EVENT_JOB_FINISHED: case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK: case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK: dname = pmm_trace_get_core_name( (mali_pmm_core_mask)event->data ); break; case MALI_PMM_EVENT_TIMEOUT: dname = "timeout start"; /* Print data with a different format */ format = "PMM Trace: Event %s { (%d) %s, %d ticks, %d ticks %s }"; break; default: dname = "unknown data"; } MALI_PRINT( (format, tname, (u32)event->id, ename, event->ts, (u32)event->data, dname) ); }
mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode ) { _mali_osk_errcode_t err; MALI_DEBUG_ASSERT_POINTER(pmm); /* Check that cores are pending power down during power down invoke */ MALI_DEBUG_ASSERT( pmm->cores_pend_down != 0 ); /* Check that cores are not pending power up during power down invoke */ MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 ); if( !pmm_power_down_okay( pmm ) ) { MALIPMM_DEBUG_PRINT( ("PMM: Waiting for cores to go idle for power off - 0x%08x / 0x%08x\n", pmm->cores_pend_down, pmm->cores_ack_down) ); return MALI_FALSE; } else { pmm->cores_powered &= ~(pmm->cores_pend_down); #if !MALI_PMM_NO_PMU err = malipmm_powerdown( pmm->cores_pend_down, power_mode); #else err = _MALI_OSK_ERR_OK; #endif if( err == _MALI_OSK_ERR_OK ) { #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif /* Remove powered down cores from idle and powered list */ pmm->cores_idle &= ~(pmm->cores_pend_down); /* Reset pending/acknowledged status */ pmm->cores_pend_down = 0; pmm->cores_ack_down = 0; #if MALI_PMM_TRACE _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered ); #endif } else { pmm->cores_powered |= pmm->cores_pend_down; MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power down cores - (0x%x) %s", pmm->cores_pend_down, pmm_trace_get_core_name(pmm->cores_pend_down)) ); pmm->fatal_power_err = MALI_TRUE; } } return MALI_TRUE; }
void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate ) { const char *dname; const char *cname; const char *ename; if( old != newstate ) { if( newstate == 0 ) { dname = "NO cores"; } else { dname = pmm_trace_get_core_name( newstate ); } /* These state checks only work if the assumption that only cores can be * turned on or turned off in seperate actions is true. If core power states can * be toggled (some one, some off) at the same time, this check does not work */ if( old > newstate ) { /* Cores have turned off */ cname = pmm_trace_get_core_name( old - newstate ); ename = "OFF"; } else { /* Cores have turned on */ cname = pmm_trace_get_core_name( newstate - old ); ename = "ON"; } MALI_PRINT( ("PMM Trace: Hardware %s ON, %s just turned %s. { 0x%08x -> 0x%08x }", dname, cname, ename, old, newstate) ); } }
void malipmm_core_unregister( mali_pmm_core_id core ) { _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; MALI_DEBUG_ASSERT_POINTER(pmm); MALI_PMM_LOCK(pmm); #if MALI_STATE_TRACKING pmm->mali_pmm_lock_acquired = 1; #endif /* MALI_STATE_TRACKING */ /* Check if the core is registered in PMM */ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, core ); MALIPMM_DEBUG_PRINT( ("PMM: core unregistered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) ); { #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif /* Remove the core from the system */ pmm->cores_idle &= (~core); pmm->cores_powered &= (~core); pmm->cores_pend_down &= (~core); pmm->cores_pend_up &= (~core); pmm->cores_ack_down &= (~core); pmm->cores_ack_up &= (~core); pmm_update_system_state( pmm ); #if MALI_PMM_TRACE _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered ); #endif } #if MALI_STATE_TRACKING pmm->mali_pmm_lock_acquired = 0; #endif /* MALI_STATE_TRACKING */ MALI_PMM_UNLOCK(pmm); }
mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm ) { _mali_osk_errcode_t err; MALI_DEBUG_ASSERT_POINTER(pmm); /* Check that cores are pending power up during power up invoke */ MALI_DEBUG_ASSERT( pmm->cores_pend_up != 0 ); /* Check that cores are not pending power down during power up invoke */ MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 ); if( pmm_power_up_okay( pmm ) ) { /* Power up has completed - sort out subsystem core status */ int n; /* Use volatile to access, so that it is updated if any cores are unregistered */ volatile mali_pmm_core_mask *ppendup = &(pmm->cores_pend_up); #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif /* Move cores into idle queues */ for( n = 0; n < SIZEOF_CORES_LIST; n++ ) { if( (cores_list[n] & (*ppendup)) != 0 ) { /* Can't hold the power lock, when acessing subsystem mutex via * the core power call. * Due to terminatation of driver requiring a subsystem mutex * and then power lock held to unregister a core. * This does mean that the following function could fail * as the core is unregistered before we tell it to power * up, but it does not matter as we are terminating */ MALI_PMM_UNLOCK(pmm); err = mali_core_signal_power_up( cores_list[n], MALI_FALSE ); MALI_PMM_LOCK(pmm); if( err != _MALI_OSK_ERR_OK ) { MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT && (*ppendup & cores_list[n]) == 0) ); /* We only expect this to fail when we are shutting down * and the core has been unregistered */ } } } /* Finished power up - add cores to idle and powered list */ pmm->cores_powered |= (*ppendup); pmm->cores_idle |= (*ppendup); /* Reset pending/acknowledge status */ pmm->cores_pend_up = 0; pmm->cores_ack_up = 0; #if MALI_PMM_TRACE _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered ); #endif return MALI_TRUE; } else { #if !MALI_PMM_NO_PMU /* Power up must now be done */ err = mali_platform_powerup( pmm->cores_pend_up ); #else err = _MALI_OSK_ERR_OK; #endif if( err != _MALI_OSK_ERR_OK ) { MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power up cores - (0x%x) %s", pmm->cores_pend_up, pmm_trace_get_core_name(pmm->cores_pend_up)) ); pmm->fatal_power_err = MALI_TRUE; } else { /* TBD - Update core status immediately rather than use event message */ _mali_uk_pmm_message_s event = { NULL, MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK, 0 }; /* All the cores that were pending power up, have now completed power up */ event.data = pmm->cores_pend_up; _mali_ukk_pmm_event_message( &event ); MALIPMM_DEBUG_PRINT( ("PMM: Sending ACK to power up") ); } } /* Always return false, as we need an interrupt to acknowledge * when power up is complete */ return MALI_FALSE; }