mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
{
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );

	pmm->cores_idle |= (cores);
	return pmm->cores_idle;
}
mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
{
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );

	/* Check core is not pending a power up */
	MALI_DEBUG_ASSERT( (pmm->cores_pend_up & cores) != 0 );
	/* Check core has not acknowledged power up more than once */
	MALI_DEBUG_ASSERT( (pmm->cores_ack_up & cores) == 0 );

	pmm->cores_ack_up |= (cores);

	return pmm->cores_ack_up;
}
mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
{
	mali_pmm_core_mask cores_subset;
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );

	/* Check that cores aren't pending power down when asked for power up */
	MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );

	cores_subset = (~(pmm->cores_powered) & cores);
	if( cores_subset != 0 )
	{
		/* There are some cores that need powering up */
		pmm->cores_pend_up = cores_subset;
	}

	return cores_subset;
}
Exemple #4
0
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);
}
mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
{
	mali_pmm_core_mask cores;
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_DEBUG_ASSERT_POINTER(event);

	switch( event->id )
	{
	case MALI_PMM_EVENT_OS_POWER_UP:
	case MALI_PMM_EVENT_OS_POWER_DOWN:
		/* All cores - the system */
		cores = pmm->cores_registered;
		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:
		/* Currently the main event data is only the cores
		 * for these messages
		 */
		cores = (mali_pmm_core_mask)event->data;
		if( cores == MALI_PMM_CORE_SYSTEM )
		{
			cores = pmm->cores_registered;
		}
		else if( cores == MALI_PMM_CORE_PP_ALL )
		{
			/* Get the subset of registered PP cores */
			cores = (pmm->cores_registered & MALI_PMM_CORE_PP_ALL);
		}
		MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
		break;

	default:
		/* Assume timeout messages - report cores still powered */
		cores = pmm->cores_powered;
		break;
	}

	return cores;
}
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_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only )
{
	mali_pmm_core_mask cores_subset;
	_mali_osk_errcode_t err;
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );

	/* Check that cores aren't pending power up when asked for power down */
	MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );

	cores_subset = (pmm->cores_powered & cores);
	if( cores_subset != 0 )
	{
		int n;
		volatile mali_pmm_core_mask *ppowered = &(pmm->cores_powered);

		/* There are some cores that need powering up, but we may
		 * need to wait until they are idle
		 */
		for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
		{
			if( (cores_list[n] & cores_subset) != 0 )
			{
				/* Core is to be powered down */
				pmm->cores_pend_down |= cores_list[n];

				/* 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
				 * down, but it does not matter as we are terminating
				 */
				MALI_PMM_UNLOCK(pmm);
				/* Signal the core to power down
				 * If it is busy (not idle) it will set a pending power down flag 
				 * (as long as we don't want to only immediately power down). 
				 * If it isn't busy it will move out of the idle queue right
				 * away
				 */
				err = mali_core_signal_power_down( cores_list[n], immediate_only );
				MALI_PMM_LOCK(pmm);

				/* Re-read cores_subset in case it has changed */
				cores_subset = (*ppowered & cores);

				if( err == _MALI_OSK_ERR_OK )
				{
					/* We moved an idle core to the power down queue
					 * which means it is now acknowledged (if it is still 
					 * registered)
					 */
					pmm->cores_ack_down |= (cores_list[n] & cores_subset);
				}
				else
				{
					MALI_DEBUG_ASSERT( err == _MALI_OSK_ERR_BUSY ||
										(err == _MALI_OSK_ERR_FAULT &&
										(*ppowered & cores_list[n]) == 0) );
					/* If we didn't move a core - it must be active, so
					 * leave it pending, so we get an acknowledgement (when
					 * not in immediate only mode)
					 * Alternatively we are shutting down and the core has
					 * been unregistered
					 */
				}
			}
		}
	}

	return cores_subset;
}