diff options
author | Eric Luong <x0119002@ti.com> | 2015-02-06 10:54:56 -0800 |
---|---|---|
committer | Hashcode <hashcode0f@gmail.com> | 2015-02-06 10:59:59 -0800 |
commit | 391c312c8964088c512de2cfb1e29c78d245d06b (patch) | |
tree | bdef0b7ecb2ff0da3c9b5922fa358fca1bdbbe73 /pvr-source/services4/srvkm/devices/sgx/sgxpower.c | |
parent | 882c2b4c53e1b2633700906b50c86d4b5f4ce274 (diff) | |
download | hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.zip hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.tar.gz hardware_ti_omap4-391c312c8964088c512de2cfb1e29c78d245d06b.tar.bz2 |
IMG DDK 1.9@2166536 for Android
IMG DDK Release 1.9@2166536 for Android.
Included in this release:
- User space and Kernel module binaries
- Kernel module source code
TI's Patches:
- 084d3db SGX-KM: sgxfreq: Enable on3demand governor as default
- c1e1f93 SGX-KM: on3demand: Added polling based on timeout
- 1baf19c Build: Compile OMAP4 kernel modules with arm-eabi toolchain
- e166956 Build: Add production build option to build script
- 9efd5d3 SGX UM: Properly update vertex shader constants when recompiled
- f6e71f1 Revert "Build: Add optional flag to disable uKernel logging"
- a49e042 SGXKM: Inherit PVRSRV_HAP_GPU_PAGEABLE flag
- f05da87 SGXUM: Creates a new PVRSRV_HAP MAPPING CTRL mask
- 0e6ac23 SGXKM: Creates a new PVRSRV_HAP MAPPING CTRL mask
- 5044cbb SGXKM: Divorce Sparse Mapping from GPU Pageable
- 4abdd37 SGX-KM: sgxfreq: Header for GPL license
- 7a1e61b gpu: thermal: adding cooling device for "case" management
- 1221aba SGX-KM: Add 'userspace' governor to sgxfreq
- 7cc1319 SGX-KM: Add on3demand governor to sgxfreq
- c3283ff SGX-KM: Allow sgxfreq active notification when prev state was active
- 7275e62 SGX-KM: Add idle and active time caluclation to sgxfreq
- e15265c SGX-KM: Add frame_done interface to sgxfreq
- a021f10 SGX-KM: Add activeidle governor to sgxfreq
- bbdceee SGX-KM: Add active/idle notification to sgxfreq
- 4e1e8d9 SGX-UM: Rework SGX idle notification
- fce3459 SGX-KM: Rework SGX idle notification
- 17cdf8c SGX-KM: Add onoff governor to sgxfreq
- 403caa1 SGX-KM: Add cooling device interface to sgxfreq
- 1d785b8 SGX-KM: Add sgxfreq subsystem for DVFS control
- 14de6d8 Build: Add optional flag to disable uKernel logging
- 374bea1 SGX UM: Set ro.product.processor before loading modules
- 91d286d SGX UM: Pvrsrvinit fix typo in remount command
- 3d08869 SGX UM: Remove BRN32044 for omap5
- 086f52b OMAP5: WA: Race condition when SGX is powered down
- 1a904c2 SGX KM: ShrinkPagePool statistics changed to PVR_DBG_MESSAGE
- fbf2890 SGX KM: Fix num_handle calculation for ion handles
- 322af97 BUILD: fix usage and help
- 50440d3 BUILD: Add install option "adb"
- ee66bfb pvr-km: gc: Add page offset for ion allocated buffers
- be4fe11 pvr-km: gc: Improve gc map/unmap logging
- 51da16d gralloc: Map NV12 buffers with the GC MMU
- 210b590 SGX-KM: Enable APM for OMAP5
- 31e2f05 SGX-UM: Enable APM for OMAP5
- a98b81b SGX-UM: Don't load omaplfb module when in-kernel driver is present
- b20f5c6 SGX-KM: Support in-kernel omaplfb
- 0955f19 SGXKM: Multi-plane support for deviceclass i-face
- 11f6682 build: remove omaplfb from install step
- 9ecd6e0 pvr-um: use arm-linux-androideabi- and fix JB debug build
- abef31d PVR-UM: Make pvrsrvinit wrapper compatible with Jellybean
- 5b4e4f0 Revert "SGXUM: Implements Gralloc late CPU mapping"
- 5f25289 SGX-UM: build - Remove target platform based configuration
- 9d5ac31 OMAP5: BUILD: Remove unused variable
- 5365b64 readme: Correct DDK version
- 8095cc6 SGX-UM: Add support for hardware specific powervr.ini files
- 7e13d26 PVR-UM: Add support to DDK for powervr.ini files
- e545f59 SGX-UM: Added 16 bit depth EGL configs
- 27da0ae SGX UM: Srvinit block until services ready
- ba35538 SGX UM: HAL block OpenPVRServices until services initialized
- 43f8c1f SGX UM: Fix calculation of chroma plane in blit_internal
- f6a6944 SGX KM: Dump dsscomp info during HW recovery
- fc6d85b SGXKM: Adds support for 1D buffer allocation
- d8d061b SGXKM: Do not perform explicit invalidate on mmap
- 3ac6e1f SGXUM: Implements Gralloc late CPU mapping
- b621744 SGXUM: Gralloc allow for late or no GPU mapping
- dde30cf SGXUM: Add allocation of images from system heap
- 552c0f5 SGXUM: Adds A8/U8/Y8 color format to WSEGL
- f1c7822 SGXKM: Increase XPROC_WORKAROUND to 500
- 65f61bf SGXKM: Fix cc-check.sh file permissions
- 0dfe392 SGXKM: Make the DMM offset optional
- 946eb30 gralloc: add support for GRALLOC_USAGE_EXCLUSIVE_DISP
- 5cf7248 gralloc: publicly define omap specific usage flags
- afcb9bd SGX-KM: Block DPLL cascading when SGX clock is enabled
- 616ff0b SGX-KM: Hold wake lock during hardware recovery
- 872b4c0 SGXKM: Fix NULL handle warning when blitting GC320
- 39de55c SGXKM: Allow for late or no GPU mapping
- d229a7b SGXKM: Allow for SW access to a tiler buffer
- 7024790 SGXUM: Adds YUV plane offsets for MM
- d202649 SGXKM: SGX Tiler non-page-aligned support
- 2b2ac18 SGXUM: Implements GPU Common Buffer Interface
- 86cd052 SGXUM: Multi-buffer manage bridge
- d272c49 SGXKM: Multi-buffer manage bridge
- 4d8facf SGXKM: Implements Heap Alloc Failure Report
- 6d4253a SGXUM: Add support for GPU unmap/remap
- 64f4805 SGXKM: Add support for GPU unmap/remap
- 5425356 SGX-KM: Use CONFIG_DRM_OMAP_DMM_TILER for kernel 3.4
- 853be19 SGX-KM: Use pud_offset to get pmd_offset
- 5ec5d70 PVR-KM: Prevent compilation of dc_omapfb3_linux
- 1bbe8a2 SGX-KM: Remove hardcoding of values in egl.cfg
- 83b8af6 pvr-km: kfree phys info at unmap instead of map
- f347fb9 pvr-km: add a struct size to the physical descriptor
- 6ccff8f gralloc: Set flag to enable GC MMU mapping in PVR services
- 0cfaa6d PVR-KM: Add function to obtain BV descriptor through 3PDC interface
- c8f4c5f PVR-KM: Map buffers to GC core MMU on allocation time with Bltsville
- 65b2b84 SGXKM: Prevent mapping of export with zero ref
- f4cc0a2 OMAP4-SGX-UM: Allow for tiler buffer SW access
- 5c97ded OMAP4-SGX-UM: Gralloc SW access and caching flags
- bbf5424 OMAP4-SGX-UM: Gralloc HAL_PIXEL_FORMAT_NV12 format
- ec6cc69 SGX-KM: Make PVRSRVExportFDToIONHandles generic and register it with ion
- 8c1255d PVR-KM: OMAP5: Use shared device for Tiler 2D Mappings
- 2391ac8 PVR-KM: OMAP5: Hardcode core version value
- 7d87962 SGX-KM: OMAP5: HACK: Set the size of the SGX registers
- 9f40224 SGX-UM: add detection of OMAP5432 in pvrsrvinit
- f75d48b SGX-UM: build: Add panda5 and omap5sevm to product list
- c23eff9 SGX-KM: BUILD: Add OMAP5 support
- 5cc4ade SGX-UM: BUILD: Consolidate build into a single Makefile
- 2c6a2f6 SGX-KM: (build) Remove Android product and version dependency
- 6f54fe8 Build: Don't install egl.cfg anymore
- a49c59c SGX-KM: egl.cfg sysfs entry
- c759928 SGX-KM: Enable DPF, TRACE and ASSERT
- 1628094 build-km: Enable blaze and blaze_tablet for ICS environment
- 05f00eb build: Enable blaze and blaze_tablet for ICS environment
- 542e279 SGX-KM: Add ability to build multiple sets of GFX kernel modules
- 69d3661 build: Set correct load directory for kernel modules.
- 2dfe14b KM: add support for sgx544sc
- 58f317a SGX-UM: Add ability to build multiple sets of GFX binaries
- 04e5deb SGX-KM: Use platform data for OPP symbols.
- 5eed373 SGX-UM: Enable building binaries for specific SGX
- 0801be2 readme: Add README
- 649d010 build: Add build_DDK.sh
- fe34640 Create gitignore file
- 519ca9a IMG DDK 1.9@2166536 for Android
Change-Id: I4a060344fa134a2484d1b7a69fc87963455e9e34
Signed-off-by: Eric Luong <x0119002@ti.com>
Diffstat (limited to 'pvr-source/services4/srvkm/devices/sgx/sgxpower.c')
-rw-r--r-- | pvr-source/services4/srvkm/devices/sgx/sgxpower.c | 630 |
1 files changed, 630 insertions, 0 deletions
diff --git a/pvr-source/services4/srvkm/devices/sgx/sgxpower.c b/pvr-source/services4/srvkm/devices/sgx/sgxpower.c new file mode 100644 index 0000000..2acd28d --- /dev/null +++ b/pvr-source/services4/srvkm/devices/sgx/sgxpower.c @@ -0,0 +1,630 @@ +/*************************************************************************/ /*! +@Title Device specific power routines +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved +@License Dual MIT/GPLv2 + +The contents of this file are subject to the MIT license as set out below. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Alternatively, the contents of this file may be used under the terms of +the GNU General Public License Version 2 ("GPL") in which case the provisions +of GPL are applicable instead of those above. + +If you wish to allow use of your version of this file only under the terms of +GPL, and not to allow others to use your version of this file under the terms +of the MIT license, indicate your decision by deleting the provisions above +and replace them with the notice and other provisions required by GPL as set +out in the file called "GPL-COPYING" included in this distribution. If you do +not delete the provisions above, a recipient may use your version of this file +under the terms of either the MIT license or GPL. + +This License is also included in this distribution in the file called +"MIT-COPYING". + +EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS +PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ /**************************************************************************/ + +#include <stddef.h> + +#include "sgxdefs.h" +#include "services_headers.h" +#include "sgxapi_km.h" +#include "sgx_mkif_km.h" +#include "sgxutils.h" +#include "pdump_km.h" + +int powering_down = 0; + + +#if defined(SUPPORT_HW_RECOVERY) +static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode, + SGX_TIMING_INFORMATION *psSGXTimingInfo, + IMG_HANDLE *phTimer) +{ + /* + Install timer callback for HW recovery at 50 times lower + frequency than the microkernel timer. + */ + *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode, + 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq); + if(*phTimer == IMG_NULL) + { + PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + return PVRSRV_OK; +} +#endif /* SUPPORT_HW_RECOVERY*/ + + +/*! +****************************************************************************** + + @Function SGXUpdateTimingInfo + + @Description + + Derives the microkernel timing info from the system-supplied values + + @Input psDeviceNode : SGX Device node + + @Return PVRSRV_ERROR : + +******************************************************************************/ +static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; +#if defined(SGX_DYNAMIC_TIMING_INFO) + SGX_TIMING_INFORMATION sSGXTimingInfo = {0}; +#else + SGX_DEVICE_MAP *psSGXDeviceMap; +#endif + IMG_UINT32 ui32ActivePowManSampleRate; + SGX_TIMING_INFORMATION *psSGXTimingInfo; + + +#if defined(SGX_DYNAMIC_TIMING_INFO) + psSGXTimingInfo = &sSGXTimingInfo; + SysGetSGXTimingInformation(psSGXTimingInfo); +#else + SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID**)&psSGXDeviceMap); + psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo; +#endif + +#if defined(SUPPORT_HW_RECOVERY) + { + PVRSRV_ERROR eError; + IMG_UINT32 ui32OlduKernelFreq; + + if (psDevInfo->hTimer != IMG_NULL) + { + ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock; + if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq) + { + /* + The ukernel timer frequency has changed. + */ + IMG_HANDLE hNewTimer; + + eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer); + if (eError == PVRSRV_OK) + { + eError = OSRemoveTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer")); + } + psDevInfo->hTimer = hNewTimer; + } + else + { + /* Failed to allocate the new timer, leave the old one. */ + } + } + } + else + { + eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + return eError; + } + } + + psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate = + psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq; + } +#endif /* SUPPORT_HW_RECOVERY*/ + + /* Copy the SGX clock speed for use in the kernel */ + psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed; + psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq; + + /* FIXME: no need to duplicate - remove it from psDevInfo */ + psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock; +#if defined(PDUMP) + PDUMPCOMMENT("Host Control - Microkernel clock"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); +#endif /* PDUMP */ + + if (psSGXTimingInfo->bEnableActivePM) + { + ui32ActivePowManSampleRate = + psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000; + /* + ui32ActivePowerCounter has the value 0 when SGX is not idle. + When SGX becomes idle, the value of ui32ActivePowerCounter is changed from 0 to ui32ActivePowManSampleRate. + The ukernel timer routine decrements the value of ui32ActivePowerCounter if it is not 0. + When the ukernel timer decrements ui32ActivePowerCounter from 1 to 0, the ukernel timer will + request power down. + Therefore the minimum value of ui32ActivePowManSampleRate is 1. + */ + ui32ActivePowManSampleRate += 1; + } + else + { + ui32ActivePowManSampleRate = 0; + } + + psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate; +#if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); +#endif /* PDUMP */ + + return PVRSRV_OK; +} + + +/*! +****************************************************************************** + + @Function SGXStartTimer + + @Description + + Start the microkernel timer + + @Input psDevInfo : SGX Device Info + + @Return IMG_VOID : + +******************************************************************************/ +static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo) +{ + #if defined(SUPPORT_HW_RECOVERY) + PVRSRV_ERROR eError; + + eError = OSEnableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer")); + } + #else + PVR_UNREFERENCED_PARAMETER(psDevInfo); + #endif /* SUPPORT_HW_RECOVERY */ +} + + +/*! +****************************************************************************** + + @Function SGXPollForClockGating + + @Description + + Wait until the SGX core clocks have gated. + + @Input psDevInfo : SGX Device Info + @Input ui32Register : Offset of register to poll + @Input ui32Register : Value of register to poll for + @Input pszComment : Description of poll + + @Return IMG_VOID : + +******************************************************************************/ +static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_UINT32 ui32Register, + IMG_UINT32 ui32RegisterValue, + IMG_CHAR *pszComment) +{ + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(ui32Register); + PVR_UNREFERENCED_PARAMETER(ui32RegisterValue); + PVR_UNREFERENCED_PARAMETER(pszComment); + + #if !defined(NO_HARDWARE) + PVR_ASSERT(psDevInfo != IMG_NULL); + + /* PRQA S 0505 1 */ /* QAC does not like assert() */ + if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2), + 0, + ui32RegisterValue, + MAX_HW_TIME_US, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + IMG_FALSE) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment)); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); + PVR_DBG_BREAK; + } + #endif /* NO_HARDWARE */ + + PDUMPCOMMENT("%s", pszComment); + PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL); +} + + +/*! +****************************************************************************** + + @Function SGXPrePowerState + + @Description + + does necessary preparation before power state transition + + @Input hDevHandle : SGX Device Node + @Input eNewPowerState : New power state + @Input eCurrentPowerState : Current power state + + @Return PVRSRV_ERROR : + +******************************************************************************/ +PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + if ((eNewPowerState != eCurrentPowerState) && + (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) + { + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32PowerCmd, ui32CompleteStatus; + SGXMKIF_COMMAND sCommand = {0}; + IMG_UINT32 ui32Core; + IMG_UINT32 ui32CoresEnabled; + + #if defined(SUPPORT_HW_RECOVERY) + /* Disable timer callback for HW recovery */ + eError = OSDisableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer")); + return eError; + } + #endif /* SUPPORT_HW_RECOVERY */ + + if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + /* Request the ukernel to idle SGX and save its state. */ + ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF; + ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE; + PDUMPCOMMENT("SGX power off request"); + } + else + { + /* Request the ukernel to idle SGX. */ + ui32PowerCmd = PVRSRV_POWERCMD_IDLE; + ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE; + PDUMPCOMMENT("SGX idle request"); + } + + powering_down = 1; + + sCommand.ui32Data[1] = ui32PowerCmd; + + eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command")); + return eError; + } + + /* Wait for the ukernel to complete processing. */ + #if !defined(NO_HARDWARE) + if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus, + ui32CompleteStatus, + ui32CompleteStatus, + MAX_HW_TIME_US, + MAX_HW_TIME_US/WAIT_TRY_COUNT, + IMG_FALSE) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed.")); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); + PVR_DBG_BREAK; + } + #endif /* NO_HARDWARE */ + + psDevInfo->bSGXIdle = IMG_TRUE; + + #if defined(PDUMP) + PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel."); + PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus), + ui32CompleteStatus, + ui32CompleteStatus, + PDUMP_POLL_OPERATOR_EQUAL, + 0, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif /* PDUMP */ + +#if defined(SGX_FEATURE_MP) + ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1; +#else + ui32CoresEnabled = 1; +#endif + + for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++) + { + /* Wait for SGX clock gating. */ + SGXPollForClockGating(psDevInfo, + SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core), + psDevInfo->ui32ClkGateStatusMask, + "Wait for SGX clock gating"); + } + + #if defined(SGX_FEATURE_MP) + /* Wait for SGX master clock gating. */ + SGXPollForClockGating(psDevInfo, + psDevInfo->ui32MasterClkGateStatusReg, + psDevInfo->ui32MasterClkGateStatusMask, + "Wait for SGX master clock gating"); + + SGXPollForClockGating(psDevInfo, + psDevInfo->ui32MasterClkGateStatus2Reg, + psDevInfo->ui32MasterClkGateStatus2Mask, + "Wait for SGX master clock gating (2)"); + #endif /* SGX_FEATURE_MP */ + + if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + /* Finally, de-initialise some registers. */ + eError = SGXDeinitialise(psDevInfo); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError)); + return eError; + } + } + } + + return PVRSRV_OK; +} + + +/*! +****************************************************************************** + + @Function SGXPostPowerState + + @Description + + does necessary preparation after power state transition + + @Input hDevHandle : SGX Device Node + @Input eNewPowerState : New power state + @Input eCurrentPowerState : Current power state + + @Return PVRSRV_ERROR : + +******************************************************************************/ +PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle, + PVRSRV_DEV_POWER_STATE eNewPowerState, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + if ((eNewPowerState != eCurrentPowerState) && + (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) + { + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + + /* Reset the power manager flags. */ + psSGXHostCtl->ui32PowerStatus = 0; + #if defined(PDUMP) + PDUMPCOMMENT("Host Control - Reset power status"); + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); + #endif /* PDUMP */ + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) + { + /* + Coming up from off, re-initialise SGX. + */ + + /* + Re-generate the timing data required by SGX. + */ + eError = SGXUpdateTimingInfo(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed")); + return eError; + } + + /* + Run the SGX init script. + */ + eError = SGXInitialise(psDevInfo, IMG_FALSE); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed")); + return eError; + } + powering_down = 0; + } + else + { + /* + Coming up from idle, restart the ukernel. + */ + SGXMKIF_COMMAND sCommand = {0}; + + sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME; + eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError)); + return eError; + } + } + + SGXStartTimer(psDevInfo); + } + + return PVRSRV_OK; +} + + +/*! +****************************************************************************** + + @Function SGXPreClockSpeedChange + + @Description + + Does processing required before an SGX clock speed change. + + @Input hDevHandle : SGX Device Node + @Input bIdleDevice : Whether the microkernel needs to be idled + @Input eCurrentPowerState : Power state of the device + + @Return PVRSRV_ERROR : + +******************************************************************************/ +PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) + { + if (bIdleDevice) + { + /* + * Idle SGX. + */ + PDUMPSUSPEND(); + + eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE, + PVRSRV_DEV_POWER_STATE_ON); + + if (eError != PVRSRV_OK) + { + PDUMPRESUME(); + return eError; + } + } + } + + PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz", + psDevInfo->ui32CoreClockSpeed)); + + return PVRSRV_OK; +} + + +/*! +****************************************************************************** + + @Function SGXPostClockSpeedChange + + @Description + + Does processing required after an SGX clock speed change. + + @Input hDevHandle : SGX Device Node + @Input bIdleDevice : Whether the microkernel had been idled previously + @Input eCurrentPowerState : Power state of the device + + @Return PVRSRV_ERROR : + +******************************************************************************/ +PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle, + IMG_BOOL bIdleDevice, + PVRSRV_DEV_POWER_STATE eCurrentPowerState) +{ + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed; + + PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed); + + if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) + { + PVRSRV_ERROR eError; + + /* + Re-generate the timing data required by SGX. + */ + eError = SGXUpdateTimingInfo(psDeviceNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed")); + return eError; + } + + if (bIdleDevice) + { + /* + * Resume SGX. + */ + eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON, + PVRSRV_DEV_POWER_STATE_IDLE); + + PDUMPRESUME(); + + if (eError != PVRSRV_OK) + { + return eError; + } + } + else + { + SGXStartTimer(psDevInfo); + } + } + + PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz", + ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed)); + + return PVRSRV_OK; +} + + +/****************************************************************************** + End of file (sgxpower.c) +******************************************************************************/ |