source: svn/newcon3bcm2_21bu/magnum/basemodules/chp/bchp_pwr.c @ 43

Last change on this file since 43 was 43, checked in by megakiss, 11 years ago

광주방송 OTC 주파수 369Mhz로 변경

  • Property svn:executable set to *
File size: 28.4 KB
Line 
1/***************************************************************************
2*     (c)2007-2010 Broadcom Corporation
3
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. 
13*   
14*  Except as expressly set forth in the Authorized License,
15*   
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*   
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: bchp_pwr.c $
39* $brcm_Revision: Hydra_Software_Devel/31 $
40* $brcm_Date: 2/8/12 12:34p $
41*
42* Module Description:
43*
44* Revision History:
45*
46* $brcm_Log: /magnum/basemodules/chp/bchp_pwr.c $
47*
48* Hydra_Software_Devel/31   2/8/12 12:34p jtna
49* SW7425-2330: power on everything during BCHP_PWR_Open if compiled
50* without BCHP_PWR_SUPPORT
51*
52* Hydra_Software_Devel/30   12/13/11 5:17p jtna
53* SW7425-1708: fix BCHP_PWR_Resume() to honor HW -> HW dependencies
54*
55* Hydra_Software_Devel/29   12/12/11 2:11p jtna
56* SW7425-1708: add BCHP_PWR_Standby/Resume() for clockgen power down
57*
58* Hydra_Software_Devel/28   6/20/11 12:02p jtna
59* SW7425-752: handle shared nodes correctly
60*
61* Hydra_Software_Devel/27   2/9/11 2:34p jtna
62* SW7420-1456: remove _isr functions
63*
64* Hydra_Software_Devel/25   2/1/11 11:53a jtna
65* SW7405-4433: ignore BDBG_MSG_TRACE
66*
67* Hydra_Software_Devel/24   1/18/11 4:12p jtna
68* SW7420-972: added initComplete member
69*
70* Hydra_Software_Devel/23   12/15/10 11:40a jtna
71* SW7420-972: fix compiler warning with BCHP_PWR_SUPPORT=n
72*
73* Hydra_Software_Devel/22   12/2/10 2:48p jtna
74* SW7420-972: more sanity checks
75*
76* Hydra_Software_Devel/21   11/18/10 7:33p jtna
77* SW7420-972: refactor init process
78*
79* Hydra_Software_Devel/20   10/28/10 5:48p jtna
80* SW7405-4810: add checkpoint-based gfx2d power management
81*
82* Hydra_Software_Devel/19   10/20/10 6:45p jtna
83* SW7420-972: rewrite to support HW_ -> HW_ dependency
84*
85* Hydra_Software_Devel/18   10/6/10 6:05p jtna
86* SW7420-972: better error handling and msgs
87*
88* Hydra_Software_Devel/17   10/1/10 3:02p jtna
89* SW7420-972: WRN at BCHP_PWR_Open() to indicate whether enabled or
90* disabled
91*
92* Hydra_Software_Devel/16   10/1/10 12:45p jtna
93* SW7420-972: wrap public API with #if BCHP_PWR_SUPPORT
94*
95* Hydra_Software_Devel/15   9/17/10 5:52p jtna
96* SW7420-972: allow HW resources to be initialized from any state
97*
98* Hydra_Software_Devel/14   9/9/10 5:02p jtna
99* SW7420-972: downgrade error msg when for re-initializing resource. more
100* sanity checks on Close()
101*
102* Hydra_Software_Devel/13   9/1/10 3:34p jtna
103* SW7420-972: add bchp_pwr resource init scheme
104*
105* Hydra_Software_Devel/12   8/26/10 3:00p jtna
106* SW7420-972: added RFM power management
107*
108* Hydra_Software_Devel/11   8/25/10 2:42p jtna
109* SW7420-972: define NEXUS_POWER_MANAGEMENT=2 for 7420. enable PX3D power
110* management.
111*
112* Hydra_Software_Devel/10   8/24/10 7:10p jtna
113* SW7420-972: add BCHP_PWR_P_Init
114*
115* Hydra_Software_Devel/9   8/20/10 12:32p jtna
116* SW7405-4433: change pHandle to handle
117*
118* Hydra_Software_Devel/8   8/19/10 10:44a jtna
119* SW7405-4433: update names
120*
121* Hydra_Software_Devel/7   8/13/10 5:27p jtna
122* SW7405-4433: changed node representation from pointer to #define
123* uint32_t
124*
125* Hydra_Software_Devel/6   6/17/10 12:28p jtna
126* SW7405-4433: add missing #include
127*
128* Hydra_Software_Devel/5   6/16/10 11:18a jtna
129* SW7405-4433: added internal synchronization
130*
131* Hydra_Software_Devel/4   6/9/10 3:34p jtna
132* SW7405-4433: add breg handle to bchp handle and don't require a breg
133* handle to be passed to the pwr functions
134*
135* Hydra_Software_Devel/3   6/9/10 12:11p jtna
136* SW7405-4433: added debug string to improve dump function
137*
138* Hydra_Software_Devel/2   6/8/10 6:55p jtna
139* SW7405-4433: extended refcnt functionality and added basic dump
140* function
141*
142* Hydra_Software_Devel/1   6/1/10 7:31p jtna
143* SW7405-4433: added bchp_pwr files
144*
145***************************************************************************/
146
147#include "bstd.h"
148#include "bkni.h"
149#include "bchp_pwr.h"
150#include "bchp_pwr_resources.h"
151#include "bchp_pwr_resources_priv.h"
152
153/* This file contains generic implementation of public APIs */
154
155BDBG_MODULE(BCHP_PWR);
156
157#define BDBG_MSG_TRACE(x) /*BDBG_MSG(x)*/
158
159extern const BCHP_PWR_P_Resource **BCHP_PWR_P_DependList[];
160extern const BCHP_PWR_P_Resource *BCHP_PWR_P_ResourceList[];
161
162#if BCHP_PWR_SUPPORT
163static BERR_Code BCHP_PWR_P_AcquireResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init);
164static BERR_Code BCHP_PWR_P_ReleaseResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init);
165void BCHP_PWR_P_Init(BCHP_Handle handle);
166unsigned BCHP_PWR_P_GetInternalIndex(BCHP_PWR_ResourceId resourceId);
167const BCHP_PWR_P_Resource* BCHP_PWR_P_GetResourceHandle(BCHP_PWR_ResourceId resourceId);
168#else
169static BERR_Code BCHP_PWR_P_AcquireResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init);
170void BCHP_PWR_P_InitOn(BCHP_Handle handle);
171#endif
172
173BERR_Code BCHP_PWR_Open(BCHP_PWR_Handle *pHandle, BCHP_Handle chp)
174{
175    BCHP_PWR_Handle pDev = NULL;
176    unsigned size;
177    BERR_Code rc;
178
179    BDBG_ASSERT(pHandle);
180    BDBG_ASSERT(chp);
181    BDBG_ASSERT(chp->regHandle);
182
183    size = sizeof(unsigned)*BCHP_PWR_P_NUM_ALLNODES;
184    pDev = BKNI_Malloc(sizeof(BCHP_PWR_P_Context));
185    if (!pDev) {
186        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
187        goto error;
188       
189    }
190    BKNI_Memset(pDev, 0, sizeof(BCHP_PWR_P_Context));
191   
192    rc = BKNI_CreateMutex(&(pDev->lock));
193    if (rc != BERR_SUCCESS) {
194        BERR_TRACE(rc);
195        goto error;
196    }
197
198    pDev->pubRefcnt = BKNI_Malloc(size);
199    if (!pDev->pubRefcnt) {
200        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
201        goto error;
202    }
203    BKNI_Memset(pDev->pubRefcnt, 0, size);
204
205    pDev->privRefcnt = BKNI_Malloc(size);
206    if (!pDev->privRefcnt) {
207        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
208        goto error;
209    }
210    BKNI_Memset(pDev->privRefcnt, 0, size);
211
212    size = sizeof(bool)*BCHP_PWR_P_NUM_ALLNODES;
213    pDev->init = BKNI_Malloc(size);
214    if (!pDev->init) {
215        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
216        goto error;
217    }
218    BKNI_Memset(pDev->init, 0, size);
219
220    pDev->magnumCtrl = BKNI_Malloc(size);
221    if (!pDev->magnumCtrl) {
222        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
223        goto error;
224    }
225    BKNI_Memset(pDev->magnumCtrl, 0, size);
226
227    pDev->sharedCtrl = BKNI_Malloc(size);
228    if (!pDev->sharedCtrl) {
229        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
230        goto error;
231    }
232    BKNI_Memset(pDev->sharedCtrl, 0, size);
233
234#if BCHP_PWR_SUPPORT
235    BDBG_WRN(("BCHP_PWR power management enabled"));
236    BDBG_MSG(("BCHP_PWR_Open: Non-HW %u, HW %u, Non-Leaf-HW %u", BCHP_PWR_P_NUM_NONLEAFS, BCHP_PWR_P_NUM_LEAFS, BCHP_PWR_P_NUM_NONLEAFSHW));
237
238    chp->pwrManager = pDev;
239    BCHP_PWR_P_Init(chp);
240   
241    *pHandle = pDev;
242    return BERR_SUCCESS;
243#else
244    BDBG_WRN(("BCHP_PWR power management disabled"));
245
246    /* turn on power for everything and never touch it again. this guarantees an initial power state similar to a chip-reset */
247    chp->pwrManager = pDev;
248    BCHP_PWR_P_InitOn(chp);
249    chp->pwrManager = NULL;
250    rc = BERR_SUCCESS;
251    /* keep going */
252#endif
253
254error:
255    if (pDev) {
256        if (pDev->lock) {
257            BKNI_DestroyMutex(pDev->lock);
258        }
259        if (pDev->pubRefcnt) {
260            BKNI_Free(pDev->pubRefcnt);
261        }
262        if (pDev->privRefcnt) {
263            BKNI_Free(pDev->privRefcnt);
264        }
265        if (pDev->init) {
266            BKNI_Free(pDev->init);
267        }
268        if (pDev->magnumCtrl) {
269            BKNI_Free(pDev->magnumCtrl);
270        }
271        if (pDev->sharedCtrl) {
272            BKNI_Free(pDev->sharedCtrl);
273        }
274        BKNI_Free(pDev);
275    }
276    return rc;
277}
278
279void BCHP_PWR_P_Init(BCHP_Handle handle)
280{
281#if BCHP_PWR_SUPPORT
282    const BCHP_PWR_P_Resource *resource = NULL;
283    unsigned i, idx;
284    unsigned refcnt[BCHP_PWR_P_NUM_ALLNODES];
285
286    BDBG_MSG(("BCHP_PWR_P_Init: >"));
287    BKNI_Memset(refcnt, 0, sizeof(refcnt));
288
289    /* power up all HW resources to guarantee an initial power state (everything powered up; this mimics a board reset).
290       this is done in two steps:
291       1) do an Acquire on MAGNUM_CONTROLLED node (with normal refcnt on all nodes)
292       2) go through the rest of the HW nodes (refcnt==0) and do an Acquire */
293
294#ifdef BCHP_PWR_RESOURCE_MAGNUM_CONTROLLED
295    resource = BCHP_PWR_P_GetResourceHandle(BCHP_PWR_RESOURCE_MAGNUM_CONTROLLED);
296    (void)BCHP_PWR_P_AcquireResource(handle, resource, true);
297    /* figure out which HW_ nodes are MAGNUM_CONTROLLED */
298    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
299        resource = BCHP_PWR_P_ResourceList[i];
300        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
301        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
302        refcnt[idx] = handle->pwrManager->privRefcnt[idx];
303        if (handle->pwrManager->privRefcnt[idx]>0) {
304            handle->pwrManager->magnumCtrl[idx] = true;
305        }   
306    }
307#endif
308   
309    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
310        resource = BCHP_PWR_P_ResourceList[i];
311        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
312        if (handle->pwrManager->privRefcnt[idx]==0) {
313            (void)BCHP_PWR_P_AcquireResource(handle, resource, true);
314        }
315    }
316    /* figure out which MAGNUM_CONTROLLED HW_ nodes also have a non-MAGNUM_CONTROLLED HW_ node parent */
317    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
318        resource = BCHP_PWR_P_ResourceList[i];
319        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
320        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
321        if (refcnt[idx]>0 && handle->pwrManager->privRefcnt[idx]>refcnt[idx]) {
322            handle->pwrManager->sharedCtrl[idx] = true;
323            BDBG_MSG(("Shared HW_ node %#x (%s)", resource->id, resource->name));
324        }   
325    }
326
327
328#if 0 /* debug dump */
329    BCHP_PWR_Dump(handle);
330#endif
331
332    /* power down MAGNUM_CONTROLLED node and mark its HW nodes as initialized.
333       the rest of the HW nodes are initialized via a call to InitAllHwResources() from upper-level SW */
334
335#ifdef BCHP_PWR_RESOURCE_MAGNUM_CONTROLLED
336    resource = BCHP_PWR_P_GetResourceHandle(BCHP_PWR_RESOURCE_MAGNUM_CONTROLLED);
337    BCHP_PWR_P_ReleaseResource(handle, resource, true);
338#endif
339
340    /* at this point all MAGNUM_CONTROLLED HW nodes are init=1 and refcnt=0.
341       all other HW nodes are init=0 and refcnt>0. */
342    handle->pwrManager->initComplete = true;
343    BDBG_MSG(("BCHP_PWR_P_Init: <"));
344
345#if 0 /* debug dump */
346    BCHP_PWR_Dump(handle);
347#endif
348
349#else /* BCHP_PWR_SUPPORT */
350    BSTD_UNUSED(handle);
351#endif
352}
353
354void BCHP_PWR_P_InitOn(BCHP_Handle handle)
355{
356#if (!BCHP_PWR_SUPPORT)
357    unsigned i;
358    const BCHP_PWR_P_Resource *resource = NULL;
359    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
360        resource = BCHP_PWR_P_ResourceList[i];
361        (void)BCHP_PWR_P_AcquireResource(handle, resource, true);
362    }
363    return;
364#else
365    BSTD_UNUSED(handle);
366#endif
367}
368
369void BCHP_PWR_Close(BCHP_PWR_Handle handle)
370{
371#if BCHP_PWR_SUPPORT
372    unsigned i;
373    bool clean = true;
374    BDBG_ASSERT(handle);
375    BDBG_MSG(("BCHP_PWR_Close: >"));
376   
377    for (i=0; i<BCHP_PWR_P_NUM_NONLEAFS; i++) {
378        if (handle->pubRefcnt[i]) {
379            BDBG_WRN(("BCHP_PWR_Close: Resource %#x (%s) still acquired (refcnt %u)", 
380                BCHP_PWR_P_ResourceList[i]->id, BCHP_PWR_P_ResourceList[i]->name, handle->pubRefcnt[i]));
381            clean = false;
382        }
383    }
384
385    /* sanity check: if public refcnts are all 0, then priv refcnts should also be all 0 */
386    if (clean) {
387        for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
388            if (handle->privRefcnt[i]>0) {
389                BDBG_ERR(("BCHP_PWR_Close: HW resource %#x (%s) has non-zero refcnt %u", 
390                    BCHP_PWR_P_ResourceList[i]->id, BCHP_PWR_P_ResourceList[i]->name, handle->privRefcnt[i]));
391            }
392        }
393    }
394
395    BKNI_DestroyMutex(handle->lock);
396    BKNI_Free(handle->pubRefcnt);
397    BKNI_Free(handle->privRefcnt);
398    BKNI_Free(handle->init);
399    BKNI_Free(handle->magnumCtrl);
400    BKNI_Free(handle->sharedCtrl);
401    BKNI_Free(handle);
402    BDBG_MSG(("BCHP_PWR_Close: <"));
403#else /* BCHP_PWR_SUPPORT */
404    BSTD_UNUSED(handle);
405#endif
406}
407
408#if 0 /* unused */
409/* returns true if "resource" is a dependency of another HW node */
410static bool BCHP_PWR_P_IsParentHwNode(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource)
411{
412    bool rc = false;
413    BSTD_UNUSED(handle);
414
415    if (resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw) {
416        unsigned i;
417        /* go through all HW nodes and see if "resource" is a dependant of any */
418        for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
419            const BCHP_PWR_P_Resource **res = BCHP_PWR_P_DependList[i];
420            if (res) {
421                for (;*res!=NULL;res++) {
422                    if (*res == resource) {
423                        return true;
424                    }
425                }
426            }
427        }
428    }
429    return rc;
430}
431#endif
432
433void BCHP_PWR_InitAllHwResources(BCHP_Handle handle)
434{
435#if BCHP_PWR_SUPPORT
436    const BCHP_PWR_P_Resource *resource;
437    unsigned i, idx;
438
439    BDBG_ASSERT(handle);
440    BDBG_ASSERT(handle->pwrManager);
441    BDBG_MSG(("BCHP_PWR_InitAllHwResources: >"));
442
443    BKNI_AcquireMutex(handle->pwrManager->lock);
444
445    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
446        resource = BCHP_PWR_P_ResourceList[i];
447        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
448        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
449
450        /* there can be 4 situations here:
451           init=1, refcnt =0 => already initialized as part of MAGNUM_CONTROLLED node
452           init=1, refcnt!=0 => assert
453           init=0, refcnt =0 => possibly a sharedCtrl node that was not released
454           init=0, refcnt!=0 => power down */
455
456        if (!handle->pwrManager->init[idx]) {
457            BDBG_ASSERT(handle->pwrManager->privRefcnt[idx]!=0);
458            (void)BCHP_PWR_P_ReleaseResource(handle, resource, true); /* power down */
459        }
460    }
461
462    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
463        resource = BCHP_PWR_P_ResourceList[i];
464        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
465        if (handle->pwrManager->privRefcnt[idx]) {
466            BDBG_WRN(("HW resource %#x (%s) not powered down", resource->id, resource->name));
467        }
468    }
469
470    BKNI_ReleaseMutex(handle->pwrManager->lock);
471    BDBG_MSG(("BCHP_PWR_InitAllHwResources: <"));
472
473#if 0 /* debug dump */
474    BCHP_PWR_Dump(handle);
475#endif
476
477#else /* BCHP_PWR_SUPPORT */
478    BSTD_UNUSED(handle);
479#endif
480}
481
482/* the #define ID's for both non-leaf nodes start at 1, not 0. for HW leaf nodes, it starts at 0xff000001.
483internally, we number them starting at 0 with the non-HW nodes, followed by HW nodes. */
484unsigned BCHP_PWR_P_GetInternalIndex(BCHP_PWR_ResourceId resourceId)
485{
486    unsigned index;
487    if ((resourceId & 0xff000000)==0xff000000) { /* HW */
488        index = resourceId - 0xff000000 - 1 + BCHP_PWR_P_NUM_NONLEAFS;
489        BDBG_ASSERT(index < BCHP_PWR_P_NUM_ALLNODES);
490    }
491    else {
492        index = resourceId - 1;
493        BDBG_ASSERT(index < BCHP_PWR_P_NUM_NONLEAFS);
494    }
495
496    return index;
497}
498
499const BCHP_PWR_P_Resource* BCHP_PWR_P_GetResourceHandle(BCHP_PWR_ResourceId resourceId)
500{
501    unsigned index = BCHP_PWR_P_GetInternalIndex(resourceId);
502    return BCHP_PWR_P_ResourceList[index];
503}
504
505static BERR_Code BCHP_PWR_P_AcquireResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init)
506{
507    BERR_Code rc = BERR_SUCCESS;
508    unsigned idx = BCHP_PWR_P_GetInternalIndex(resource->id);
509    int ref_cnt = handle->pwrManager->privRefcnt[idx];
510    bool init = handle->pwrManager->init[idx];
511    BDBG_MSG_TRACE(("  Acquire %#x (%s): %u", resource->id, resource->name, ref_cnt));
512
513    if (!init && !from_init) { /* uninitialized HW node */
514        if (resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw) {
515            if (handle->pwrManager->sharedCtrl[idx]) {
516                handle->pwrManager->init[idx] = true; /* mark as init and let refcnt increment */
517            }
518            else {
519                BDBG_WRN(("HW resource %#x (%s) must be initialized before being acquired", resource->id, resource->name));
520                return BERR_NOT_INITIALIZED;
521            }
522        }
523    }
524
525    switch(resource->type) {
526        case BCHP_PWR_P_ResourceType_eNonLeaf:
527        case BCHP_PWR_P_ResourceType_eNonLeafHw:
528        {
529            const BCHP_PWR_P_Resource **resources = BCHP_PWR_P_DependList[idx];
530            BDBG_ASSERT(resources);
531
532            for (;*resources!=NULL;resources++) {
533                rc |= BCHP_PWR_P_AcquireResource(handle, *resources, from_init);
534            }
535            if (resource->type==BCHP_PWR_P_ResourceType_eNonLeaf) {
536                break;
537            }
538            /* otherwise fall-through. for Acquire(), the recursive Acquire() must occur before activating the leaf HW node */
539        }
540        case BCHP_PWR_P_ResourceType_eLeaf:
541        {
542            if (ref_cnt==0) {
543                BDBG_MSG_TRACE(("  Activate HW node %#x (%s)", resource->id, resource->name));
544                BCHP_PWR_P_HW_Control(handle, resource, true);
545            }
546            break;
547        }
548    }
549
550    handle->pwrManager->privRefcnt[idx]++;
551    return rc;
552}
553
554#if BCHP_PWR_SUPPORT
555static BERR_Code BCHP_PWR_P_ReleaseResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init)
556{
557    BERR_Code rc = BERR_SUCCESS;
558    unsigned idx = BCHP_PWR_P_GetInternalIndex(resource->id);
559    int ref_cnt = handle->pwrManager->privRefcnt[idx];
560    bool init = handle->pwrManager->init[idx];
561    BDBG_MSG_TRACE(("  Release %#x (%s): %u", resource->id, resource->name, ref_cnt));
562
563    if (!init && !from_init) { /* uninitialized HW node */
564        if (resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw) {
565            BDBG_WRN(("HW resource %#x (%s) must be initialized before being released", resource->id, resource->name));
566            BDBG_ASSERT(0); /* should not be reachable via public API */
567            return BERR_NOT_INITIALIZED;
568        }
569        /* !init && from_init is the case when we're trying to initialize from P_Init()
570           init && !from_init is the case when we're trying to release via public API
571           init && from_init  means re-initializing, which is harmless. e.g. HW node with a HW parent */
572    }
573       
574    if (ref_cnt==0) {
575        BDBG_ERR(("Cannot release resource %#x (%s) with refcnt 0", resource->id, resource->name));
576        BDBG_ASSERT(0); /* should not be reachable via public API */
577        return BERR_NOT_INITIALIZED;
578    }
579
580    ref_cnt = --(handle->pwrManager->privRefcnt[idx]);
581
582    switch(resource->type) {
583        case BCHP_PWR_P_ResourceType_eLeaf:
584        case BCHP_PWR_P_ResourceType_eNonLeafHw:
585        {
586            if (ref_cnt==0) {
587                if (!from_init) {
588                    BDBG_MSG_TRACE(("  Deactivate HW node %#x (%s)", resource->id, resource->name));
589                } 
590                else {
591                    BDBG_MSG(("Initialize HW resource %#x (%s)", resource->id, resource->name));
592                    handle->pwrManager->init[idx] = true;
593                }
594                BCHP_PWR_P_HW_Control(handle, resource, false);
595            }
596            if (resource->type==BCHP_PWR_P_ResourceType_eLeaf) {
597                break;
598            }
599            /* otherwise fall-through. for Release(), the recursive Release() must occur after activating the leaf HW node */
600        }
601        case BCHP_PWR_P_ResourceType_eNonLeaf:
602        {
603            const BCHP_PWR_P_Resource **resources = BCHP_PWR_P_DependList[idx];
604            BDBG_ASSERT(resources);
605
606            for (;*resources!=NULL;resources++) {
607                rc |= BCHP_PWR_P_ReleaseResource(handle, *resources, from_init);
608            }
609            break;
610        }
611    }
612    return rc;
613}
614#endif /* BCHP_PWR_SUPPORT */
615
616BERR_Code BCHP_PWR_AcquireResource(BCHP_Handle handle, BCHP_PWR_ResourceId resourceId)
617{
618#if BCHP_PWR_SUPPORT
619    BERR_Code rc;
620    const BCHP_PWR_P_Resource *resource;
621    unsigned idx, refcnt;
622
623    BDBG_ASSERT(handle);
624    BDBG_ASSERT(handle->pwrManager);
625
626    if (!resourceId) {
627        return BERR_INVALID_PARAMETER;
628    }
629    if (resourceId > BCHP_PWR_P_NUM_NONLEAFS) { /* keep in mind that the public resource ID count starts from 1 */
630        return BERR_TRACE(BERR_INVALID_PARAMETER);
631    }
632
633    BKNI_AcquireMutex(handle->pwrManager->lock);
634
635    idx = BCHP_PWR_P_GetInternalIndex(resourceId);
636    resource = BCHP_PWR_P_GetResourceHandle(resourceId);
637    refcnt = handle->pwrManager->pubRefcnt[idx];
638
639    BDBG_MSG(("Acquire resource %#x (%s) refcnt %u->%u", resource->id, resource->name, refcnt, refcnt+1));
640    handle->pwrManager->pubRefcnt[idx]++;
641   
642    rc = BCHP_PWR_P_AcquireResource(handle, resource, false);
643
644    if (rc!=BERR_SUCCESS) {   
645        BDBG_ERR(("Acquire resource %#x (%s) failed. refcnt %u", resource->id, resource->name, refcnt));
646        handle->pwrManager->pubRefcnt[idx]--;
647    }
648
649    BKNI_ReleaseMutex(handle->pwrManager->lock);
650    return rc;
651#else /* BCHP_PWR_SUPPORT */
652    BSTD_UNUSED(handle);
653    BSTD_UNUSED(resourceId);
654    return BERR_SUCCESS;
655#endif
656}
657
658BERR_Code BCHP_PWR_ReleaseResource(BCHP_Handle handle, BCHP_PWR_ResourceId resourceId)
659{
660#if BCHP_PWR_SUPPORT
661    BERR_Code rc;
662    const BCHP_PWR_P_Resource *resource;
663    unsigned idx, refcnt;
664
665    BDBG_ASSERT(handle);
666    BDBG_ASSERT(handle->pwrManager);
667
668    if (!resourceId) {
669        return BERR_INVALID_PARAMETER;
670    }
671    if (resourceId > BCHP_PWR_P_NUM_NONLEAFS) { /* keep in mind that the public resource ID count starts from 1 */
672        return BERR_TRACE(BERR_INVALID_PARAMETER);
673    }
674
675    BKNI_AcquireMutex(handle->pwrManager->lock);
676
677    idx = BCHP_PWR_P_GetInternalIndex(resourceId);
678    resource = BCHP_PWR_P_GetResourceHandle(resourceId);
679    refcnt = handle->pwrManager->pubRefcnt[idx];
680
681    /* you can only release what you've acquired */
682    if (refcnt == 0) {
683        BDBG_ERR(("Unacquired power resource %#x (%s) cannot be released", resource->id, resource->name));
684        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
685    }
686    else {
687        BDBG_MSG(("Release resource %#x (%s) refcnt %u->%u", resource->id, resource->name, refcnt, refcnt-1));
688        handle->pwrManager->pubRefcnt[idx]--;
689
690        rc = BCHP_PWR_P_ReleaseResource(handle, resource, false);
691        if (rc!=BERR_SUCCESS) {
692            BDBG_ERR(("Release resource %#x (%s) failed. refcnt %u", resource->id, resource->name, refcnt));
693            handle->pwrManager->pubRefcnt[idx]++;
694        }
695    }
696
697    BKNI_ReleaseMutex(handle->pwrManager->lock);
698    return rc;
699#else /* BCHP_PWR_SUPPORT */
700    BSTD_UNUSED(handle);
701    BSTD_UNUSED(resourceId);
702    return BERR_SUCCESS;
703#endif
704}
705
706void BCHP_PWR_Dump(BCHP_Handle handle)
707{
708#if BCHP_PWR_SUPPORT
709    int i;
710    BDBG_ASSERT(handle);
711    BDBG_ASSERT(handle->pwrManager);
712
713    BKNI_AcquireMutex(handle->pwrManager->lock);
714   
715    BKNI_Printf("%-24s %5s %5s %5s\n", "resource name", "pub", "priv", "init");
716    for (i=0; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
717        /* cannot call BCHP_PWR_P_GetResourceHandle here because it requires the public resource ID */
718        BKNI_Printf("%-24s %5u %5u %5u\n", BCHP_PWR_P_ResourceList[i]->name,
719            handle->pwrManager->pubRefcnt[i], handle->pwrManager->privRefcnt[i], handle->pwrManager->init[i]);
720    }
721    BKNI_Printf("\n");
722
723    BKNI_ReleaseMutex(handle->pwrManager->lock);
724    return;
725#else /* BCHP_PWR_SUPPORT */
726    BSTD_UNUSED(handle);
727    return;
728#endif
729}
730
731BERR_Code BCHP_PWR_Standby(BCHP_Handle handle, const BCHP_PWR_StandbySettings *pSettings)
732{
733#if BCHP_PWR_SUPPORT
734    const BCHP_PWR_P_Resource *resource = NULL;
735    unsigned i, idx;
736
737    BDBG_ASSERT(handle);
738    BSTD_UNUSED(pSettings);
739    i = idx = 0;
740
741    /* prints which clocks are still alive */
742    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
743        resource = BCHP_PWR_P_ResourceList[i];
744        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
745        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
746        if (handle->pwrManager->privRefcnt[idx]!=0) {
747            BDBG_MSG(("Standby: clock %s still active", resource->name));
748        }
749    }
750
751    return BERR_SUCCESS;
752#else
753    BSTD_UNUSED(handle);
754    BSTD_UNUSED(pSettings);
755    return BERR_SUCCESS;
756#endif
757}
758
759void BCHP_PWR_Resume(BCHP_Handle handle)
760{
761#if BCHP_PWR_SUPPORT
762    const BCHP_PWR_P_Resource *resource = NULL;
763    unsigned i, idx;
764    unsigned *refcnt;
765    BDBG_ASSERT(handle);
766
767    /* on BCHP_PWR_Resume, we must re-apply the SW state to HW.
768       we can't just blindly Release HW nodes with refcnt 0, because HW -> HW dependencies must be honored
769       therefore, we must Acquire, then Release */
770    BDBG_MSG(("BCHP_PWR_Resume:>"));
771
772    /* save the current state, because we have to muck with it a little */
773    refcnt = BKNI_Malloc(sizeof(unsigned)*BCHP_PWR_P_NUM_ALLNODES);
774    if (!refcnt) {
775        BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
776        return;
777    }
778    BKNI_Memcpy(refcnt, handle->pwrManager->privRefcnt, sizeof(unsigned)*BCHP_PWR_P_NUM_ALLNODES);
779   
780    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
781        resource = BCHP_PWR_P_ResourceList[i];
782        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
783        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
784        if (refcnt[idx]==0) { /* node that should be powered down, according to the SW state */
785            BCHP_PWR_P_AcquireResource(handle, resource, false); /* if the HW is actually turned on, the Acquire call is only needed to increment the refcnt */
786        }
787    }
788
789    for (i=BCHP_PWR_P_NUM_NONLEAFS; i<BCHP_PWR_P_NUM_ALLNODES; i++) {
790        resource = BCHP_PWR_P_ResourceList[i];
791        BDBG_ASSERT(resource->type==BCHP_PWR_P_ResourceType_eLeaf || resource->type==BCHP_PWR_P_ResourceType_eNonLeafHw);
792        idx = BCHP_PWR_P_GetInternalIndex(resource->id);
793        if (refcnt[idx]==0) { /* node that should be powered down, according to the SW state */
794            BCHP_PWR_P_ReleaseResource(handle, resource, false);
795            BDBG_MSG(("Resume: clock %s powered down", resource->name));
796        }
797    }
798
799    /* this is an important sanity check */
800    i = BKNI_Memcmp(refcnt, handle->pwrManager->privRefcnt, sizeof(unsigned)*BCHP_PWR_P_NUM_ALLNODES);
801    BDBG_ASSERT(i==0);
802
803    BKNI_Free(refcnt);
804    BDBG_MSG(("BCHP_PWR_Resume:<"));
805       
806#else
807    BSTD_UNUSED(handle);
808    return;
809#endif
810}
811
Note: See TracBrowser for help on using the repository browser.