gpu: pvr: pass proc info to sgxkick and sgxtransfer
[sgx.git] / pvr / sgxpower.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
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.
8  *
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.
13  *
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.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #include <stddef.h>
28 #include <linux/io.h>
29 #include <linux/sched.h>
30
31 #include "sgxdefs.h"
32 #include "services_headers.h"
33 #include "sgxapi_km.h"
34 #include "sgxinfokm.h"
35 #include "sgxutils.h"
36 #include "pvr_pdump.h"
37
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
43
44 enum PVR_DEVICE_POWER_STATE {
45
46         PVR_DEVICE_POWER_STATE_ON = 0,
47         PVR_DEVICE_POWER_STATE_IDLE = 1,
48         PVR_DEVICE_POWER_STATE_OFF = 2,
49
50         PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff
51 };
52
53 static enum PVR_DEVICE_POWER_STATE MapDevicePowerState(enum PVR_POWER_STATE
54                                                        ePowerState)
55 {
56         enum PVR_DEVICE_POWER_STATE eDevicePowerState;
57
58         switch (ePowerState) {
59         case PVRSRV_POWER_STATE_D0:
60                 {
61                         eDevicePowerState = PVR_DEVICE_POWER_STATE_ON;
62                         break;
63                 }
64         case PVRSRV_POWER_STATE_D3:
65                 {
66                         eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF;
67                         break;
68                 }
69         default:
70                 {
71                         PVR_DPF(PVR_DBG_ERROR,
72                                  "MapDevicePowerState: Invalid state: %ld",
73                                  ePowerState);
74                         eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32;
75                         PVR_DBG_BREAK;
76                 }
77         }
78
79         return eDevicePowerState;
80 }
81
82 static void sgx_set_pwrdown_delay(struct PVRSRV_DEVICE_NODE *node,
83                                   unsigned ukernel_freq, int msec)
84 {
85         struct PVRSRV_SGXDEV_INFO *dev_info = node->pvDevice;
86         unsigned delay;
87
88         delay = ukernel_freq * msec / 1000 + 1;
89         if (dev_info->power_down_delay != delay) {
90                 writel(delay,
91                         &dev_info->psSGXHostCtl->ui32ActivePowManSampleRate);
92                 dev_info->power_down_delay = delay;
93         }
94 }
95
96 static int sgx_calc_power_down_delay(struct PVRSRV_DEVICE_NODE *node)
97 {
98         struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
99
100         /*
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
103          * maximum.
104          */
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;
108         else
109                 return SGX_POWER_DOWN_DELAY_LONG_MS;
110
111 }
112
113 void sgx_mark_new_command(struct PVRSRV_DEVICE_NODE *node)
114 {
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;
119
120         cmd_start = cpu_clock(smp_processor_id());
121
122         if (unlikely(info->last_idle == info->burst_start)) {
123                 /*
124                  * This is the initial case, when we haven't yet any commands
125                  * issued.
126                  */
127                 new_burst = true;
128         } else {
129                 /*
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.
133                  */
134                 if (time_after64(info->last_idle, info->burst_start) &&
135                     cmd_start - info->last_idle > SGX_CMD_BURST_THRESHOLD_NS)
136                         new_burst = true;
137         }
138
139         if (new_burst) {
140                 info->burst_start = cmd_start;
141                 /*
142                  * We predict the length of this new burst to be that of the
143                  * previous burst.
144                  */
145                 info->burst_size = info->burst_cnt;
146                 info->burst_cnt = 0;
147         } else if (info->burst_cnt < SGX_CMD_BURST_MAX_SIZE) {
148                 info->burst_cnt++;
149         }
150
151         SysGetSGXTimingInformation(&tinfo);
152         sgx_set_pwrdown_delay(node, tinfo.ui32uKernelFreq,
153                               sgx_calc_power_down_delay(node));
154 }
155
156 void sgx_mark_power_down(struct PVRSRV_DEVICE_NODE *node)
157 {
158         struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
159
160         info->last_idle = cpu_clock(smp_processor_id());
161         /*
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.
166          */
167         info->last_idle -= MS_TO_NS(info->power_down_delay);
168 }
169
170 static void SGXGetTimingInfo(struct PVRSRV_DEVICE_NODE *psDeviceNode)
171 {
172         struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
173         struct SGX_TIMING_INFORMATION sSGXTimingInfo = { 0 };
174         struct timer_work_data *data = psDevInfo->hTimer;
175
176         SysGetSGXTimingInformation(&sSGXTimingInfo);
177
178         if (data) {
179                 BUG_ON(data->armed);
180                 /*
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.
186                  */
187                 data->interval = 150 * SYS_SGX_PDS_TIMER_FREQ /
188                         sSGXTimingInfo.ui32uKernelFreq;
189         }
190
191         writel(sSGXTimingInfo.ui32uKernelFreq /
192                 sSGXTimingInfo.ui32HWRecoveryFreq,
193                 &psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate);
194
195         psDevInfo->ui32CoreClockSpeed = sSGXTimingInfo.ui32CoreClockSpeed;
196         psDevInfo->ui32uKernelTimerClock =
197                 sSGXTimingInfo.ui32CoreClockSpeed /
198                 sSGXTimingInfo.ui32uKernelFreq;
199
200         sgx_set_pwrdown_delay(psDeviceNode, sSGXTimingInfo.ui32uKernelFreq,
201                               sgx_calc_power_down_delay(psDeviceNode));
202 }
203
204 void SGXStartTimer(struct PVRSRV_SGXDEV_INFO *psDevInfo, IMG_BOOL bStartOSTimer)
205 {
206         u32 ui32RegVal;
207
208         ui32RegVal =
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);
213
214         if (bStartOSTimer) {
215                 enum PVRSRV_ERROR eError;
216
217                 eError = SGXOSTimerEnable(psDevInfo->hTimer);
218                 if (eError != PVRSRV_OK)
219                         PVR_DPF(PVR_DBG_ERROR,
220                                  "SGXStartTimer : Failed to enable host timer");
221         }
222 }
223
224 static void SGXPollForClockGating(struct PVRSRV_SGXDEV_INFO *psDevInfo,
225                                   u32 ui32Register,
226                                   u32 ui32RegisterValue, char *pszComment)
227 {
228         PVR_UNREFERENCED_PARAMETER(psDevInfo);
229         PVR_UNREFERENCED_PARAMETER(ui32Register);
230         PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
231         PVR_UNREFERENCED_PARAMETER(pszComment);
232
233 #if !defined(NO_HARDWARE)
234         if (psDevInfo != NULL)
235                 if (PollForValueKM
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.",
241                                  pszComment);
242
243 #endif
244
245         PDUMPCOMMENT(pszComment);
246         PDUMPREGPOL(ui32Register, 0, ui32RegisterValue);
247 }
248
249 static enum PVRSRV_ERROR SGXPrePowerState(void *hDevHandle,
250                           enum PVR_DEVICE_POWER_STATE eNewPowerState,
251                           enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
252 {
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 };
260
261                 eError = SGXOSTimerCancel(psDevInfo->hTimer);
262                 if (eError != PVRSRV_OK) {
263                         PVR_DPF(PVR_DBG_ERROR,
264                                  "SGXPrePowerState: Failed to disable timer");
265                         return eError;
266                 }
267
268                 if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
269
270                         ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
271                         ui32CompleteStatus =
272                             PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
273                         PDUMPCOMMENT("SGX power off request");
274                 } else {
275
276                         ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
277                         ui32CompleteStatus =
278                             PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
279                         PDUMPCOMMENT("SGX idle request");
280                 }
281
282                 sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_POWERCMD;
283                 sCommand.ui32Data[1] = ui32PowerCmd;
284
285                 eError =
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");
291                         return eError;
292                 }
293
294 #if !defined(NO_HARDWARE)
295                 if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
296                                    ui32CompleteStatus,
297                                    ui32CompleteStatus,
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.");
302                         PVR_DBG_BREAK;
303                 }
304 #endif
305
306 #if defined(PDUMP)
307                 PDUMPCOMMENT
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));
315 #endif
316
317                 SGXPollForClockGating(psDevInfo,
318                                       psDevInfo->ui32ClkGateStatusReg,
319                                       psDevInfo->ui32ClkGateStatusMask,
320                                       "Wait for SGX clock gating");
321
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",
327                                          eError);
328                                 return eError;
329                         }
330                 }
331         }
332
333         return PVRSRV_OK;
334 }
335
336 static enum PVRSRV_ERROR SGXPostPowerState(void *hDevHandle,
337                            enum PVR_DEVICE_POWER_STATE eNewPowerState,
338                            enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
339 {
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;
347
348                 writel(0, &psSGXHostCtl->ui32PowerStatus);
349                 PDUMPCOMMENT("TA/3D CCB Control - Reset power status");
350 #if defined(PDUMP)
351                 PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
352                          offsetof(struct SGXMKIF_HOST_CTL, ui32PowerStatus),
353                          sizeof(u32), PDUMP_FLAGS_CONTINUOUS,
354                          MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
355 #endif
356
357                 if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) {
358
359                         SGXGetTimingInfo(psDeviceNode);
360
361                         eError = SGXInitialise(psDevInfo, IMG_FALSE);
362                         if (eError != PVRSRV_OK) {
363                                 PVR_DPF(PVR_DBG_ERROR,
364                                 "SGXPostPowerState: SGXInitialise failed");
365                                 return eError;
366                         }
367                 } else {
368
369                         struct SGXMKIF_COMMAND sCommand = { 0 };
370
371                         SGXStartTimer(psDevInfo, IMG_TRUE);
372
373                         sCommand.ui32Data[0] =
374                             PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
375                         eError =
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",
382                                          eError);
383                                 return PVRSRV_ERROR_GENERIC;
384                         }
385                 }
386         }
387
388         return PVRSRV_OK;
389 }
390
391 enum PVRSRV_ERROR SGXPrePowerStateExt(void *hDevHandle,
392                                       enum PVR_POWER_STATE eNewPowerState,
393                                       enum PVR_POWER_STATE eCurrentPowerState)
394 {
395         enum PVR_DEVICE_POWER_STATE eNewDevicePowerState =
396             MapDevicePowerState(eNewPowerState);
397         enum PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
398             MapDevicePowerState(eCurrentPowerState);
399
400         return SGXPrePowerState(hDevHandle, eNewDevicePowerState,
401                                 eCurrentDevicePowerState);
402 }
403
404 enum PVRSRV_ERROR SGXPostPowerStateExt(void *hDevHandle,
405                                        enum PVR_POWER_STATE eNewPowerState,
406                                        enum PVR_POWER_STATE eCurrentPowerState)
407 {
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);
413
414         eError =
415             SGXPostPowerState(hDevHandle, eNewDevicePowerState,
416                               eCurrentDevicePowerState);
417         if (eError != PVRSRV_OK)
418                 return eError;
419
420         PVR_DPF(PVR_DBG_MESSAGE,
421                  "SGXPostPowerState : SGX Power Transition from %d to %d OK",
422                  eCurrentPowerState, eNewPowerState);
423
424         return eError;
425 }
426
427 enum PVRSRV_ERROR SGXPreClockSpeedChange(void *hDevHandle, IMG_BOOL bIdleDevice,
428                                  enum PVR_POWER_STATE eCurrentPowerState)
429 {
430         enum PVRSRV_ERROR eError;
431         struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
432         struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
433
434         PVR_UNREFERENCED_PARAMETER(psDevInfo);
435
436         if (eCurrentPowerState == PVRSRV_POWER_STATE_D0)
437                 if (bIdleDevice) {
438                         PDUMPSUSPEND();
439                         eError =
440                             SGXPrePowerState(hDevHandle,
441                                              PVR_DEVICE_POWER_STATE_IDLE,
442                                              PVR_DEVICE_POWER_STATE_ON);
443                         if (eError != PVRSRV_OK) {
444                                 PDUMPRESUME();
445                                 return eError;
446                         }
447                 }
448
449         PVR_DPF(PVR_DBG_MESSAGE,
450                  "SGXPreClockSpeedChange: SGX clock speed was %luHz",
451                  psDevInfo->ui32CoreClockSpeed);
452
453         return PVRSRV_OK;
454 }
455
456 enum PVRSRV_ERROR SGXPostClockSpeedChange(void *hDevHandle,
457                                   IMG_BOOL bIdleDevice,
458                                   enum PVR_POWER_STATE eCurrentPowerState)
459 {
460         struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
461         struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
462         u32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
463
464         PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
465
466         if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
467                 SGXGetTimingInfo(psDeviceNode);
468                 if (bIdleDevice) {
469                         enum PVRSRV_ERROR eError;
470                         eError =
471                             SGXPostPowerState(hDevHandle,
472                                               PVR_DEVICE_POWER_STATE_ON,
473                                               PVR_DEVICE_POWER_STATE_IDLE);
474                         PDUMPRESUME();
475                         if (eError != PVRSRV_OK)
476                                 return eError;
477                 } else {
478                         SGXStartTimer(psDevInfo, IMG_TRUE);
479                 }
480
481         }
482
483         PVR_DPF(PVR_DBG_MESSAGE, "SGXPostClockSpeedChange: "
484                                 "SGX clock speed changed from %luHz to %luHz",
485                  ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed);
486
487         return PVRSRV_OK;
488 }