1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
29 #include <linux/sched.h>
32 #include "services_headers.h"
33 #include "sgxapi_km.h"
34 #include "sgxinfokm.h"
36 #include "pvr_pdump.h"
38 #define MS_TO_NS(x) ((x) * 1000000ULL)
39 #define SGX_CMD_BURST_THRESHOLD_NS MS_TO_NS(3)
40 #define SGX_CMD_BURST_MAX_SIZE 4
41 #define SGX_POWER_DOWN_DELAY_LONG_MS 4
42 #define SGX_POWER_DOWN_DELAY_SHORT_MS 0
44 enum PVR_DEVICE_POWER_STATE {
46 PVR_DEVICE_POWER_STATE_ON = 0,
47 PVR_DEVICE_POWER_STATE_IDLE = 1,
48 PVR_DEVICE_POWER_STATE_OFF = 2,
50 PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff
53 static enum PVR_DEVICE_POWER_STATE MapDevicePowerState(enum PVR_POWER_STATE
56 enum PVR_DEVICE_POWER_STATE eDevicePowerState;
58 switch (ePowerState) {
59 case PVRSRV_POWER_STATE_D0:
61 eDevicePowerState = PVR_DEVICE_POWER_STATE_ON;
64 case PVRSRV_POWER_STATE_D3:
66 eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF;
71 PVR_DPF(PVR_DBG_ERROR,
72 "MapDevicePowerState: Invalid state: %ld",
74 eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32;
79 return eDevicePowerState;
82 static void sgx_set_pwrdown_delay(struct PVRSRV_DEVICE_NODE *node,
83 unsigned ukernel_freq, int msec)
85 struct PVRSRV_SGXDEV_INFO *dev_info = node->pvDevice;
88 delay = ukernel_freq * msec / 1000 + 1;
89 if (dev_info->power_down_delay != delay) {
91 &dev_info->psSGXHostCtl->ui32ActivePowManSampleRate);
92 dev_info->power_down_delay = delay;
96 static int sgx_calc_power_down_delay(struct PVRSRV_DEVICE_NODE *node)
98 struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
101 * Set the power down delay to short if the command to be executed is
102 * the last one in the burst, except if the burst size is at the
105 if (info->burst_size < SGX_CMD_BURST_MAX_SIZE &&
106 info->burst_cnt == info->burst_size)
107 return SGX_POWER_DOWN_DELAY_SHORT_MS;
109 return SGX_POWER_DOWN_DELAY_LONG_MS;
113 void sgx_mark_new_command(struct PVRSRV_DEVICE_NODE *node)
115 struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
116 struct SGX_TIMING_INFORMATION tinfo = { 0 };
117 unsigned long long cmd_start;
118 bool new_burst = false;
120 cmd_start = cpu_clock(smp_processor_id());
122 if (unlikely(info->last_idle == info->burst_start)) {
124 * This is the initial case, when we haven't yet any commands
130 * If the last idle occurred after the current burst started
131 * and the time since the idle is greater than the threshold
132 * allowed for delays within a burst then this is a new burst.
134 if (time_after64(info->last_idle, info->burst_start) &&
135 cmd_start - info->last_idle > SGX_CMD_BURST_THRESHOLD_NS)
140 info->burst_start = cmd_start;
142 * We predict the length of this new burst to be that of the
145 info->burst_size = info->burst_cnt;
147 } else if (info->burst_cnt < SGX_CMD_BURST_MAX_SIZE) {
151 SysGetSGXTimingInformation(&tinfo);
152 sgx_set_pwrdown_delay(node, tinfo.ui32uKernelFreq,
153 sgx_calc_power_down_delay(node));
156 void sgx_mark_power_down(struct PVRSRV_DEVICE_NODE *node)
158 struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
160 info->last_idle = cpu_clock(smp_processor_id());
162 * After the last command completes power down happens in a delayed
163 * manner. The current value of this delay is in power_down_delay.
164 * To get the command complete time - which is the actual idle start
165 * time - we have to deduct the amount of delay from the current time.
167 info->last_idle -= MS_TO_NS(info->power_down_delay);
170 static void SGXGetTimingInfo(struct PVRSRV_DEVICE_NODE *psDeviceNode)
172 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
173 struct SGX_TIMING_INFORMATION sSGXTimingInfo = { 0 };
174 struct timer_work_data *data = psDevInfo->hTimer;
176 SysGetSGXTimingInformation(&sSGXTimingInfo);
181 * The magic calculation below sets the hardware lock-up
182 * detection and recovery timer interval to ~150msecs.
183 * The interval length will be scaled based on the SGX
184 * functional clock frequency. The higher the frequency
185 * the shorter the interval and vice versa.
187 data->interval = 150 * SYS_SGX_PDS_TIMER_FREQ /
188 sSGXTimingInfo.ui32uKernelFreq;
191 writel(sSGXTimingInfo.ui32uKernelFreq /
192 sSGXTimingInfo.ui32HWRecoveryFreq,
193 &psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate);
195 psDevInfo->ui32CoreClockSpeed = sSGXTimingInfo.ui32CoreClockSpeed;
196 psDevInfo->ui32uKernelTimerClock =
197 sSGXTimingInfo.ui32CoreClockSpeed /
198 sSGXTimingInfo.ui32uKernelFreq;
200 sgx_set_pwrdown_delay(psDeviceNode, sSGXTimingInfo.ui32uKernelFreq,
201 sgx_calc_power_down_delay(psDeviceNode));
204 void SGXStartTimer(struct PVRSRV_SGXDEV_INFO *psDevInfo, IMG_BOOL bStartOSTimer)
209 EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
210 OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
211 PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
212 PDUMP_FLAGS_CONTINUOUS);
215 enum PVRSRV_ERROR eError;
217 eError = SGXOSTimerEnable(psDevInfo->hTimer);
218 if (eError != PVRSRV_OK)
219 PVR_DPF(PVR_DBG_ERROR,
220 "SGXStartTimer : Failed to enable host timer");
224 static void SGXPollForClockGating(struct PVRSRV_SGXDEV_INFO *psDevInfo,
226 u32 ui32RegisterValue, char *pszComment)
228 PVR_UNREFERENCED_PARAMETER(psDevInfo);
229 PVR_UNREFERENCED_PARAMETER(ui32Register);
230 PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
231 PVR_UNREFERENCED_PARAMETER(pszComment);
233 #if !defined(NO_HARDWARE)
234 if (psDevInfo != NULL)
236 ((u32 __iomem *)psDevInfo->pvRegsBaseKM +
237 (ui32Register >> 2), 0,
238 ui32RegisterValue, MAX_HW_TIME_US / WAIT_TRY_COUNT,
239 WAIT_TRY_COUNT) != PVRSRV_OK)
240 PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: %s failed.",
245 PDUMPCOMMENT(pszComment);
246 PDUMPREGPOL(ui32Register, 0, ui32RegisterValue);
249 static enum PVRSRV_ERROR SGXPrePowerState(void *hDevHandle,
250 enum PVR_DEVICE_POWER_STATE eNewPowerState,
251 enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
253 if ((eNewPowerState != eCurrentPowerState) &&
254 (eNewPowerState != PVR_DEVICE_POWER_STATE_ON)) {
255 enum PVRSRV_ERROR eError;
256 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
257 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
258 u32 ui32PowerCmd, ui32CompleteStatus;
259 struct SGXMKIF_COMMAND sCommand = { 0 };
261 eError = SGXOSTimerCancel(psDevInfo->hTimer);
262 if (eError != PVRSRV_OK) {
263 PVR_DPF(PVR_DBG_ERROR,
264 "SGXPrePowerState: Failed to disable timer");
268 if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
270 ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
272 PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
273 PDUMPCOMMENT("SGX power off request");
276 ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
278 PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
279 PDUMPCOMMENT("SGX idle request");
282 sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_POWERCMD;
283 sCommand.ui32Data[1] = ui32PowerCmd;
286 SGXScheduleCCBCommand(psDevInfo, SGXMKIF_COMMAND_EDM_KICK,
287 &sCommand, KERNEL_ID, 0);
288 if (eError != PVRSRV_OK) {
289 PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
290 "Failed to submit power down command");
294 #if !defined(NO_HARDWARE)
295 if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
298 MAX_HW_TIME_US / WAIT_TRY_COUNT,
299 WAIT_TRY_COUNT) != PVRSRV_OK) {
300 PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
301 "Wait for SGX ukernel power transition failed.");
308 ("TA/3D CCB Control - Wait for power event on uKernel.");
309 PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
310 offsetof(struct SGXMKIF_HOST_CTL, ui32PowerStatus),
311 ui32CompleteStatus, ui32CompleteStatus,
312 PDUMP_POLL_OPERATOR_EQUAL,
313 MAKEUNIQUETAG(psDevInfo->
314 psKernelSGXHostCtlMemInfo));
317 SGXPollForClockGating(psDevInfo,
318 psDevInfo->ui32ClkGateStatusReg,
319 psDevInfo->ui32ClkGateStatusMask,
320 "Wait for SGX clock gating");
322 if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
323 eError = SGXDeinitialise(psDevInfo);
324 if (eError != PVRSRV_OK) {
325 PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
326 "SGXDeinitialise failed: %lu",
336 static enum PVRSRV_ERROR SGXPostPowerState(void *hDevHandle,
337 enum PVR_DEVICE_POWER_STATE eNewPowerState,
338 enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
340 if ((eNewPowerState != eCurrentPowerState) &&
341 (eCurrentPowerState != PVR_DEVICE_POWER_STATE_ON)) {
342 enum PVRSRV_ERROR eError;
343 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
344 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
345 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
346 psDevInfo->psSGXHostCtl;
348 writel(0, &psSGXHostCtl->ui32PowerStatus);
349 PDUMPCOMMENT("TA/3D CCB Control - Reset power status");
351 PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
352 offsetof(struct SGXMKIF_HOST_CTL, ui32PowerStatus),
353 sizeof(u32), PDUMP_FLAGS_CONTINUOUS,
354 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
357 if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) {
359 SGXGetTimingInfo(psDeviceNode);
361 eError = SGXInitialise(psDevInfo, IMG_FALSE);
362 if (eError != PVRSRV_OK) {
363 PVR_DPF(PVR_DBG_ERROR,
364 "SGXPostPowerState: SGXInitialise failed");
369 struct SGXMKIF_COMMAND sCommand = { 0 };
371 SGXStartTimer(psDevInfo, IMG_TRUE);
373 sCommand.ui32Data[0] =
374 PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
376 SGXScheduleCCBCommand(psDevInfo,
377 SGXMKIF_COMMAND_EDM_KICK,
378 &sCommand, ISR_ID, 0);
379 if (eError != PVRSRV_OK) {
380 PVR_DPF(PVR_DBG_ERROR,
381 "SGXPostPowerState failed to schedule CCB command: %lu",
383 return PVRSRV_ERROR_GENERIC;
391 enum PVRSRV_ERROR SGXPrePowerStateExt(void *hDevHandle,
392 enum PVR_POWER_STATE eNewPowerState,
393 enum PVR_POWER_STATE eCurrentPowerState)
395 enum PVR_DEVICE_POWER_STATE eNewDevicePowerState =
396 MapDevicePowerState(eNewPowerState);
397 enum PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
398 MapDevicePowerState(eCurrentPowerState);
400 return SGXPrePowerState(hDevHandle, eNewDevicePowerState,
401 eCurrentDevicePowerState);
404 enum PVRSRV_ERROR SGXPostPowerStateExt(void *hDevHandle,
405 enum PVR_POWER_STATE eNewPowerState,
406 enum PVR_POWER_STATE eCurrentPowerState)
408 enum PVRSRV_ERROR eError;
409 enum PVR_DEVICE_POWER_STATE eNewDevicePowerState =
410 MapDevicePowerState(eNewPowerState);
411 enum PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
412 MapDevicePowerState(eCurrentPowerState);
415 SGXPostPowerState(hDevHandle, eNewDevicePowerState,
416 eCurrentDevicePowerState);
417 if (eError != PVRSRV_OK)
420 PVR_DPF(PVR_DBG_MESSAGE,
421 "SGXPostPowerState : SGX Power Transition from %d to %d OK",
422 eCurrentPowerState, eNewPowerState);
427 enum PVRSRV_ERROR SGXPreClockSpeedChange(void *hDevHandle, IMG_BOOL bIdleDevice,
428 enum PVR_POWER_STATE eCurrentPowerState)
430 enum PVRSRV_ERROR eError;
431 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
432 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
434 PVR_UNREFERENCED_PARAMETER(psDevInfo);
436 if (eCurrentPowerState == PVRSRV_POWER_STATE_D0)
440 SGXPrePowerState(hDevHandle,
441 PVR_DEVICE_POWER_STATE_IDLE,
442 PVR_DEVICE_POWER_STATE_ON);
443 if (eError != PVRSRV_OK) {
449 PVR_DPF(PVR_DBG_MESSAGE,
450 "SGXPreClockSpeedChange: SGX clock speed was %luHz",
451 psDevInfo->ui32CoreClockSpeed);
456 enum PVRSRV_ERROR SGXPostClockSpeedChange(void *hDevHandle,
457 IMG_BOOL bIdleDevice,
458 enum PVR_POWER_STATE eCurrentPowerState)
460 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
461 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
462 u32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
464 PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
466 if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
467 SGXGetTimingInfo(psDeviceNode);
469 enum PVRSRV_ERROR eError;
471 SGXPostPowerState(hDevHandle,
472 PVR_DEVICE_POWER_STATE_ON,
473 PVR_DEVICE_POWER_STATE_IDLE);
475 if (eError != PVRSRV_OK)
478 SGXStartTimer(psDevInfo, IMG_TRUE);
483 PVR_DPF(PVR_DBG_MESSAGE, "SGXPostClockSpeedChange: "
484 "SGX clock speed changed from %luHz to %luHz",
485 ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed);