Initial commit
[kernel/linux-3.0.git] / drivers / media / video / samsung / mali_r2p3 / common / pmm / mali_pmm_state.c
1 /*
2  * Copyright (C) 2010 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #if USING_MALI_PMM
12
13 #include "mali_ukk.h"
14 #include "mali_kernel_common.h"
15 #include "mali_kernel_subsystem.h"
16
17 #include "mali_pmm.h"
18 #include "mali_pmm_state.h"
19 #include "mali_pmm_system.h"
20
21 #include "mali_kernel_core.h"
22 #include "mali_platform.h"
23
24 #define SIZEOF_CORES_LIST 6
25
26 /* NOTE: L2 *MUST* be first on the list so that it
27  * is correctly powered on first and powered off last
28  */
29 static mali_pmm_core_id cores_list[] = { MALI_PMM_CORE_L2,
30                                                                                 MALI_PMM_CORE_GP,
31                                                                                 MALI_PMM_CORE_PP0,
32                                                                                 MALI_PMM_CORE_PP1,
33                                                                                 MALI_PMM_CORE_PP2,
34                                                                                 MALI_PMM_CORE_PP3 };
35
36
37
38 void pmm_update_system_state( _mali_pmm_internal_state_t *pmm )
39 {
40         mali_pmm_state state;
41
42         MALI_DEBUG_ASSERT_POINTER(pmm);
43
44         if( pmm->cores_registered == 0 )
45         {
46                 state = MALI_PMM_STATE_UNAVAILABLE;
47         }
48         else if( pmm->cores_powered == 0 )
49         {
50                 state = MALI_PMM_STATE_SYSTEM_OFF;
51         }
52         else if( pmm->cores_powered == pmm->cores_registered )
53         {
54                 state = MALI_PMM_STATE_SYSTEM_ON;
55         }
56         else
57         {
58                 /* Some other state where not everything is on or off */
59                 state = MALI_PMM_STATE_SYSTEM_TRANSITION;
60         }
61
62 #if MALI_PMM_TRACE
63         _mali_pmm_trace_state_change( pmm->state, state );
64 #endif
65         pmm->state = state;
66 }
67
68 mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
69 {
70         mali_pmm_core_mask cores;
71         MALI_DEBUG_ASSERT_POINTER(pmm);
72         MALI_DEBUG_ASSERT_POINTER(event);
73
74         switch( event->id )
75         {
76         case MALI_PMM_EVENT_OS_POWER_UP:
77         case MALI_PMM_EVENT_OS_POWER_DOWN:
78                 /* All cores - the system */
79                 cores = pmm->cores_registered;
80                 break;
81
82         case MALI_PMM_EVENT_JOB_SCHEDULED:
83         case MALI_PMM_EVENT_JOB_QUEUED:
84         case MALI_PMM_EVENT_JOB_FINISHED:
85         case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
86         case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
87                 /* Currently the main event data is only the cores
88                  * for these messages
89                  */
90                 cores = (mali_pmm_core_mask)event->data;
91                 if( cores == MALI_PMM_CORE_SYSTEM )
92                 {
93                         cores = pmm->cores_registered;
94                 }
95                 else if( cores == MALI_PMM_CORE_PP_ALL )
96                 {
97                         /* Get the subset of registered PP cores */
98                         cores = (pmm->cores_registered & MALI_PMM_CORE_PP_ALL);
99                 }
100                 MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
101                 break;
102
103         default:
104                 /* Assume timeout messages - report cores still powered */
105                 cores = pmm->cores_powered;
106                 break;
107         }
108
109         return cores;
110 }
111
112 mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
113 {
114         mali_pmm_core_mask cores_subset;
115         MALI_DEBUG_ASSERT_POINTER(pmm);
116         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
117
118         /* Check that cores aren't pending power down when asked for power up */
119         MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
120
121         cores_subset = (~(pmm->cores_powered) & cores);
122         if( cores_subset != 0 )
123         {
124                 /* There are some cores that need powering up */
125                 pmm->cores_pend_up = cores_subset;
126         }
127
128         return cores_subset;
129 }
130
131 mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only )
132 {
133         mali_pmm_core_mask cores_subset;
134         _mali_osk_errcode_t err;
135         MALI_DEBUG_ASSERT_POINTER(pmm);
136         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
137
138         /* Check that cores aren't pending power up when asked for power down */
139         MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
140
141         cores_subset = (pmm->cores_powered & cores);
142         if( cores_subset != 0 )
143         {
144                 int n;
145                 volatile mali_pmm_core_mask *ppowered = &(pmm->cores_powered);
146
147                 /* There are some cores that need powering up, but we may
148                  * need to wait until they are idle
149                  */
150                 for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
151                 {
152                         if( (cores_list[n] & cores_subset) != 0 )
153                         {
154                                 /* Core is to be powered down */
155                                 pmm->cores_pend_down |= cores_list[n];
156
157                                 /* Can't hold the power lock, when acessing subsystem mutex via
158                                  * the core power call.
159                                  * Due to terminatation of driver requiring a subsystem mutex
160                                  * and then power lock held to unregister a core.
161                                  * This does mean that the following function could fail
162                                  * as the core is unregistered before we tell it to power
163                                  * down, but it does not matter as we are terminating
164                                  */
165 #if MALI_STATE_TRACKING
166                 pmm->mali_pmm_lock_acquired = 0;
167 #endif /* MALI_STATE_TRACKING */
168
169                                 MALI_PMM_UNLOCK(pmm);
170                                 /* Signal the core to power down
171                                  * If it is busy (not idle) it will set a pending power down flag 
172                                  * (as long as we don't want to only immediately power down). 
173                                  * If it isn't busy it will move out of the idle queue right
174                                  * away
175                                  */
176                                 err = mali_core_signal_power_down( cores_list[n], immediate_only );
177                                 MALI_PMM_LOCK(pmm);
178
179 #if MALI_STATE_TRACKING
180                 pmm->mali_pmm_lock_acquired = 1;
181 #endif /* MALI_STATE_TRACKING */
182                         
183
184                                 /* Re-read cores_subset in case it has changed */
185                                 cores_subset = (*ppowered & cores);
186
187                                 if( err == _MALI_OSK_ERR_OK )
188                                 {
189                                         /* We moved an idle core to the power down queue
190                                          * which means it is now acknowledged (if it is still 
191                                          * registered)
192                                          */
193                                         pmm->cores_ack_down |= (cores_list[n] & cores_subset);
194                                 }
195                                 else
196                                 {
197                                         MALI_DEBUG_PRINT(1,("The error in PMM is ...%x...%x",err,*ppowered));
198                                         MALI_DEBUG_ASSERT( err == _MALI_OSK_ERR_BUSY ||
199                                                                                 (err == _MALI_OSK_ERR_FAULT &&
200                                                                                 (*ppowered & cores_list[n]) == 0) );
201                                         /* If we didn't move a core - it must be active, so
202                                          * leave it pending, so we get an acknowledgement (when
203                                          * not in immediate only mode)
204                                          * Alternatively we are shutting down and the core has
205                                          * been unregistered
206                                          */
207                                 }
208                         }
209                 }
210         }
211
212         return cores_subset;
213 }
214
215 void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm )
216 {
217         int n;
218         mali_pmm_core_mask pd, ad;
219         _mali_osk_errcode_t err;
220         volatile mali_pmm_core_mask *pregistered;
221
222         MALI_DEBUG_ASSERT_POINTER(pmm);
223
224         MALIPMM_DEBUG_PRINT( ("PMM: Cancelling power down\n") );
225
226         pd = pmm->cores_pend_down;
227         ad = pmm->cores_ack_down;
228         /* Clear the pending cores so that they don't move to the off
229          * queue if they haven't already
230          */
231         pmm->cores_pend_down = 0;
232         pmm->cores_ack_down = 0;
233         pregistered = &(pmm->cores_registered);
234
235         /* Power up all the pending power down cores - just so
236          * we make sure the system is in a known state, as a
237          * pending core might have sent an acknowledged message
238          * which hasn't been read yet.
239          */
240         for( n = 0; n < SIZEOF_CORES_LIST; n++ )
241         {
242                 if( (cores_list[n] & pd) != 0 )
243                 {
244                         /* Can't hold the power lock, when acessing subsystem mutex via
245                          * the core power call.
246                          * Due to terminatation of driver requiring a subsystem mutex
247                          * and then power lock held to unregister a core.
248                          * This does mean that the following power up function could fail
249                          * as the core is unregistered before we tell it to power
250                          * up, but it does not matter as we are terminating
251                          */
252 #if MALI_STATE_TRACKING
253                         pmm->mali_pmm_lock_acquired = 0;
254 #endif /* MALI_STATE_TRACKING */
255
256                         MALI_PMM_UNLOCK(pmm);
257                         /* As we are cancelling - only move the cores back to the queue - 
258                          * no reset needed
259                          */
260                         err = mali_core_signal_power_up( cores_list[n], MALI_TRUE );
261                         MALI_PMM_LOCK(pmm);
262 #if MALI_STATE_TRACKING
263                         pmm->mali_pmm_lock_acquired = 1;
264 #endif /* MALI_STATE_TRACKING */
265
266                         /* Update pending list with the current registered cores */
267                         pd &= (*pregistered);
268
269                         if( err != _MALI_OSK_ERR_OK )
270                         {
271                                 MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_BUSY && 
272                                                                                 ((cores_list[n] & ad) == 0))  ||
273                                                                                 (err == _MALI_OSK_ERR_FAULT &&
274                                                                                 (*pregistered & cores_list[n]) == 0) );
275                                 /* If we didn't power up a core - it must be active and 
276                                  * hasn't actually tried to power down - this is expected
277                                  * for cores that haven't acknowledged
278                                  * Alternatively we are shutting down and the core has
279                                  * been unregistered
280                                  */
281                         }
282                 }
283         }
284         /* Only used in debug builds */
285         MALI_IGNORE(ad);
286 }
287
288
289 mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm )
290 {
291         MALI_DEBUG_ASSERT_POINTER(pmm);
292
293         return ( pmm->cores_pend_down == pmm->cores_ack_down ? MALI_TRUE : MALI_FALSE );
294 }
295
296 mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode )
297 {
298         _mali_osk_errcode_t err;
299         MALI_DEBUG_ASSERT_POINTER(pmm);
300
301         /* Check that cores are pending power down during power down invoke */
302         MALI_DEBUG_ASSERT( pmm->cores_pend_down != 0 );
303         /* Check that cores are not pending power up during power down invoke */
304         MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
305
306         if( !pmm_power_down_okay( pmm ) )
307         {
308                 MALIPMM_DEBUG_PRINT( ("PMM: Waiting for cores to go idle for power off - 0x%08x / 0x%08x\n", 
309                                 pmm->cores_pend_down, pmm->cores_ack_down) );
310                 return MALI_FALSE;
311         }
312         else
313         {
314                 pmm->cores_powered &= ~(pmm->cores_pend_down);
315 #if !MALI_PMM_NO_PMU
316                 err = malipmm_powerdown( pmm->cores_pend_down, power_mode);
317 #else
318                 err = _MALI_OSK_ERR_OK;
319 #endif
320                 
321                 if( err == _MALI_OSK_ERR_OK )
322                 {
323 #if MALI_PMM_TRACE
324                         mali_pmm_core_mask old_power = pmm->cores_powered;
325 #endif
326                         /* Remove powered down cores from idle and powered list */
327                         pmm->cores_idle &= ~(pmm->cores_pend_down);
328                         /* Reset pending/acknowledged status */
329                         pmm->cores_pend_down = 0;
330                         pmm->cores_ack_down = 0;
331 #if MALI_PMM_TRACE
332                         _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
333 #endif
334                 }
335                 else
336                 {
337                         pmm->cores_powered |= pmm->cores_pend_down;
338                         MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power down cores - (0x%x) %s", 
339                                         pmm->cores_pend_down, pmm_trace_get_core_name(pmm->cores_pend_down)) );
340                         pmm->fatal_power_err = MALI_TRUE;
341                 }
342         }
343
344         return MALI_TRUE;
345 }
346
347
348 mali_bool pmm_power_up_okay( _mali_pmm_internal_state_t *pmm )
349 {
350         MALI_DEBUG_ASSERT_POINTER(pmm);
351
352         return ( pmm->cores_pend_up == pmm->cores_ack_up ? MALI_TRUE : MALI_FALSE );
353 }
354
355
356 mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm )
357 {
358         _mali_osk_errcode_t err;
359
360         MALI_DEBUG_ASSERT_POINTER(pmm);
361
362         /* Check that cores are pending power up during power up invoke */
363         MALI_DEBUG_ASSERT( pmm->cores_pend_up != 0 );
364         /* Check that cores are not pending power down during power up invoke */
365         MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
366
367         if( pmm_power_up_okay( pmm ) )
368         {
369                 /* Power up has completed - sort out subsystem core status */
370                 
371                 int n;
372                 /* Use volatile to access, so that it is updated if any cores are unregistered */
373                 volatile mali_pmm_core_mask *ppendup = &(pmm->cores_pend_up);
374 #if MALI_PMM_TRACE
375                 mali_pmm_core_mask old_power = pmm->cores_powered;
376 #endif
377                 /* Move cores into idle queues */
378                 for( n = 0; n < SIZEOF_CORES_LIST; n++ )
379                 {
380                         if( (cores_list[n] & (*ppendup)) != 0 )
381                         {
382                                 /* Can't hold the power lock, when acessing subsystem mutex via
383                                  * the core power call.
384                                  * Due to terminatation of driver requiring a subsystem mutex
385                                  * and then power lock held to unregister a core.
386                                  * This does mean that the following function could fail
387                                  * as the core is unregistered before we tell it to power
388                                  * up, but it does not matter as we are terminating
389                                  */
390 #if MALI_STATE_TRACKING
391                                 pmm->mali_pmm_lock_acquired = 0;
392 #endif /* MALI_STATE_TRACKING */
393
394                                 MALI_PMM_UNLOCK(pmm);
395                                 err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
396                                 MALI_PMM_LOCK(pmm);
397
398 #if MALI_STATE_TRACKING
399                                 pmm->mali_pmm_lock_acquired = 1;
400 #endif /* MALI_STATE_TRACKING */
401
402
403                                 if( err != _MALI_OSK_ERR_OK )
404                                 {
405                                         MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT &&
406                                                                                 (*ppendup & cores_list[n]) == 0) );
407                                         /* We only expect this to fail when we are shutting down 
408                                          * and the core has been unregistered
409                                          */
410                                 }
411                         }
412                 }
413                 /* Finished power up - add cores to idle and powered list */
414                 pmm->cores_powered |= (*ppendup);
415                 pmm->cores_idle |= (*ppendup);
416                 /* Reset pending/acknowledge status */
417                 pmm->cores_pend_up = 0;
418                 pmm->cores_ack_up = 0;
419
420 #if MALI_PMM_TRACE
421                 _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
422 #endif
423                 return MALI_TRUE;
424         }
425         else
426         {
427 #if !MALI_PMM_NO_PMU
428                 /* Power up must now be done */
429                 err = malipmm_powerup( pmm->cores_pend_up );
430 #else
431                 err = _MALI_OSK_ERR_OK;
432 #endif
433                 if( err != _MALI_OSK_ERR_OK )
434                 {
435                         MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power up cores - (0x%x) %s", 
436                                         pmm->cores_pend_up, pmm_trace_get_core_name(pmm->cores_pend_up)) );
437                         pmm->fatal_power_err = MALI_TRUE;
438                 }
439                 else
440                 {
441                         /* TBD - Update core status immediately rather than use event message */
442                         _mali_uk_pmm_message_s event = {
443                                 NULL,
444                                 MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK,
445                                 0 };
446                         /* All the cores that were pending power up, have now completed power up */
447                         event.data = pmm->cores_pend_up;
448                         _mali_ukk_pmm_event_message( &event );
449                         MALIPMM_DEBUG_PRINT( ("PMM: Sending ACK to power up") );
450                 }
451         }
452
453         /* Always return false, as we need an interrupt to acknowledge
454          * when power up is complete
455          */
456         return MALI_FALSE;
457 }
458
459 mali_pmm_core_mask pmm_cores_set_active( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
460 {
461         MALI_DEBUG_ASSERT_POINTER(pmm);
462         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
463
464         pmm->cores_idle &= (~cores);
465         return pmm->cores_idle;
466 }
467
468 mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
469 {
470         MALI_DEBUG_ASSERT_POINTER(pmm);
471         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
472
473         pmm->cores_idle |= (cores);
474         return pmm->cores_idle;
475 }
476
477 mali_pmm_core_mask pmm_cores_set_down_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
478 {
479         MALI_DEBUG_ASSERT_POINTER(pmm);
480         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
481
482         /* Check core is not pending a power down */
483         MALI_DEBUG_ASSERT( (pmm->cores_pend_down & cores) != 0 );
484         /* Check core has not acknowledged power down more than once */
485         MALI_DEBUG_ASSERT( (pmm->cores_ack_down & cores) == 0 );
486
487         pmm->cores_ack_down |= (cores);
488
489         return pmm->cores_ack_down;
490 }
491
492 void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm )
493 {
494         _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
495         _mali_osk_notification_t *msg = NULL;
496         mali_pmm_status status;
497         MALI_DEBUG_ASSERT_POINTER(pmm);
498         MALIPMM_DEBUG_PRINT( ("PMM: Fatal Reset called") ); 
499
500         MALI_DEBUG_ASSERT( pmm->status != MALI_PMM_STATUS_OFF );
501
502         /* Reset the common status */
503         pmm->waiting = 0;
504         pmm->missed = 0;
505         pmm->fatal_power_err = MALI_FALSE;
506         pmm->no_events = 0;
507         pmm->check_policy = MALI_FALSE;
508         pmm->cores_pend_down = 0;
509         pmm->cores_pend_up = 0;
510         pmm->cores_ack_down = 0;
511         pmm->cores_ack_up = 0;
512         pmm->is_dvfs_active = 0; 
513 #if MALI_PMM_TRACE
514         pmm->messages_sent = 0;
515         pmm->messages_received = 0;
516         pmm->imessages_sent = 0;
517         pmm->imessages_received = 0;
518         MALI_PRINT( ("PMM Trace: *** Fatal reset occurred ***") );
519 #endif
520
521         /* Set that we are unavailable whilst resetting */
522         pmm->state = MALI_PMM_STATE_UNAVAILABLE;
523         status = pmm->status;
524         pmm->status = MALI_PMM_STATUS_OFF;
525
526         /* We want all cores powered */
527         pmm->cores_powered = pmm->cores_registered;
528         /* The cores may not be idle, but this state will be rectified later */
529         pmm->cores_idle = pmm->cores_registered;
530         
531         /* So power on any cores that are registered */
532         if( pmm->cores_registered != 0 )
533         {
534                 int n;
535                 volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered);
536 #if !MALI_PMM_NO_PMU
537                 err = malipmm_powerup( pmm->cores_registered );
538 #endif
539                 if( err != _MALI_OSK_ERR_OK )
540                 {
541                         /* This is very bad as we can't even be certain the cores are now 
542                          * powered up
543                          */
544                         MALI_PRINT_ERROR( ("PMM: Failed to perform PMM reset!\n") );
545                         /* TBD driver exit? */
546                 }
547
548                 for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
549                 {
550                         if( (cores_list[n] & (*pregistered)) != 0 )
551                         {
552 #if MALI_STATE_TRACKING
553                                 pmm->mali_pmm_lock_acquired = 0;
554 #endif /* MALI_STATE_TRACKING */
555
556                                 MALI_PMM_UNLOCK(pmm);
557                                 /* Core is now active - so try putting it in the idle queue */
558                                 err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
559                                 MALI_PMM_LOCK(pmm);
560 #if MALI_STATE_TRACKING
561                 pmm->mali_pmm_lock_acquired = 1;
562 #endif /* MALI_STATE_TRACKING */
563
564                                 /* We either succeeded, or we were not off anyway, or we have
565                                  * just be deregistered 
566                                  */
567                                 MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_OK) ||
568                                                                         (err == _MALI_OSK_ERR_BUSY) ||
569                                                                         (err == _MALI_OSK_ERR_FAULT && 
570                                                                         (*pregistered & cores_list[n]) == 0) );
571                         }
572                 }
573         }
574
575         /* Unblock any pending OS event */
576         if( status == MALI_PMM_STATUS_OS_POWER_UP )
577         {
578                 /* Get the OS data and respond to the power up */
579                 _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
580         }
581         if( status == MALI_PMM_STATUS_OS_POWER_DOWN )
582         {
583                 /* Get the OS data and respond to the power down 
584                  * NOTE: We are not powered down at this point due to power problems,
585                  * so we are lying to the system, but something bad has already 
586                  * happened and we are trying unstick things
587                  * TBD - Add busy loop to power down cores?
588                  */
589                 _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
590         }
591                 
592         /* Purge the event queues */
593         do
594         {
595                 if( _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ) == _MALI_OSK_ERR_OK )
596                 {
597                         _mali_osk_notification_delete ( msg );
598                         break;
599                 }
600         } while (MALI_TRUE);
601
602         do
603         {
604                 if( _mali_osk_notification_queue_dequeue( pmm->queue, &msg ) == _MALI_OSK_ERR_OK )
605                 {
606                         _mali_osk_notification_delete ( msg );
607                         break;
608                 }
609         } while (MALI_TRUE);
610
611         /* Return status/state to normal */
612         pmm->status = MALI_PMM_STATUS_IDLE;
613         pmm_update_system_state(pmm);
614 }
615
616 mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
617 {
618         MALI_DEBUG_ASSERT_POINTER(pmm);
619         MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
620
621         /* Check core is not pending a power up */
622         MALI_DEBUG_ASSERT( (pmm->cores_pend_up & cores) != 0 );
623         /* Check core has not acknowledged power up more than once */
624         MALI_DEBUG_ASSERT( (pmm->cores_ack_up & cores) == 0 );
625
626         pmm->cores_ack_up |= (cores);
627
628         return pmm->cores_ack_up;
629 }
630
631 void pmm_save_os_event_data(_mali_pmm_internal_state_t *pmm, mali_pmm_message_data data)
632 {
633         MALI_DEBUG_ASSERT_POINTER(pmm);
634         /* Check that there is no saved data */
635         MALI_DEBUG_ASSERT( pmm->os_data == 0 );
636         /* Can't store zero data - as retrieve check will fail */
637         MALI_DEBUG_ASSERT( data != 0 );
638
639         pmm->os_data = data;
640 }
641
642 mali_pmm_message_data pmm_retrieve_os_event_data(_mali_pmm_internal_state_t *pmm)
643 {
644         mali_pmm_message_data data;
645
646         MALI_DEBUG_ASSERT_POINTER(pmm);
647         /* Check that there is saved data */
648         MALI_DEBUG_ASSERT( pmm->os_data != 0 );
649
650         /* Get data, and clear the saved version */
651         data = pmm->os_data;
652         pmm->os_data = 0;
653
654         return data;
655 }
656
657 /* Create list of core names to look up
658  * We are doing it this way to overcome the need for
659  * either string allocation, or stack space, so we
660  * use constant strings instead
661  */
662 typedef struct pmm_trace_corelist
663 {
664         mali_pmm_core_mask id;
665         const char *name;
666 } pmm_trace_corelist_t;
667
668 static pmm_trace_corelist_t pmm_trace_cores[] = {
669         { MALI_PMM_CORE_SYSTEM,  "SYSTEM" },
670         { MALI_PMM_CORE_GP,      "GP" },
671         { MALI_PMM_CORE_L2,      "L2" },
672         { MALI_PMM_CORE_PP0,     "PP0" },
673         { MALI_PMM_CORE_PP1,     "PP1" },
674         { MALI_PMM_CORE_PP2,     "PP2" },
675         { MALI_PMM_CORE_PP3,     "PP3" },
676         { MALI_PMM_CORE_PP_ALL,  "PP (all)" },
677         { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0),
678                 "GP+L2+PP0" },
679         { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0),
680                 "GP+PP0" },     
681         { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
682                 "GP+L2+PP0+PP1" },
683         { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
684                 "GP+PP0+PP1" },
685         { 0, NULL } /* Terminator of list */
686 };
687
688 const char *pmm_trace_get_core_name( mali_pmm_core_mask cores )
689 {
690         const char *dname = NULL;
691         int cl;
692         
693         /* Look up name in corelist */
694         cl = 0;
695         while( pmm_trace_cores[cl].name != NULL )
696         {
697                 if( pmm_trace_cores[cl].id == cores )
698                 {
699                         dname = pmm_trace_cores[cl].name;
700                         break;
701                 }
702                 cl++;
703         }
704         
705         if( dname == NULL )
706         {
707                 /* We don't know a good short-hand for the configuration */
708                 dname = "[multi-core]";
709         }
710
711         return dname;
712 }
713
714 #endif /* USING_MALI_PMM */
715