diff options
Diffstat (limited to 'drivers/media/video/samsung/mali/common/pmm/mali_pmm.c')
-rw-r--r-- | drivers/media/video/samsung/mali/common/pmm/mali_pmm.c | 1024 |
1 files changed, 0 insertions, 1024 deletions
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c deleted file mode 100644 index 7041391..0000000 --- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright (C) 2010 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * @file mali_pmm.c - * Implementation of the power management module for the kernel device driver - */ - -#if USING_MALI_PMM - -#include "mali_ukk.h" -#include "mali_kernel_common.h" -#include "mali_kernel_subsystem.h" - -#include "mali_pmm.h" -#include "mali_pmm_system.h" -#include "mali_pmm_state.h" -#include "mali_pmm_policy.h" -#include "mali_pmm_pmu.h" -#include "mali_platform.h" -#include "mali_kernel_pm.h" - -/* Internal PMM subsystem state */ -static _mali_pmm_internal_state_t *pmm_state = NULL; -/* Mali kernel subsystem id */ -static mali_kernel_subsystem_identifier mali_subsystem_pmm_id = -1; - -#define GET_PMM_STATE_PTR (pmm_state) - -/* Internal functions */ -static _mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource); -static void pmm_event_process( void ); -_mali_osk_errcode_t malipmm_irq_uhandler(void *data); -void malipmm_irq_bhandler(void *data); - -/** @brief Start the PMM subsystem - * - * @param id Subsystem id to uniquely identify this subsystem - * @return _MALI_OSK_ERR_OK if the system started successfully, or a suitable - * _mali_osk_errcode_t otherwise. - */ -_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id ); - -/** @brief Perform post start up of the PMM subsystem - * - * Post start up includes initializing the current policy, now that the system is - * completely started - to stop policies turning off hardware during the start up - * - * @param id the unique subsystem id - * @return _MALI_OSK_ERR_OK if the post startup was successful, or a suitable - * _mali_osk_errcode_t otherwise. - */ -_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id ); - -/** @brief Terminate the PMM subsystem - * - * @param id the unique subsystem id - */ -void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ); - -#if MALI_STATE_TRACKING -u32 malipmm_subsystem_dump_state( char *buf, u32 size ); -#endif - - -/* This will be one of the subsystems in the array of subsystems: - static struct mali_kernel_subsystem * subsystems[]; - found in file: mali_kernel_core.c -*/ -struct mali_kernel_subsystem mali_subsystem_pmm= -{ - malipmm_kernel_subsystem_start, /* startup */ - NULL, /*malipmm_kernel_subsystem_terminate,*/ /* shutdown */ - malipmm_kernel_load_complete, /* loaded all subsystems */ - NULL, - NULL, - NULL, - NULL, -#if MALI_STATE_TRACKING - malipmm_subsystem_dump_state, /* dump_state */ -#endif -}; - -#if PMM_OS_TEST - -u32 power_test_event = 0; -mali_bool power_test_flag = MALI_FALSE; -_mali_osk_timer_t *power_test_timer = NULL; - -void _mali_osk_pmm_power_up_done(mali_pmm_message_data data) -{ - MALI_PRINT(("POWER TEST OS UP DONE\n")); -} - -void _mali_osk_pmm_power_down_done(mali_pmm_message_data data) -{ - MALI_PRINT(("POWER TEST OS DOWN DONE\n")); -} - -/** - * Symbian OS Power Up call to the driver - */ -void power_test_callback( void *arg ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - power_test_flag = MALI_TRUE; - _mali_osk_irq_schedulework( pmm->irq ); -} - -void power_test_start() -{ - power_test_timer = _mali_osk_timer_init(); - _mali_osk_timer_setcallback( power_test_timer, power_test_callback, NULL ); - - /* First event is power down */ - power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN; - _mali_osk_timer_add( power_test_timer, 10000 ); -} - -mali_bool power_test_check() -{ - if( power_test_flag ) - { - _mali_uk_pmm_message_s event = { - NULL, - 0, - 1 }; - event.id = power_test_event; - - power_test_flag = MALI_FALSE; - - /* Send event */ - _mali_ukk_pmm_event_message( &event ); - - /* Switch to next event to test */ - if( power_test_event == MALI_PMM_EVENT_OS_POWER_DOWN ) - { - power_test_event = MALI_PMM_EVENT_OS_POWER_UP; - } - else - { - power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN; - } - _mali_osk_timer_add( power_test_timer, 5000 ); - - return MALI_TRUE; - } - - return MALI_FALSE; -} - -void power_test_end() -{ - _mali_osk_timer_del( power_test_timer ); - _mali_osk_timer_term( power_test_timer ); - power_test_timer = NULL; -} - -#endif - -void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - _mali_osk_notification_t *msg; - mali_pmm_message_t *event; - MALI_DEBUG_ASSERT_POINTER(pmm); - MALI_DEBUG_ASSERT_POINTER(args); - - MALIPMM_DEBUG_PRINT( ("PMM: sending message\n") ); - -#if MALI_PMM_TRACE && MALI_PMM_TRACE_SENT_EVENTS - _mali_pmm_trace_event_message( args, MALI_FALSE ); -#endif - - msg = _mali_osk_notification_create( MALI_PMM_NOTIFICATION_TYPE, sizeof( mali_pmm_message_t ) ); - - if( msg ) - { - event = (mali_pmm_message_t *)msg->result_buffer; - event->id = args->id; - event->ts = _mali_osk_time_tickcount(); - event->data = args->data; - - _mali_osk_atomic_inc( &(pmm->messages_queued) ); - - if( args->id > MALI_PMM_EVENT_INTERNALS ) - { - /* Internal PMM message */ - _mali_osk_notification_queue_send( pmm->iqueue, msg ); - #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) - pmm->imessages_sent++; - #endif - } - else - { - /* Real event */ - _mali_osk_notification_queue_send( pmm->queue, msg ); - #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) - pmm->messages_sent++; - #endif - } - } - else - { - MALI_PRINT_ERROR( ("PMM: Could not send message %d", args->id) ); - /* Make note of this OOM - which has caused a missed event */ - pmm->missed++; - } - - /* Schedule time to look at the event or the fact we couldn't create an event */ - _mali_osk_irq_schedulework( pmm->irq ); -} - -mali_pmm_state _mali_pmm_state( void ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - if( pmm && (mali_subsystem_pmm_id != -1) ) - { - return pmm->state; - } - - /* No working subsystem yet */ - return MALI_PMM_STATE_UNAVAILABLE; -} - - -mali_pmm_core_mask _mali_pmm_cores_list( void ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - return pmm->cores_registered; -} - -mali_pmm_core_mask _mali_pmm_cores_powered( void ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - return pmm->cores_powered; -} - - -_mali_osk_errcode_t _mali_pmm_list_policies( - u32 policy_list_size, - mali_pmm_policy *policy_list, - u32 *policies_available ) -{ - /* TBD - This is currently a stub function for basic power management */ - - MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED ); -} - -_mali_osk_errcode_t _mali_pmm_set_policy( mali_pmm_policy policy ) -{ - /* TBD - This is currently a stub function for basic power management */ - -/* TBD - When this is not a stub... include tracing... -#if MALI_PMM_TRACE - _mali_pmm_trace_policy_change( old, newpolicy ); -#endif -*/ - MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED ); -} - -_mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy ) -{ - if( policy ) - { - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - if( pmm ) - { - *policy = pmm->policy; - MALI_SUCCESS; - } - else - { - *policy = MALI_PMM_POLICY_NONE; - MALI_ERROR( _MALI_OSK_ERR_FAULT ); - } - } - - /* No return argument */ - MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS ); -} - -#if ( MALI_PMM_TRACE || MALI_STATE_TRACKING ) - -/* Event names - order must match mali_pmm_event_id enum */ -static char *pmm_trace_events[] = { - "OS_POWER_UP", - "OS_POWER_DOWN", - "JOB_SCHEDULED", - "JOB_QUEUED", - "JOB_FINISHED", - "TIMEOUT", -}; - -/* State names - order must match mali_pmm_state enum */ -static char *pmm_trace_state[] = { - "UNAVAILABLE", - "SYSTEM ON", - "SYSTEM OFF", - "SYSTEM TRANSITION", -}; - -/* Policy names - order must match mali_pmm_policy enum */ -static char *pmm_trace_policy[] = { - "NONE", - "ALWAYS ON", - "JOB CONTROL", -}; - -/* Status names - order must match mali_pmm_status enum */ -static char *pmm_trace_status[] = { - "MALI_PMM_STATUS_IDLE", /**< PMM is waiting next event */ - "MALI_PMM_STATUS_POLICY_POWER_DOWN", /**< Policy initiated power down */ - "MALI_PMM_STATUS_POLICY_POWER_UP", /**< Policy initiated power down */ - "MALI_PMM_STATUS_OS_WAITING", /**< PMM is waiting for OS power up */ - "MALI_PMM_STATUS_OS_POWER_DOWN", /**< OS initiated power down */ - "MALI_PMM_STATUS_RUNTIME_IDLE_IN_PROGRESS", - "MALI_PMM_STATUS_DVFS_PAUSE", /**< PMM DVFS Status Pause */ - "MALI_PMM_STATUS_OS_POWER_UP", /**< OS initiated power up */ - "MALI_PMM_STATUS_OFF", /**< PMM is not active */ -}; - -#endif /* MALI_PMM_TRACE || MALI_STATE_TRACKING */ -#if MALI_PMM_TRACE - -/* UK event names - order must match mali_pmm_event_id enum */ -static char *pmm_trace_events_uk[] = { - "UKS", - "UK_EXAMPLE", -}; - -/* Internal event names - order must match mali_pmm_event_id enum */ -static char *pmm_trace_events_internal[] = { - "INTERNALS", - "INTERNAL_POWER_UP_ACK", - "INTERNAL_POWER_DOWN_ACK", -}; - -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 _mali_pmm_trace_state_change( mali_pmm_state old, mali_pmm_state newstate ) -{ - if( old != newstate ) - { - MALI_PRINT( ("PMM Trace: State changed from %s to %s", pmm_trace_state[old], pmm_trace_state[newstate]) ); - } -} - -void _mali_pmm_trace_policy_change( mali_pmm_policy old, mali_pmm_policy newpolicy ) -{ - if( old != newpolicy ) - { - MALI_PRINT( ("PMM Trace: Policy changed from %s to %s", pmm_trace_policy[old], pmm_trace_policy[newpolicy]) ); - } -} - -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) ); -} - -#endif /* MALI_PMM_TRACE */ - - -/****************** Mali Kernel API *****************/ - -_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id ) -{ - mali_subsystem_pmm_id = id; - MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(PMU, malipmm_create)); - MALI_SUCCESS; -} - -_mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource) -{ - /* Create PMM state memory */ - MALI_DEBUG_ASSERT( pmm_state == NULL ); - pmm_state = (_mali_pmm_internal_state_t *) _mali_osk_malloc(sizeof(*pmm_state)); - MALI_CHECK_NON_NULL( pmm_state, _MALI_OSK_ERR_NOMEM ); - - /* All values get 0 as default */ - _mali_osk_memset(pmm_state, 0, sizeof(*pmm_state)); - - /* Set up the initial PMM state */ - pmm_state->waiting = 0; - pmm_state->status = MALI_PMM_STATUS_IDLE; - pmm_state->state = MALI_PMM_STATE_UNAVAILABLE; /* Until a core registers */ - - /* Set up policy via compile time option for the moment */ -#if MALI_PMM_ALWAYS_ON - pmm_state->policy = MALI_PMM_POLICY_ALWAYS_ON; -#else - pmm_state->policy = MALI_PMM_POLICY_JOB_CONTROL; -#endif - -#if MALI_PMM_TRACE - _mali_pmm_trace_policy_change( MALI_PMM_POLICY_NONE, pmm_state->policy ); -#endif - - /* Set up assumes all values are initialized to NULL or MALI_FALSE, so - * we can exit halfway through set up and perform clean up - */ - -#if USING_MALI_PMU - if( mali_pmm_pmu_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup; - pmm_state->pmu_initialized = MALI_TRUE; -#endif - pmm_state->queue = _mali_osk_notification_queue_init(); - if( !pmm_state->queue ) goto pmm_fail_cleanup; - - pmm_state->iqueue = _mali_osk_notification_queue_init(); - if( !pmm_state->iqueue ) goto pmm_fail_cleanup; - - /* We are creating an IRQ handler just for the worker thread it gives us */ - pmm_state->irq = _mali_osk_irq_init( _MALI_OSK_IRQ_NUMBER_PMM, - malipmm_irq_uhandler, - malipmm_irq_bhandler, - NULL, - NULL, - (void *)pmm_state, /* PMM state is passed to IRQ */ - "PMM handler" ); - - if( !pmm_state->irq ) goto pmm_fail_cleanup; - - pmm_state->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 75); - if( !pmm_state->lock ) goto pmm_fail_cleanup; - - if( _mali_osk_atomic_init( &(pmm_state->messages_queued), 0 ) != _MALI_OSK_ERR_OK ) - { - goto pmm_fail_cleanup; - } - - MALIPMM_DEBUG_PRINT( ("PMM: subsystem created, policy=%d\n", pmm_state->policy) ); - - MALI_SUCCESS; - -pmm_fail_cleanup: - MALI_PRINT_ERROR( ("PMM: subsystem failed to be created\n") ); - if( pmm_state ) - { - if( pmm_state->lock ) _mali_osk_lock_term( pmm_state->lock ); - if( pmm_state->irq ) _mali_osk_irq_term( pmm_state->irq ); - if( pmm_state->queue ) _mali_osk_notification_queue_term( pmm_state->queue ); - if( pmm_state->iqueue ) _mali_osk_notification_queue_term( pmm_state->iqueue ); -#if USING_MALI_PMU - if( pmm_state->pmu_initialized ) - { - _mali_osk_resource_type_t t = PMU; - mali_pmm_pmu_deinit(&t); - } -#endif /* USING_MALI_PMU */ - - _mali_osk_free(pmm_state); - pmm_state = NULL; - } - MALI_ERROR( _MALI_OSK_ERR_FAULT ); -} - -_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - - MALIPMM_DEBUG_PRINT( ("PMM: subsystem loaded, policy initializing\n") ); - -#if PMM_OS_TEST - power_test_start(); -#endif - - /* Initialize the profile now the system has loaded - so that cores are - * not turned off during start up - */ - return pmm_policy_init( pmm ); -} - -void malipmm_force_powerup( void ) -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - MALI_PMM_LOCK(pmm); - pmm->status = MALI_PMM_STATUS_OFF; - MALI_PMM_UNLOCK(pmm); - - /* flush PMM workqueue */ - _mali_osk_flush_workqueue( pmm->irq ); - - if (pmm->cores_powered == 0) - { - malipmm_powerup(pmm->cores_registered); - } -} - -void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) -{ - /* Check this is the right system */ - MALI_DEBUG_ASSERT( id == mali_subsystem_pmm_id ); - MALI_DEBUG_ASSERT_POINTER(pmm_state); - - if( pmm_state ) - { -#if PMM_OS_TEST - power_test_end(); -#endif - /* Get the lock so we can shutdown */ - MALI_PMM_LOCK(pmm_state); -#if MALI_STATE_TRACKING - pmm_state->mali_pmm_lock_acquired = 1; -#endif /* MALI_STATE_TRACKING */ - pmm_state->status = MALI_PMM_STATUS_OFF; -#if MALI_STATE_TRACKING - pmm_state->mali_pmm_lock_acquired = 0; -#endif /* MALI_STATE_TRACKING */ - MALI_PMM_UNLOCK(pmm_state); - _mali_osk_pmm_ospmm_cleanup(); - pmm_policy_term(pmm_state); - _mali_osk_irq_term( pmm_state->irq ); - _mali_osk_notification_queue_term( pmm_state->queue ); - _mali_osk_notification_queue_term( pmm_state->iqueue ); - if (pmm_state->cores_registered) malipmm_powerdown(pmm_state->cores_registered,MALI_POWER_MODE_LIGHT_SLEEP); -#if USING_MALI_PMU - if( pmm_state->pmu_initialized ) - { - _mali_osk_resource_type_t t = PMU; - mali_pmm_pmu_deinit(&t); - } -#endif /* USING_MALI_PMU */ - - _mali_osk_atomic_term( &(pmm_state->messages_queued) ); - MALI_PMM_LOCK_TERM(pmm_state); - _mali_osk_free(pmm_state); - pmm_state = NULL; - } - - MALIPMM_DEBUG_PRINT( ("PMM: subsystem terminated\n") ); -} - -_mali_osk_errcode_t malipmm_powerup( u32 cores ) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - - /* If all the cores are powered down, power up the MALI */ - if (pmm->cores_powered == 0) { - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - /* Initiate the power up */ - if (_mali_osk_pmm_dev_activate() < 0) { - MALI_PRINT(("PMM: Try again PD_G3D enable\n")); - if (mali_pd_enable() < 0) { - MALI_PRINT(("PMM: Mali PMM device activate failed\n")); - err = _MALI_OSK_ERR_FAULT; - return err; - } - } -#endif - } - -#if USING_MALI_PMU - err = mali_pmm_pmu_powerup( cores ); -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - mali_platform_powerup(cores); -#endif - - return err; -} - -_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode ) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - mali_platform_powerdown(cores); -#endif - -#if USING_MALI_PMU - err = mali_pmm_pmu_powerdown( cores ); -#endif - - /* If all cores are powered down, power off the MALI */ - if (pmm->cores_powered == 0) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - /* Initiate the power down */ - _mali_osk_pmm_dev_idle(); -#endif - mali_platform_power_mode_change(power_mode); - } - return err; -} - -_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); - -#if MALI_STATE_TRACKING - pmm->mali_pmm_lock_acquired = 1; -#endif /* MALI_STATE_TRACKING */ - - - /* 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 = malipmm_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)) ); - } - -#if MALI_STATE_TRACKING - pmm->mali_pmm_lock_acquired = 0; -#endif /* MALI_STATE_TRACKING */ - - 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); -#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); -} -void malipmm_core_power_down_okay( mali_pmm_core_id core ) -{ - _mali_uk_pmm_message_s event = { - NULL, - MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK, - 0 }; - - event.data = core; - - _mali_ukk_pmm_event_message( &event ); -} - -void malipmm_set_policy_check() -{ - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - MALI_DEBUG_ASSERT_POINTER(pmm); - pmm->check_policy = MALI_TRUE; - - /* To check the policy we need to schedule some work */ - _mali_osk_irq_schedulework( pmm->irq ); -} - -_mali_osk_errcode_t malipmm_irq_uhandler(void *data) -{ - MALIPMM_DEBUG_PRINT( ("PMM: uhandler - not expected to be used\n") ); - - MALI_SUCCESS; -} - -void malipmm_irq_bhandler(void *data) -{ - _mali_pmm_internal_state_t *pmm; - pmm = (_mali_pmm_internal_state_t *)data; - MALI_DEBUG_ASSERT_POINTER(pmm); - -#if PMM_OS_TEST - if( power_test_check() ) return; -#endif - - MALI_PMM_LOCK(pmm); -#if MALI_STATE_TRACKING - pmm->mali_pmm_lock_acquired = 1; -#endif /* MALI_STATE_TRACKING */ - - /* Quick out when we are shutting down */ - if( pmm->status == MALI_PMM_STATUS_OFF ) - { - - #if MALI_STATE_TRACKING - pmm->mali_pmm_lock_acquired = 0; - #endif /* MALI_STATE_TRACKING */ - - MALI_PMM_UNLOCK(pmm); - return; - } - - MALIPMM_DEBUG_PRINT( ("PMM: bhandler - Processing event\n") ); - - if( pmm->missed > 0 ) - { - MALI_PRINT_ERROR( ("PMM: Failed to send %d events", pmm->missed) ); - pmm_fatal_reset( pmm ); - } - - if( pmm->check_policy ) - { - pmm->check_policy = MALI_FALSE; - pmm_policy_check_policy(pmm); - } - else - { - /* Perform event processing */ - pmm_event_process(); - if( pmm->fatal_power_err ) - { - /* Try a reset */ - pmm_fatal_reset( pmm ); - } - } - -#if MALI_STATE_TRACKING - pmm->mali_pmm_lock_acquired = 0; -#endif /* MALI_STATE_TRACKING */ - - MALI_PMM_UNLOCK(pmm); -} - -static void pmm_event_process( void ) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - _mali_osk_notification_t *msg = NULL; - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - mali_pmm_message_t *event; - u32 process_messages; - - MALI_DEBUG_ASSERT_POINTER(pmm); - - - /* Max number of messages to process before exiting - as we shouldn't stay - * processing the messages for a long time - */ - process_messages = _mali_osk_atomic_read( &(pmm->messages_queued) ); - - while( process_messages > 0 ) - { - /* Check internal message queue first */ - err = _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ); - - if( err != _MALI_OSK_ERR_OK ) - { - if( pmm->status == MALI_PMM_STATUS_IDLE || pmm->status == MALI_PMM_STATUS_OS_WAITING || pmm->status == MALI_PMM_STATUS_DVFS_PAUSE) - { - if( pmm->waiting > 0 ) pmm->waiting--; - - /* We aren't busy changing state, so look at real events */ - err = _mali_osk_notification_queue_dequeue( pmm->queue, &msg ); - - if( err != _MALI_OSK_ERR_OK ) - { - pmm->no_events++; - MALIPMM_DEBUG_PRINT( ("PMM: event_process - No message to process\n") ); - /* Nothing to do - so return */ - return; - } - else - { - #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) - pmm->messages_received++; - #endif - } - } - else - { - /* Waiting for an internal message */ - pmm->waiting++; - MALIPMM_DEBUG_PRINT( ("PMM: event_process - Waiting for internal message, messages queued=%d\n", pmm->waiting) ); - return; - } - } - else - { - #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) - pmm->imessages_received++; - #endif - } - - MALI_DEBUG_ASSERT_POINTER( msg ); - /* Check the message type matches */ - MALI_DEBUG_ASSERT( msg->notification_type == MALI_PMM_NOTIFICATION_TYPE ); - - event = msg->result_buffer; - - _mali_osk_atomic_dec( &(pmm->messages_queued) ); - process_messages--; - - #if MALI_PMM_TRACE - /* Trace before we process the event in case we have an error */ - _mali_pmm_trace_event_message( event, MALI_TRUE ); - #endif - err = pmm_policy_process( pmm, event ); - - - if( err != _MALI_OSK_ERR_OK ) - { - MALI_PRINT_ERROR( ("PMM: Error(%d) in policy %d when processing event message with id: %d", - err, pmm->policy, event->id) ); - } - - /* Delete notification */ - _mali_osk_notification_delete ( msg ); - - if( pmm->fatal_power_err ) - { - /* Nothing good has happened - exit */ - return; - } - - - #if MALI_PMM_TRACE - MALI_PRINT( ("PMM Trace: Event processed, msgs (sent/read) = %d/%d, int msgs (sent/read) = %d/%d, no events = %d, waiting = %d\n", - pmm->messages_sent, pmm->messages_received, pmm->imessages_sent, pmm->imessages_received, pmm->no_events, pmm->waiting) ); - #endif - } - - if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->waiting > 0 ) - { - /* For events we ignored whilst we were busy, add a new - * scheduled time to look at them */ - _mali_osk_irq_schedulework( pmm->irq ); - } -} - -#if MALI_STATE_TRACKING -u32 malipmm_subsystem_dump_state(char *buf, u32 size) -{ - int len = 0; - _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; - - if( !pmm ) - { - len += _mali_osk_snprintf(buf + len, size + len, "PMM: Null state\n"); - } - else - { - len += _mali_osk_snprintf(buf+len, size+len, "Locks:\n PMM lock acquired: %s\n", - pmm->mali_pmm_lock_acquired ? "true" : "false"); - len += _mali_osk_snprintf(buf+len, size+len, - "PMM state:\n Previous status: %s\n Status: %s\n Current event: %s\n Policy: %s\n Check policy: %s\n State: %s\n", - pmm_trace_status[pmm->mali_last_pmm_status], pmm_trace_status[pmm->status], - pmm_trace_events[pmm->mali_new_event_status], pmm_trace_policy[pmm->policy], - pmm->check_policy ? "true" : "false", pmm_trace_state[pmm->state]); - len += _mali_osk_snprintf(buf+len, size+len, - "PMM cores:\n Cores registered: %d\n Cores powered: %d\n Cores idle: %d\n" - " Cores pending down: %d\n Cores pending up: %d\n Cores ack down: %d\n Cores ack up: %d\n", - pmm->cores_registered, pmm->cores_powered, pmm->cores_idle, pmm->cores_pend_down, - pmm->cores_pend_up, pmm->cores_ack_down, pmm->cores_ack_up); - len += _mali_osk_snprintf(buf+len, size+len, "PMM misc:\n PMU init: %s\n Messages queued: %d\n" - " Waiting: %d\n No events: %d\n Missed events: %d\n Fatal power error: %s\n", - pmm->pmu_initialized ? "true" : "false", _mali_osk_atomic_read(&(pmm->messages_queued)), - pmm->waiting, pmm->no_events, pmm->missed, pmm->fatal_power_err ? "true" : "false"); - } - return len; -} -#endif /* MALI_STATE_TRACKING */ - -#endif /* USING_MALI_PMM */ |