| 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 | |
|---|
| 155 | BDBG_MODULE(BCHP_PWR); |
|---|
| 156 | |
|---|
| 157 | #define BDBG_MSG_TRACE(x) /*BDBG_MSG(x)*/ |
|---|
| 158 | |
|---|
| 159 | extern const BCHP_PWR_P_Resource **BCHP_PWR_P_DependList[]; |
|---|
| 160 | extern const BCHP_PWR_P_Resource *BCHP_PWR_P_ResourceList[]; |
|---|
| 161 | |
|---|
| 162 | #if BCHP_PWR_SUPPORT |
|---|
| 163 | static BERR_Code BCHP_PWR_P_AcquireResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init); |
|---|
| 164 | static BERR_Code BCHP_PWR_P_ReleaseResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init); |
|---|
| 165 | void BCHP_PWR_P_Init(BCHP_Handle handle); |
|---|
| 166 | unsigned BCHP_PWR_P_GetInternalIndex(BCHP_PWR_ResourceId resourceId); |
|---|
| 167 | const BCHP_PWR_P_Resource* BCHP_PWR_P_GetResourceHandle(BCHP_PWR_ResourceId resourceId); |
|---|
| 168 | #else |
|---|
| 169 | static BERR_Code BCHP_PWR_P_AcquireResource(BCHP_Handle handle, const BCHP_PWR_P_Resource *resource, bool from_init); |
|---|
| 170 | void BCHP_PWR_P_InitOn(BCHP_Handle handle); |
|---|
| 171 | #endif |
|---|
| 172 | |
|---|
| 173 | BERR_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 | |
|---|
| 254 | error: |
|---|
| 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 | |
|---|
| 279 | void 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 | |
|---|
| 354 | void 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 | |
|---|
| 369 | void 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 */ |
|---|
| 410 | static 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 | |
|---|
| 433 | void 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. |
|---|
| 483 | internally, we number them starting at 0 with the non-HW nodes, followed by HW nodes. */ |
|---|
| 484 | unsigned 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 | |
|---|
| 499 | const 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 | |
|---|
| 505 | static 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 |
|---|
| 555 | static 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 | |
|---|
| 616 | BERR_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 | |
|---|
| 658 | BERR_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 | |
|---|
| 706 | void 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 | |
|---|
| 731 | BERR_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 | |
|---|
| 759 | void 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 | |
|---|