aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c')
-rw-r--r--drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c489
1 files changed, 489 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c b/drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c
new file mode 100644
index 00000000000..93c5b7c5b3a
--- /dev/null
+++ b/drivers/gpu/pvr/omap3/sysutils_linux_wqueue_compat.c
@@ -0,0 +1,489 @@
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 <linux/version.h>
28#include <linux/clk.h>
29#include <linux/err.h>
30#include <linux/hardirq.h>
31#include <linux/mutex.h>
32#include <linux/platform_device.h>
33#include <plat/omap-pm.h>
34
35#include "sgxdefs.h"
36#include "services_headers.h"
37#include "sysinfo.h"
38#include "sgxapi_km.h"
39#include "sysconfig.h"
40#include "sgxinfokm.h"
41#include "syslocal.h"
42
43#if !defined(PVR_LINUX_USING_WORKQUEUES)
44#error "PVR_LINUX_USING_WORKQUEUES must be defined"
45#endif
46
47#define ONE_MHZ 1000000
48#define HZ_TO_MHZ(m) ((m) / ONE_MHZ)
49
50#if defined(SUPPORT_OMAP3430_SGXFCLK_96M)
51#define SGX_PARENT_CLOCK "cm_96m_fck"
52#else
53#define SGX_PARENT_CLOCK "core_ck"
54#endif
55
56extern struct platform_device *gpsPVRLDMDev;
57
58static PVRSRV_ERROR ForceMaxSGXClocks(SYS_SPECIFIC_DATA *psSysSpecData)
59{
60 PVR_UNREFERENCED_PARAMETER(psSysSpecData);
61
62 /* Pin the memory bus bw to the highest value according to CORE_REV */
63#if defined(SGX530) && (SGX_CORE_REV == 125)
64 omap_pm_set_min_bus_tput(&gpsPVRLDMDev->dev, OCP_INITIATOR_AGENT, 800000);
65#else
66 omap_pm_set_min_bus_tput(&gpsPVRLDMDev->dev, OCP_INITIATOR_AGENT, 664000);
67#endif
68 return PVRSRV_OK;
69}
70
71static IMG_VOID PowerLockWrap(SYS_SPECIFIC_DATA *psSysSpecData)
72{
73 if (!in_interrupt())
74 {
75 BUG_ON(in_atomic());
76 mutex_lock(&psSysSpecData->sPowerLock);
77
78 }
79}
80
81static IMG_VOID PowerLockUnwrap(SYS_SPECIFIC_DATA *psSysSpecData)
82{
83 if (!in_interrupt())
84 {
85 BUG_ON(in_atomic());
86 mutex_unlock(&psSysSpecData->sPowerLock);
87 }
88}
89
90PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData)
91{
92 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
93
94 PowerLockWrap(psSysSpecData);
95
96 return PVRSRV_OK;
97}
98
99IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData)
100{
101 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
102
103 PowerLockUnwrap(psSysSpecData);
104}
105
106IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
107{
108 return IMG_TRUE;
109}
110
111IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
112{
113}
114
115static inline IMG_UINT32 scale_by_rate(IMG_UINT32 val, IMG_UINT32 rate1, IMG_UINT32 rate2)
116{
117 if (rate1 >= rate2)
118 {
119 return val * (rate1 / rate2);
120 }
121
122 return val / (rate2 / rate1);
123}
124
125static inline IMG_UINT32 scale_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
126{
127 return scale_by_rate(val, rate, SYS_SGX_CLOCK_SPEED);
128}
129
130static inline IMG_UINT32 scale_inv_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
131{
132 return scale_by_rate(val, SYS_SGX_CLOCK_SPEED, rate);
133}
134
135IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psTimingInfo)
136{
137 IMG_UINT32 rate;
138
139#if defined(NO_HARDWARE)
140 rate = SYS_SGX_CLOCK_SPEED;
141#else
142 PVR_ASSERT(atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0);
143
144 rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
145 PVR_ASSERT(rate != 0);
146#endif
147 psTimingInfo->ui32CoreClockSpeed = rate;
148 psTimingInfo->ui32HWRecoveryFreq = scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate);
149 psTimingInfo->ui32uKernelFreq = scale_prop_to_SGX_clock(SYS_SGX_PDS_TIMER_FREQ, rate);
150#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
151 psTimingInfo->bEnableActivePM = IMG_TRUE;
152#else
153 psTimingInfo->bEnableActivePM = IMG_FALSE;
154#endif
155 psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
156}
157
158PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData)
159{
160#if !defined(NO_HARDWARE)
161 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
162 long lNewRate;
163 long lRate;
164 IMG_INT res;
165
166 if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0)
167 {
168 return PVRSRV_OK;
169 }
170
171 PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks"));
172
173#if defined(DEBUG)
174 {
175 IMG_UINT32 rate = clk_get_rate(psSysSpecData->psMPU_CK);
176 PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: CPU Clock is %dMhz", HZ_TO_MHZ(rate)));
177 }
178#endif
179
180 res = clk_enable(psSysSpecData->psSGX_FCK);
181 if (res < 0)
182 {
183 PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't enable SGX functional clock (%d)", res));
184 return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
185 }
186
187 res = clk_enable(psSysSpecData->psSGX_ICK);
188 if (res < 0)
189 {
190 PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't enable SGX interface clock (%d)", res));
191
192 clk_disable(psSysSpecData->psSGX_FCK);
193 return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
194 }
195
196 lNewRate = clk_round_rate(psSysSpecData->psSGX_FCK, SYS_SGX_CLOCK_SPEED + ONE_MHZ);
197 if (lNewRate <= 0)
198 {
199 PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't round SGX functional clock rate"));
200 return PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE;
201 }
202
203 lRate = clk_get_rate(psSysSpecData->psSGX_FCK);
204 if (lRate != lNewRate)
205 {
206 res = clk_set_rate(psSysSpecData->psSGX_FCK, lNewRate);
207 if (res < 0)
208 {
209 PVR_DPF((PVR_DBG_WARNING, "EnableSGXClocks: Couldn't set SGX functional clock rate (%d)", res));
210 }
211 }
212
213#if defined(DEBUG)
214 {
215 IMG_UINT32 rate = clk_get_rate(psSysSpecData->psSGX_FCK);
216 PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: SGX Functional Clock is %dMhz", HZ_TO_MHZ(rate)));
217 }
218#endif
219
220 ForceMaxSGXClocks(psSysSpecData);
221
222 atomic_set(&psSysSpecData->sSGXClocksEnabled, 1);
223
224#else /* !defined(NO_HARDWARE) */
225 PVR_UNREFERENCED_PARAMETER(psSysData);
226#endif /* !defined(NO_HARDWARE) */
227 return PVRSRV_OK;
228}
229
230
231IMG_VOID DisableSGXClocks(SYS_DATA *psSysData)
232{
233#if !defined(NO_HARDWARE)
234 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
235
236 if (atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
237 {
238 return;
239 }
240
241 PVR_DPF((PVR_DBG_MESSAGE, "DisableSGXClocks: Disabling SGX Clocks"));
242
243 if (psSysSpecData->psSGX_ICK)
244 {
245 clk_disable(psSysSpecData->psSGX_ICK);
246 }
247
248 if (psSysSpecData->psSGX_FCK)
249 {
250 clk_disable(psSysSpecData->psSGX_FCK);
251 }
252
253 omap_pm_set_min_bus_tput(&gpsPVRLDMDev->dev, OCP_INITIATOR_AGENT, 0);
254
255 atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
256
257#else
258 PVR_UNREFERENCED_PARAMETER(psSysData);
259#endif
260}
261
262PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
263{
264 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
265 struct clk *psCLK;
266 IMG_INT res;
267 PVRSRV_ERROR eError;
268
269#if defined(DEBUG) || defined(TIMING)
270 IMG_INT rate;
271 struct clk *sys_ck;
272 IMG_CPU_PHYADDR TimerRegPhysBase;
273 IMG_HANDLE hTimerEnable;
274 IMG_UINT32 *pui32TimerEnable;
275
276#endif
277
278 PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
279
280 if (!psSysSpecData->bSysClocksOneTimeInit)
281 {
282 mutex_init(&psSysSpecData->sPowerLock);
283
284 atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
285
286 psCLK = clk_get(NULL, SGX_PARENT_CLOCK);
287 if (IS_ERR(psCLK))
288 {
289 PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't get Core Clock"));
290 goto ExitError;
291 }
292 psSysSpecData->psCORE_CK = psCLK;
293
294 psCLK = clk_get(NULL, "sgx_fck");
295 if (IS_ERR(psCLK))
296 {
297 PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
298 goto ExitError;
299 }
300 psSysSpecData->psSGX_FCK = psCLK;
301
302 psCLK = clk_get(NULL, "sgx_ick");
303 if (IS_ERR(psCLK))
304 {
305 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get SGX Interface Clock"));
306 goto ExitError;
307 }
308 psSysSpecData->psSGX_ICK = psCLK;
309
310#if defined(DEBUG)
311 psCLK = clk_get(NULL, "mpu_ck");
312 if (IS_ERR(psCLK))
313 {
314 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get MPU Clock"));
315 goto ExitError;
316 }
317 psSysSpecData->psMPU_CK = psCLK;
318#endif
319 res = clk_set_parent(psSysSpecData->psSGX_FCK, psSysSpecData->psCORE_CK);
320 if (res < 0)
321 {
322 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't set SGX parent clock (%d)", res));
323 goto ExitError;
324 }
325
326 psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
327 }
328
329#if defined(DEBUG) || defined(TIMING)
330
331 psCLK = clk_get(NULL, "gpt11_fck");
332 if (IS_ERR(psCLK))
333 {
334 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
335 goto ExitUnRegisterConstraintNotifications;
336 }
337 psSysSpecData->psGPT11_FCK = psCLK;
338
339 psCLK = clk_get(NULL, "gpt11_ick");
340 if (IS_ERR(psCLK))
341 {
342 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
343 goto ExitUnRegisterConstraintNotifications;
344 }
345 psSysSpecData->psGPT11_ICK = psCLK;
346
347 sys_ck = clk_get(NULL, "sys_ck");
348 if (IS_ERR(sys_ck))
349 {
350 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get System clock"));
351 goto ExitUnRegisterConstraintNotifications;
352 }
353
354 if(clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck)
355 {
356 PVR_TRACE(("Setting GPTIMER11 parent to System Clock"));
357 res = clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck);
358 if (res < 0)
359 {
360 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't set GPTIMER11 parent clock (%d)", res));
361 goto ExitUnRegisterConstraintNotifications;
362 }
363 }
364
365 rate = clk_get_rate(psSysSpecData->psGPT11_FCK);
366 PVR_TRACE(("GPTIMER11 clock is %dMHz", HZ_TO_MHZ(rate)));
367
368 res = clk_enable(psSysSpecData->psGPT11_FCK);
369 if (res < 0)
370 {
371 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)", res));
372 goto ExitUnRegisterConstraintNotifications;
373 }
374
375 res = clk_enable(psSysSpecData->psGPT11_ICK);
376 if (res < 0)
377 {
378 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)", res));
379 goto ExitDisableGPT11FCK;
380 }
381
382
383 TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE;
384 pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
385 4,
386 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
387 &hTimerEnable);
388
389 if (pui32TimerEnable == IMG_NULL)
390 {
391 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: OSMapPhysToLin failed"));
392 goto ExitDisableGPT11ICK;
393 }
394
395 rate = *pui32TimerEnable;
396 if(!(rate & 4))
397 {
398 PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
399
400
401 *pui32TimerEnable = rate | 4;
402 }
403
404 OSUnMapPhysToLin(pui32TimerEnable,
405 4,
406 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
407 hTimerEnable);
408
409
410 TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
411 pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
412 4,
413 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
414 &hTimerEnable);
415
416 if (pui32TimerEnable == IMG_NULL)
417 {
418 PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: OSMapPhysToLin failed"));
419 goto ExitDisableGPT11ICK;
420 }
421
422
423 *pui32TimerEnable = 3;
424
425 OSUnMapPhysToLin(pui32TimerEnable,
426 4,
427 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
428 hTimerEnable);
429
430#endif
431
432 eError = PVRSRV_OK;
433 goto Exit;
434
435#if defined(DEBUG) || defined(TIMING)
436ExitDisableGPT11ICK:
437 clk_disable(psSysSpecData->psGPT11_ICK);
438ExitDisableGPT11FCK:
439 clk_disable(psSysSpecData->psGPT11_FCK);
440ExitUnRegisterConstraintNotifications:
441#endif
442ExitError:
443 eError = PVRSRV_ERROR_DISABLE_CLOCK_FAILURE;
444Exit:
445 return eError;
446}
447
448IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
449{
450#if defined(DEBUG) || defined(TIMING)
451 SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
452 IMG_CPU_PHYADDR TimerRegPhysBase;
453 IMG_HANDLE hTimerDisable;
454 IMG_UINT32 *pui32TimerDisable;
455#endif
456
457 PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
458
459
460 DisableSGXClocks(psSysData);
461
462#if defined(DEBUG) || defined(TIMING)
463
464 TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
465 pui32TimerDisable = OSMapPhysToLin(TimerRegPhysBase,
466 4,
467 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
468 &hTimerDisable);
469
470 if (pui32TimerDisable == IMG_NULL)
471 {
472 PVR_DPF((PVR_DBG_ERROR, "DisableSystemClocks: OSMapPhysToLin failed"));
473 }
474 else
475 {
476 *pui32TimerDisable = 0;
477
478 OSUnMapPhysToLin(pui32TimerDisable,
479 4,
480 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
481 hTimerDisable);
482 }
483
484 clk_disable(psSysSpecData->psGPT11_ICK);
485
486 clk_disable(psSysSpecData->psGPT11_FCK);
487
488#endif
489}