Fix error from calling MultiProc_getId with non-SMP IPU core name on OMAP5 QNX
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / family / omap5430 / ipu / ipu_pm.c
1 /*
2  *  Copyright (c) 2011-2014, Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *  *  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  *  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
32 /* Standard headers */
33 #include <ti/syslink/Std.h>
35 /*QNX specific header include */
36 #include <errno.h>
37 #include <unistd.h>
38 #include <sys/iofunc.h>
39 #include <sys/dispatch.h>
40 #include <sys/netmgr.h>
41 #include <sys/rsrcdbmgr.h>
42 #include <sys/rsrcdbmsg.h>
43 #undef QNX_PM_ENABLE
44 #ifdef QNX_PM_ENABLE
45 #include <sys/powman.h>
46 #include <cpu_dll_msg.h>
47 #endif
49 /* Module headers */
50 #include <ipu_pm.h>
51 #include <_ipu_pm.h>
52 #include <sys/mman.h>
53 #include <hw/inout.h>
54 #include <time.h>
55 #include <sys/siginfo.h>
56 #include <stdbool.h>
57 #include <ti/ipc/MultiProc.h>
58 #include <ti/syslink/ProcMgr.h>
59 #include <OMAP5430BenelliProc.h>
60 #include <ArchIpcInt.h>
61 #include <_Omap5430IpcInt.h>
63 #include <OMAP5430BenelliHalReset.h>
65 //#include <camera/camdrv.h>
66 #include <Bitops.h>
67 #include <_rpmsg.h>
69 #ifndef SYSLINK_SYSBIOS_SMP
70 #define CORE0    "CORE0"
71 #else
72 #define CORE0    "IPU"
73 #endif
75 /* Defines the ipu_pm state object, which contains all the module
76  * specific information. */
77 struct ipu_pm_module_object {
78     atomic_t ref_count;
79     /* Reference count */
80     ipu_pm_config cfg;
81     /* Module configuration */
82     pthread_mutex_t mtx;
83     /* Handle of gate to be used for local thread safety */
84     int ivahd_use_cnt;
85     /* Count of ivahd users */
86     int ivaseq0_use_cnt;
87     /* Count of ivaseq0 users */
88     int ivaseq1_use_cnt;
89     /* Count of ivaseq1 users */
90     ProcMgr_Handle proc_handles[MultiProc_MAXPROCESSORS];
91     /* Array of processor handles */
92     uint32_t loaded_procs;
93     /* Info on which procs are loaded */
94     uint32_t proc_state;
95     /* Current state of the remote procs */
96     timer_t hibernation_timer;
97     /* Timer used for hibernation */
98     int hib_timer_state;
99     /* State of the hibernation timer */
100     OsalIsr_Handle gpt9IsrObject;
101     /* ISR handle for gpt9 WDT */
102     OsalIsr_Handle gpt11IsrObject;
103     /* ISR handle for gpt11 WDT */
104     OsalIsr_Handle gpt6IsrObject;
105     /* ISR handle for gpt6 WDT */
106     bool attached[MultiProc_MAXPROCESSORS];
107     /* Indicates whether the ipu_pm module is attached. */
108     bool is_setup;
109     /* Indicates whether the ipu_pm module is setup. */
110 };
112 static struct ipu_pm_module_object ipu_pm_state = {
113     .ivahd_use_cnt = 0,
114     .loaded_procs = 0,
115     .proc_state = 0,
116 } ;
118 extern Bool syslink_hib_enable;
119 extern uint32_t syslink_hib_timeout;
120 extern Bool syslink_hib_hibernating;
121 extern pthread_mutex_t syslink_hib_mutex;
122 extern pthread_cond_t syslink_hib_cond;
124 #undef BENELLI_SELF_HIBERNATION
125 #define BENELLI_WATCHDOG_TIMER
127 /* A9 state flag 0000 | 0000 Benelli internal use*/
128 #define CORE0_PROC_DOWN        0x00010000
129 #define CORE1_PROC_DOWN        0x00020000
131 #define CORE0_LOADED 0x1
132 #define CORE1_LOADED 0x2
133 #define DSP_LOADED   0x4
135 #ifdef BENELLI_SELF_HIBERNATION
136 /* A9-M3 mbox status */
137 #define A9_M3_MBOX 0x4A0F4000
138 #define MBOX_MESSAGE_STATUS 0x000000CC
140 /* Flag provided by BIOS */
141 #define IDLE_FLAG_BENELLI_ADDR_MAP_BASE 0x9F0F0000
142 #define IDLE_FLAG_PHY_ADDR_OFFSET   0x2D8
144 /* BIOS flags states for each core in IPU */
145 static void *core0Idle = NULL;
146 static void *core1Idle = NULL;
147 static void *a9_m3_mbox = NULL;
148 static void *m3_clkstctrl = NULL;
150 #define NUM_IDLE_CORES ((in32((uintptr_t)core1Idle) << 1) + \
151                         (in32((uintptr_t)core0Idle)))
152 #define PENDING_MBOX_MSG in32((uintptr_t)a9_m3_mbox + MBOX_MESSAGE_STATUS)
154 extern Bool rpmsg_resmgr_allow_hib (UInt16 proc_id);
155 #endif
157 #ifdef QNX_PM_ENABLE
158 static struct powauth *syslink_auth_active = NULL;
159 static struct powauth *syslink_auth_oswr = NULL;
161 enum {core_active, core_inactive, core_off};
162 static int ipu_pm_powman_init(void);
163 static void tell_powman_auth_oswr(int need);
164 static BOOL oswr_prevent = FALSE;
166 #endif
168 typedef struct GPTIMER_REGS {
169     uint32_t tidr;
170     uint32_t space[3];
171     uint32_t tiocp_cfg;
172     uint32_t space1[3];
173     uint32_t reserved;
174     uint32_t irqstatus_raw;
175     uint32_t irqstatus;
176     uint32_t irqenable_set;
177     uint32_t irqenable_clr;
178     uint32_t irqwakeen;
179     uint32_t tclr;
180     uint32_t tcrr;
181     uint32_t tldr;
182     uint32_t ttgr;
183     uint32_t twps;
184     uint32_t tmar;
185     uint32_t tcar1;
186     uint32_t tsicr;
187     uint32_t tcar2;
188 } GPTIMER_REGS;
190 #define OMAP54XX_IRQ_GPT6 74
191 #define OMAP54XX_IRQ_GPT9 77
192 #define OMAP54XX_IRQ_GPT11 79
194 #define GPTIMER3_BASE        0x48034000
195 #define GPTIMER4_BASE        0x48036000
196 #define GPTIMER9_BASE        0x4803E000
197 #define GPTIMER11_BASE       0x48088000
198 #define GPTIMER5_BASE        0x40138000
199 #define GPTIMER6_BASE        0x4013A000
201 static void *GPT3Base = 0;
202 static void *GPT3ClkCtrl =0;
203 static bool GPT3Saved = FALSE;
204 static bool GPT3InUse = FALSE;
205 static void *GPT4Base = 0;
206 static void *GPT4ClkCtrl =0;
207 static bool GPT4Saved = FALSE;
208 static bool GPT4InUse = FALSE;
209 static void *GPT5Base = 0;
210 static void *GPT5ClkCtrl =0;
211 static bool GPT5Saved = FALSE;
212 static bool GPT5InUse = FALSE;
213 static void *GPT6Base = 0;
214 static void *GPT6ClkCtrl =0;
215 static bool GPT6Saved = FALSE;
216 static bool GPT6InUse = FALSE;
217 static void *GPT9Base = 0;
218 static void *GPT9ClkCtrl =0;
219 static bool GPT9Saved = FALSE;
220 static bool GPT9InUse = FALSE;
221 static void *GPT11Base = 0;
222 static void *GPT11ClkCtrl =0;
223 static bool GPT11Saved = FALSE;
224 static bool GPT11InUse = FALSE;
226 static GPTIMER_REGS GPT3Reg_saved;
227 static GPTIMER_REGS GPT4Reg_saved;
228 static GPTIMER_REGS GPT5Reg_saved;
229 static GPTIMER_REGS GPT6Reg_saved;
230 static GPTIMER_REGS GPT9Reg_saved;
231 static GPTIMER_REGS GPT11Reg_saved;
233 static void *prm_base_va = NULL;
234 static void *cm2_base_va = NULL;
235 static void *cm_core_aon_base_va = NULL;
237 #define MAX_DUCATI_CHANNELS   4
238 #define DUCATI_CHANNEL_START 25
239 #define DUCATI_CHANNEL_END   28
240 static bool DMAAllocation = false;
241 #ifdef QNX_PM_ENABLE
242 static rsrc_request_t sdma_req;
243 #endif
245 // Note, the number of camera modes is tied to enum campower_mode_t, which can
246 // be found in camera/camdrv.h
247 #define NUM_CAM_MODES 3
248 static unsigned last_camera_req[NUM_CAM_MODES];
249 static unsigned last_led_req = 0;
251 enum processor_version {
252     OMAP_5430_es10 = 0,
253     OMAP_5430_es20,
254     ERROR_CONTROL_ID = -1,
255     INVALID_SI_VERSION = -2
256 };
258 #define PRM_SIZE                    0x2000
259 #define PRM_BASE                    0x4AE06000
260 #define PRM_CM_SYS_CLKSEL_OFFSET    0x110
261 //IVA_PRM registers for OMAP5 ES1.0
262 #define PM_IVA_PWRSTCTRL_OFFSET     0xF00
263 #define PM_IVA_PWRSTST_OFFSET       0xF04
264 #define RM_IVA_RSTCTRL_OFFSET       0xF10
265 #define RM_IVA_IVA_CONTEXT_OFFSET   0xF24
266 //IVA_PRM registers for OMAP5 ES2.0
267 #define PM_IVA_PWRSTCTRL_ES20_OFFSET     0x1200
268 #define PM_IVA_PWRSTST_ES20_OFFSET       0x1204
269 #define RM_IVA_RSTCTRL_ES20_OFFSET       0x1210
270 #define RM_IVA_IVA_CONTEXT_ES20_OFFSET   0x1224
272 #define CM2_SIZE                        0x2000
273 #define CM2_BASE                        0x4A008000
274 #define CM_L3_2_L3_2_CLKCTRL_OFFSET     0x820
275 #define CM_MPU_M3_CLKCTRL_OFFSET        0x900
277 //IVA_CM_CORE registers for OMAP5 ES1.0
278 #define CM_IVA_CLKSTCTRL_OFFSET       0xF00
279 #define CM_IVA_IVA_CLKCTRL_OFFSET   0xF20
280 #define CM_IVA_SL2_CLKCTRL_OFFSET     0xF28
281 //IVA_CM_CORE registers for OMAP5 ES2.0
282 #define CM_IVA_CLKSTCTRL_ES20_OFFSET       0x1200
283 #define CM_IVA_IVA_CLKCTRL_ES20_OFFSET     0x1220
284 #define CM_IVA_SL2_CLKCTRL_ES20_OFFSET     0x1228
286 // CM_L4PER GPTIMER offsets for OMAP5 ES1.0
287 #define CM_L4PER_GPTIMER3_CLKCTRL_ES1_0_OFFSET  0x1440
288 #define CM_L4PER_GPTIMER4_CLKCTRL_ES1_0_OFFSET  0x1448
289 #define CM_L4PER_GPTIMER9_CLKCTRL_ES1_0_OFFSET  0x1450
290 #define CM_L4PER_GPTIMER11_CLKCTRL_ES1_0_OFFSET 0x1430
292 // CM_L4PER GPTIMER offsets for OMAP5 ES2.0
293 #define CM_L4PER_TIMER3_CLKCTRL_ES2_0_OFFSET  0x1040
294 #define CM_L4PER_TIMER4_CLKCTRL_ES2_0_OFFSET  0x1048
295 #define CM_L4PER_TIMER9_CLKCTRL_ES2_0_OFFSET  0x1050
296 #define CM_L4PER_TIMER11_CLKCTRL_ES2_0_OFFSET 0x1030
298 #define CM_CORE_AON_SIZE                  0x1000
299 #define CM_CORE_AON_BASE                  0x4A004000
300 #define CM_ABE_CLKSTCTRL_OFFSET           0x500
301 #define CM_ABE_TIMER5_CLKCTRL_OFFSET      0x568
302 #define CM_ABE_TIMER6_CLKCTRL_OFFSET      0x570
304 #define IVAHD_FREQ_MAX_IN_HZ 532000000
306 #define ID_CODE_BASE   0x4A002000
307 #define ID_CODE_OFFSET 0x204
309 #define OMAP5430_ES10    0x0B942
310 #define OMAP5432_ES10    0x0B998
311 #define OMAP5430_ES20    0x1B942
312 #define OMAP5432_ES20    0x1B998
314 #ifdef QNX_PM_ENABLE
315 static dvfsMsg_t dvfsMessage;
316 static int cpudll_coid = -1;
317 static reply_getListOfDomainOPPs_t cpudll_iva_opp = { {0} };  /* for result of getDomainOPP (IVA)*/
318 static reply_getListOfDomainOPPs_t cpudll_core_opp = { {0} };  /* for result of getDomainOPP (CORE)*/
319 #endif
321 enum {
322     RPRM_GPTIMER    = 0,
323     RPRM_IVAHD  = 1,
324     RPRM_IVASEQ0    = 2,
325     RPRM_IVASEQ1    = 3,
326     RPRM_L3BUS  = 4,
327     RPRM_ISS    = 5,
328     RPRM_FDIF   = 6,
329     RPRM_SL2IF  = 7,
330     RPRM_AUXCLK = 8,
331     RPRM_REGULATOR  = 9,
332     RPRM_GPIO   = 10,
333     RPRM_SDMA   = 11,
334     RPRM_IPU    = 12,
335     RPRM_DSP    = 13,
336     RPRM_I2C    = 14,
337     RPRM_CAMERA = 15,
338     RPRM_LED    = 16,
339     RPRM_MAX
340 };
342 enum processor_version get_omap_version (void)
344     uintptr_t id_code_base = NULL;
345     enum processor_version omap_rev;
346     uint32_t reg;
348     id_code_base = mmap_device_io(0x1000, ID_CODE_BASE);
349     if (id_code_base == MAP_DEVICE_FAILED){
350         GT_setFailureReason (curTrace, GT_4CLASS, "get_omap_version",
351                              ERROR_CONTROL_ID,
352                              "Unable to map ID_CODE register");
353         return ERROR_CONTROL_ID;
354     }
356     reg = in32(id_code_base + ID_CODE_OFFSET);
357     reg &= 0xFFFFF000;
358     reg = reg >> 12;
360     switch (reg) {
361         case OMAP5430_ES10:
362         case OMAP5432_ES10:
363             omap_rev = OMAP_5430_es10;
364             break;
366         case OMAP5430_ES20:
367         case OMAP5432_ES20:
368             omap_rev = OMAP_5430_es20;
369             break;
371         default:
372             omap_rev = INVALID_SI_VERSION;
373             break;
374     }
376     if (id_code_base)
377         munmap_device_io(id_code_base, 0x1000);
379     return omap_rev;
382 /* Function to Map the required registers for
383 * GPT configuration
384 */
385 int map_gpt_regs(void)
387     int retval = 0;
388     enum processor_version omap_rev;
389     uint32_t cm_l4per_gpt3_offset;
390     uint32_t cm_l4per_gpt4_offset;
391     uint32_t cm_l4per_gpt9_offset;
392     uint32_t cm_l4per_gpt11_offset;
394     omap_rev = get_omap_version();
395     if (omap_rev < 0) {
396         GT_setFailureReason (curTrace, GT_4CLASS, "map_gpt_regs",
397                              omap_rev, "Error while reading the OMAP REVISION");
398         return -EIO;
399     }
401     if (omap_rev == OMAP_5430_es20) {
402         cm_l4per_gpt3_offset = CM_L4PER_TIMER3_CLKCTRL_ES2_0_OFFSET;
403         cm_l4per_gpt4_offset = CM_L4PER_TIMER4_CLKCTRL_ES2_0_OFFSET;
404         cm_l4per_gpt9_offset = CM_L4PER_TIMER9_CLKCTRL_ES2_0_OFFSET;
405         cm_l4per_gpt11_offset = CM_L4PER_TIMER11_CLKCTRL_ES2_0_OFFSET;
406     }
407     else {
408         cm_l4per_gpt3_offset = CM_L4PER_GPTIMER3_CLKCTRL_ES1_0_OFFSET;
409         cm_l4per_gpt4_offset = CM_L4PER_GPTIMER4_CLKCTRL_ES1_0_OFFSET;
410         cm_l4per_gpt9_offset = CM_L4PER_GPTIMER9_CLKCTRL_ES1_0_OFFSET;
411         cm_l4per_gpt11_offset = CM_L4PER_GPTIMER11_CLKCTRL_ES1_0_OFFSET;
412     }
414     GPT3ClkCtrl = cm2_base_va + cm_l4per_gpt3_offset;
416     GPT3Base = (void *)mmap_device_io(0x1000, GPTIMER3_BASE);
417     if ((uintptr_t)GPT3Base == MAP_DEVICE_FAILED) {
418         retval = -ENOMEM;
419         GPT3Base = NULL;
420         goto exit;
421     }
423     GPT4ClkCtrl = cm2_base_va + cm_l4per_gpt4_offset;
425     GPT4Base = (void *)mmap_device_io(0x1000, GPTIMER4_BASE);
426     if ((uintptr_t)GPT4Base == MAP_DEVICE_FAILED) {
427         retval = -ENOMEM;
428         GPT4Base = NULL;
429         goto exit;
430     }
432     GPT9ClkCtrl = cm2_base_va + cm_l4per_gpt9_offset;
434     GPT9Base = (void *)mmap_device_io(0x1000, GPTIMER9_BASE);
435     if ((uintptr_t)GPT9Base == MAP_DEVICE_FAILED) {
436         retval = -ENOMEM;
437         GPT9Base = NULL;
438         goto exit;
439     }
441     GPT11ClkCtrl = cm2_base_va + cm_l4per_gpt11_offset;
443     GPT11Base = (void *)mmap_device_io(0x1000, GPTIMER11_BASE);
444     if ((uintptr_t)GPT11Base == MAP_DEVICE_FAILED) {
445         retval = -ENOMEM;
446         GPT11Base = NULL;
447         goto exit;
448     }
450     GPT5ClkCtrl = cm_core_aon_base_va + CM_ABE_TIMER5_CLKCTRL_OFFSET;
452     GPT5Base = (void *)mmap_device_io(0x1000, GPTIMER5_BASE);
453     if ((uintptr_t)GPT5Base == MAP_DEVICE_FAILED) {
454         retval = -ENOMEM;
455         GPT5Base = NULL;
456         goto exit;
457     }
459     GPT6ClkCtrl = cm_core_aon_base_va + CM_ABE_TIMER6_CLKCTRL_OFFSET;
461     GPT6Base = (void *)mmap_device_io(0x1000, GPTIMER6_BASE);
462     if ((uintptr_t)GPT6Base == MAP_DEVICE_FAILED) {
463         retval = -ENOMEM;
464         GPT6Base = NULL;
465         goto exit;
466     }
468     return EOK;
470 exit:
471     GPT6ClkCtrl = NULL;
472     if (GPT5Base) {
473         munmap(GPT5Base, 0x1000);
474         GPT5Base = NULL;
475     }
476     GPT5ClkCtrl = NULL;
477     if (GPT11Base) {
478         munmap(GPT11Base, 0x1000);
479         GPT11Base = NULL;
480     }
481     GPT11ClkCtrl = NULL;
482     if (GPT9Base) {
483         munmap(GPT9Base, 0x1000);
484         GPT9Base = NULL;
485     }
486     GPT9ClkCtrl = NULL;
487     if (GPT4Base) {
488         munmap(GPT4Base, 0x1000);
489         GPT4Base = NULL;
490     }
491     GPT4ClkCtrl = NULL;
492     if (GPT3Base) {
493         munmap(GPT3Base, 0x1000);
494         GPT3Base = NULL;
495     }
496     GPT3ClkCtrl = NULL;
497     return retval;
500 void unmap_gpt_regs(void)
502     if(GPT11Base != NULL)
503         munmap(GPT11Base, 0x1000);
505     GPT11Base = NULL;
507     GPT11ClkCtrl = NULL;
509     if(GPT9Base != NULL)
510         munmap(GPT9Base, 0x1000);
512     GPT9Base = NULL;
514     GPT9ClkCtrl = NULL;
516     if(GPT4Base != NULL)
517         munmap(GPT4Base, 0x1000);
519     GPT4Base = NULL;
521     GPT4ClkCtrl = NULL;
523     if(GPT3Base != NULL)
524         munmap(GPT3Base, 0x1000);
526     GPT3Base = NULL;
528     GPT3ClkCtrl = NULL;
530     if(GPT5Base != NULL)
531         munmap(GPT5Base, 0x1000);
533     GPT5Base = NULL;
535     GPT5ClkCtrl = NULL;
537     if(GPT6Base != NULL)
538         munmap(GPT6Base, 0x1000);
540     GPT6Base = NULL;
542     GPT6ClkCtrl = NULL;
545 #ifdef BENELLI_WATCHDOG_TIMER
547 /* Interrupt clear function*/
548 static Bool ipu_pm_clr_gptimer_interrupt(Ptr fxnArgs)
550     UINT32 reg;
551     uint32_t num = (uint32_t)fxnArgs;
552     GPTIMER_REGS *GPTRegs = NULL;
554     if (num == GPTIMER_3) {
555         GPTRegs = GPT3Base;
556     }
557     else if (num == GPTIMER_4) {
558         GPTRegs = GPT4Base;
559     }
560     else if (num == GPTIMER_9) {
561         GPTRegs = GPT9Base;
562     }
563     else if (num == GPTIMER_11) {
564         GPTRegs = GPT11Base;
565     }
566     else if (num == GPTIMER_5) {
567         GPTRegs = GPT5Base;
568     }
569     else if (num == GPTIMER_6) {
570         GPTRegs = GPT6Base;
571     }
572     else {
573         return TRUE;
574     }
576     reg = in32((uintptr_t)&GPTRegs->irqstatus);
577     reg |= 0x2;
579     /*Clear Overflow event */
580     out32((uintptr_t)&GPTRegs->irqstatus, reg);
581     reg = in32((uintptr_t)&GPTRegs->irqstatus);
583     /*Always return TRUE for ISR*/
584     return TRUE;
587 /* ISR for GP Timer*/
588 static Bool ipu_pm_gptimer_interrupt(Ptr fxnArgs)
590     int num;
591     uint16_t core0_id = MultiProc_getId(CORE0);
592 #ifndef SYSLINK_SYSBIOS_SMP
593     uint16_t core1_id = MultiProc_getId("CORE1");
594 #else
595     uint16_t core1_id = core0_id;
596 #endif
597     uint16_t dsp_id = MultiProc_getId("DSP");
599     switch ((uint32_t)fxnArgs) {
600         case GPTIMER_9:
601             num = 9;
602             ProcMgr_setState(ipu_pm_state.proc_handles[core0_id],
603                              ProcMgr_State_Watchdog);
604             break;
605         case GPTIMER_11:
606             num = 11;
607             ProcMgr_setState(ipu_pm_state.proc_handles[core1_id],
608                              ProcMgr_State_Watchdog);
609             break;
610         case GPTIMER_6:
611             num = 6;
612             ProcMgr_setState(ipu_pm_state.proc_handles[dsp_id],
613                              ProcMgr_State_Watchdog);
614             break;
615         default:
616             num = 0;
617             break;
618     }
619     // what to do here?
620     GT_1trace(curTrace, GT_4CLASS,
621               "ipu_pm_gptimer_interrupt: GPTimer %d expired!", num);
623     return 0;
625 #endif
627 int ipu_pm_gpt_enable(int num)
629     GPTIMER_REGS * GPTRegs = NULL;
630     uintptr_t GPTClkCtrl = NULL;
631     int max_tries = 100;
633     if (num == GPTIMER_3) {
634         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
635         GPTRegs = GPT3Base;
636         GPT3InUse = TRUE;
637     }
638     else if (num == GPTIMER_4) {
639         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
640         GPTRegs = GPT4Base;
641         GPT4InUse = TRUE;
642     }
643     else if (num == GPTIMER_9) {
644         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
645         GPTRegs = GPT9Base;
646         GPT9InUse = TRUE;
647     }
648     else if (num == GPTIMER_11) {
649         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
650         GPTRegs = GPT11Base;
651         GPT11InUse = TRUE;
652     }
653     else if (num == GPTIMER_5) {
654         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
655         GPTRegs = GPT5Base;
656         GPT5InUse = TRUE;
657         // make sure abe clock is enabled as it is source for gpt5
658         out32((uintptr_t)(cm_core_aon_base_va + CM_ABE_CLKSTCTRL_OFFSET), 0x2);
659     }
660     else if (num == GPTIMER_6) {
661         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
662         GPTRegs = GPT6Base;
663         GPT6InUse = TRUE;
664         // make sure abe clock is enabled as it is source for gpt6
665         out32((uintptr_t)(cm_core_aon_base_va + CM_ABE_CLKSTCTRL_OFFSET), 0x2);
666     }
667     else {
668         return -EINVAL;
669     }
671     /* Enable GPT MODULEMODE and set CLKSEL to SYS_CLK*/
672     out32(GPTClkCtrl, 0x2);
673     do {
674         if (!(in32(GPTClkCtrl) & 0x30000))
675             break;
676     } while (--max_tries);
677     if (max_tries == 0) {
678         ipu_pm_gpt_disable(num);
679         return -EIO;
680     }
682     /* Set Smart-idle wake-up-capable */
683     out32((uintptr_t)&GPTRegs->tiocp_cfg, 0xC);
685     return EOK;
688 int ipu_pm_gpt_disable(int num)
690     uintptr_t GPTClkCtrl = NULL;
691     GPTIMER_REGS *GPTRegs = NULL;
692     UINT32 reg = 0;
694     if (num == GPTIMER_3) {
695         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
696         GPTRegs = GPT3Base;
697         GPT3InUse = FALSE;
698     }
699     else if (num == GPTIMER_4) {
700         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
701         GPTRegs = GPT4Base;
702         GPT4InUse = FALSE;
703     }
704     else if (num == GPTIMER_9) {
705         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
706         GPTRegs = GPT9Base;
707         GPT9InUse = FALSE;
708     }
709     else if (num == GPTIMER_11) {
710         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
711         GPTRegs = GPT11Base;
712         GPT11InUse = FALSE;
713     }
714     else if (num == GPTIMER_5) {
715         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
716         GPTRegs = GPT5Base;
717         GPT5InUse = FALSE;
718     }
719     else if (num == GPTIMER_6) {
720         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
721         GPTRegs = GPT6Base;
722         GPT6InUse = FALSE;
723     }
724     else {
725         return -EINVAL;
726     }
728     /*Check if Clock is Enabled*/
729     reg = in32(GPTClkCtrl);
730     if ((reg & 0x3) == 0x2) {
731         /* Clear any pending interrupt to allow idle */
732         reg = in32((uintptr_t)&GPTRegs->irqstatus);
733         if (reg) {
734             out32((uintptr_t)&GPTRegs->irqstatus, reg);
735         }
737         /*Disable the Timer*/
738         reg = in32(GPTClkCtrl);
739         reg &= 0xFFFFFFFC;
740         out32(GPTClkCtrl, reg);
741     }
742     else {
743         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_disable", -EINVAL,
744                             "gpt clock is not enabled!");
745         return -EINVAL;
746     }
747     return EOK;
750 int ipu_pm_gpt_start (int num)
752     GPTIMER_REGS * GPTRegs = NULL;
753     uint32_t reg = 0;
755     if (num == GPTIMER_3) {
756         GPTRegs = GPT3Base;
757     }
758     else if (num == GPTIMER_4) {
759         GPTRegs = GPT4Base;
760     }
761     else if (num == GPTIMER_9) {
762         GPTRegs = GPT9Base;
763     }
764     else if (num == GPTIMER_11) {
765         GPTRegs = GPT11Base;
766     }
767     else if (num == GPTIMER_5) {
768         GPTRegs = GPT5Base;
769     }
770     else if (num == GPTIMER_6) {
771         GPTRegs = GPT6Base;
772     }
773     else {
774         return -EINVAL;
775     }
777     /*Start the Timer*/
778     reg = in32((uintptr_t)&GPTRegs->tclr);
779     reg |=0x1;
780     out32((uintptr_t)&GPTRegs->tclr, reg);
782     return EOK;
785 int ipu_pm_gpt_stop(int num)
787     uintptr_t GPTClkCtrl = NULL;
788     GPTIMER_REGS * GPTRegs = NULL;
789     uint32_t reg = 0;
791     if (num == GPTIMER_3) {
792         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
793         GPTRegs = GPT3Base;
794     }
795     else if (num == GPTIMER_4) {
796         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
797         GPTRegs = GPT4Base;
798     }
799     else if (num == GPTIMER_9) {
800         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
801         GPTRegs = GPT9Base;
802     }
803     else if (num == GPTIMER_11) {
804         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
805         GPTRegs = GPT11Base;
806     }
807     else if (num == GPTIMER_5) {
808         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
809         GPTRegs = GPT5Base;
810     }
811     else if (num == GPTIMER_6) {
812         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
813         GPTRegs = GPT6Base;
814     }
815     else {
816         return -EINVAL;
817     }
819     /*Check if Clock is Enabled*/
820     reg = in32(GPTClkCtrl);
821     if ((reg & 0x3) == 0x2) {
823         /*Stop the Timer*/
824         reg = in32((uintptr_t)&GPTRegs->tclr);
825         reg &=0xFFFFFFFE;
826         out32((uintptr_t)&GPTRegs->tclr, reg);
827     }
828     else {
829         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_stop", -EINVAL,
830                             "gpt clock is not enabled!");
831         return -EINVAL;
832     };
834     return EOK;
837 void save_gpt_context(int num)
839     GPTIMER_REGS *GPTRegs = NULL;
840     GPTIMER_REGS *GPTSaved = NULL;
841     bool *GPTRestore = NULL;
843     if (num == GPTIMER_3) {
844         GPTRegs = GPT3Base;
845         GPTSaved = &GPT3Reg_saved;
846         GPTRestore = &GPT3Saved;
847     }
848     else if (num == GPTIMER_4) {
849         GPTRegs = GPT4Base;
850         GPTSaved = &GPT4Reg_saved;
851         GPTRestore = &GPT4Saved;
852     }
853     else if (num == GPTIMER_9) {
854         GPTRegs = GPT9Base;
855         GPTSaved = &GPT9Reg_saved;
856         GPTRestore = &GPT9Saved;
857     }
858     else if (num == GPTIMER_11) {
859         GPTRegs = GPT11Base;
860         GPTSaved = &GPT11Reg_saved;
861         GPTRestore = &GPT11Saved;
862     }
863     else if (num == GPTIMER_5) {
864         GPTRegs = GPT5Base;
865         GPTSaved = &GPT5Reg_saved;
866         GPTRestore = &GPT5Saved;
867     }
868     else if (num == GPTIMER_6) {
869         GPTRegs = GPT6Base;
870         GPTSaved = &GPT6Reg_saved;
871         GPTRestore = &GPT6Saved;
872     }
873     else {
874         return;
875     }
877     GPTSaved->tiocp_cfg = in32((uintptr_t)&GPTRegs->tiocp_cfg);
878     GPTSaved->tcrr = in32((uintptr_t)&GPTRegs->tcrr);
879     GPTSaved->irqenable_set = in32((uintptr_t)&GPTRegs->irqenable_set);
880     GPTSaved->irqstatus_raw = in32((uintptr_t)&GPTRegs->irqstatus_raw);
881     GPTSaved->irqstatus = in32((uintptr_t)&GPTRegs->irqstatus);
882     GPTSaved->irqwakeen = in32((uintptr_t)&GPTRegs->irqwakeen);
883     GPTSaved->tclr = in32((uintptr_t)&GPTRegs->tclr);
884     GPTSaved->tldr = in32((uintptr_t)&GPTRegs->tldr);
885     GPTSaved->ttgr = in32((uintptr_t)&GPTRegs->ttgr);
886     GPTSaved->tmar = in32((uintptr_t)&GPTRegs->tmar);
887     GPTSaved->tsicr = in32((uintptr_t)&GPTRegs->tsicr);
888     *GPTRestore = TRUE;
891 void restore_gpt_context(int num)
893     GPTIMER_REGS *GPTRegs = NULL;
894     GPTIMER_REGS *GPTSaved = NULL;
895     bool *GPTRestore = NULL;
897     if (num == GPTIMER_3) {
898         GPTRegs = GPT3Base;
899         GPTSaved = &GPT3Reg_saved;
900         GPTRestore = &GPT3Saved;
901     }
902     else if (num == GPTIMER_4) {
903         GPTRegs = GPT4Base;
904         GPTSaved = &GPT4Reg_saved;
905         GPTRestore = &GPT4Saved;
906     }
907     else if (num == GPTIMER_9) {
908         GPTRegs = GPT9Base;
909         GPTSaved = &GPT9Reg_saved;
910         GPTRestore = &GPT9Saved;
911     }
912     else if (num == GPTIMER_11) {
913         GPTRegs = GPT11Base;
914         GPTSaved = &GPT11Reg_saved;
915         GPTRestore = &GPT11Saved;
916     }
917     else if (num == GPTIMER_5) {
918         GPTRegs = GPT5Base;
919         GPTSaved = &GPT5Reg_saved;
920         GPTRestore = &GPT5Saved;
921     }
922     else if (num == GPTIMER_6) {
923         GPTRegs = GPT6Base;
924         GPTSaved = &GPT6Reg_saved;
925         GPTRestore = &GPT6Saved;
926     }
927     else {
928         return;
929     }
931     if (*GPTRestore) {
932         *GPTRestore = FALSE;
933         out32((uintptr_t)&GPTRegs->tiocp_cfg, GPTSaved->tiocp_cfg);
934         out32((uintptr_t)&GPTRegs->irqenable_set, GPTSaved->irqenable_set);
935         out32((uintptr_t)&GPTRegs->tcrr, GPTSaved->tcrr);
936         out32((uintptr_t)&GPTRegs->irqstatus_raw, GPTSaved->irqstatus_raw);
937         out32((uintptr_t)&GPTRegs->irqstatus, GPTSaved->irqstatus);
938         out32((uintptr_t)&GPTRegs->irqwakeen, GPTSaved->irqwakeen);
939         out32((uintptr_t)&GPTRegs->tclr, GPTSaved->tclr);
940         out32((uintptr_t)&GPTRegs->tldr, GPTSaved->tldr);
941         out32((uintptr_t)&GPTRegs->ttgr, GPTSaved->ttgr);
942         out32((uintptr_t)&GPTRegs->tmar, GPTSaved->tmar);
943         out32((uintptr_t)&GPTRegs->tsicr, GPTSaved->tsicr);
944     }
947 int ipu_pm_ivaseq0_disable()
949     uintptr_t pm_base = 0;
950     uint32_t reg = 0;
951     enum processor_version omap_rev;
952     uint32_t rm_iva_rstctrl_offset;
954     pthread_mutex_lock(&ipu_pm_state.mtx);
956     if (ipu_pm_state.ivaseq0_use_cnt-- == 1) {
957         pm_base = (uintptr_t)prm_base_va;
959         omap_rev = get_omap_version();
960         if (omap_rev < 0) {
961             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
962                                  omap_rev, "Error while reading the OMAP REVISION");
963             return -EIO;
964         }
966         if (omap_rev == OMAP_5430_es20) {
967             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
968         }
969         else {
970             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
971         }
973         reg = in32(pm_base + rm_iva_rstctrl_offset);
974         reg |= 0x1;
975         out32(pm_base + rm_iva_rstctrl_offset, reg);
976     }
977     else {
978         GT_0trace(curTrace, GT_3CLASS, "ivaseq0 still in use");
979     }
981     pthread_mutex_unlock(&ipu_pm_state.mtx);
982     return EOK;
985 int ipu_pm_ivaseq0_enable()
987     uintptr_t pm_base = 0;
988     uint32_t reg = 0;
989     enum processor_version omap_rev;
990     uint32_t rm_iva_rstctrl_offset;
992     pthread_mutex_lock(&ipu_pm_state.mtx);
993     if (++ipu_pm_state.ivaseq0_use_cnt == 1) {
994         pm_base = (uintptr_t)prm_base_va;
996         omap_rev = get_omap_version();
997         if (omap_rev < 0) {
998             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
999                                  omap_rev, "Error while reading the OMAP REVISION");
1000             return -EIO;
1001         }
1003         if (omap_rev == OMAP_5430_es20) {
1004             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1005         }
1006         else {
1007             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1008         }
1010         reg = in32(pm_base + rm_iva_rstctrl_offset);
1011         reg &= 0xFFFFFFFE;
1012         out32(pm_base + rm_iva_rstctrl_offset, reg);
1013     }
1014     else {
1015         GT_0trace(curTrace, GT_3CLASS, "ivaseq0 still in use");
1016     }
1018     pthread_mutex_unlock(&ipu_pm_state.mtx);
1019     return EOK;
1022 int ipu_pm_ivaseq1_disable()
1024     uintptr_t pm_base = 0;
1025     uint32_t reg = 0;
1026     enum processor_version omap_rev;
1027     uint32_t rm_iva_rstctrl_offset;
1029     pthread_mutex_lock(&ipu_pm_state.mtx);
1031     if (ipu_pm_state.ivaseq1_use_cnt-- == 1) {
1032         pm_base = (uintptr_t)prm_base_va;
1034         omap_rev = get_omap_version();
1035         if (omap_rev < 0) {
1036             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
1037                                  omap_rev, "Error while reading the OMAP REVISION");
1038             return -EIO;
1039         }
1041         if (omap_rev == OMAP_5430_es20) {
1042             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1043         }
1044         else {
1045             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1046         }
1048         reg = in32(pm_base + rm_iva_rstctrl_offset);
1049         reg |= 0x2;
1050         out32(pm_base + rm_iva_rstctrl_offset, reg);
1051     }
1052     else {
1053         GT_0trace(curTrace, GT_3CLASS, "ivaseq1 still in use");
1054     }
1056     pthread_mutex_unlock(&ipu_pm_state.mtx);
1057     return EOK;
1060 int ipu_pm_ivaseq1_enable()
1062     uintptr_t pm_base = 0;
1063     uint32_t reg = 0;
1064     enum processor_version omap_rev;
1065     uint32_t rm_iva_rstctrl_offset;
1067     pthread_mutex_lock(&ipu_pm_state.mtx);
1068     if (++ipu_pm_state.ivaseq1_use_cnt == 1) {
1069         pm_base = (uintptr_t)prm_base_va;
1071         omap_rev = get_omap_version();
1072         if (omap_rev < 0) {
1073             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
1074                                  omap_rev, "Error while reading the OMAP REVISION");
1075             return -EIO;
1076         }
1078         if (omap_rev == OMAP_5430_es20) {
1079             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1080         }
1081         else {
1082             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1083         }
1085         reg = in32(pm_base + rm_iva_rstctrl_offset);
1086         reg &= 0xFFFFFFFD;
1087         out32(pm_base + rm_iva_rstctrl_offset, reg);
1088     }
1089     else {
1090         GT_0trace(curTrace, GT_3CLASS, "ivaseq1 still in use");
1091     }
1093     pthread_mutex_unlock(&ipu_pm_state.mtx);
1094     return EOK;
1097 int ipu_pm_ivahd_disable()
1099     uintptr_t pm_base = 0;
1100     uintptr_t cm_base = 0;
1101     uint32_t reg = 0;
1102     int max_tries = 100;
1103     enum processor_version omap_rev;
1104     uint32_t pm_iva_pwrstctrl_offset;
1105     uint32_t cm_iva_clkstctrl_offset;
1106     uint32_t cm_iva_iva_clkctrl_offset;
1107     uint32_t cm_iva_sl2_clkctrl_offset;
1108     uint32_t rm_iva_rstctrl_offset;
1110     pthread_mutex_lock(&ipu_pm_state.mtx);
1112     if (ipu_pm_state.ivahd_use_cnt-- == 1) {
1113         omap_rev = get_omap_version();
1114         if (omap_rev < 0) {
1115             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_disable",
1116                                  omap_rev, "Error while reading the OMAP REVISION");
1117             return -EIO;
1118         }
1119         pm_base = (uintptr_t)prm_base_va;
1120         cm_base = (uintptr_t)cm2_base_va;
1122         if (omap_rev == OMAP_5430_es20) {
1123             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1124             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1125             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1126             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1127             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1128         }
1129         else {
1130             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1131             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1132             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1133             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1134             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1135         }
1137         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1138         reg &= 0xFFFFFFFC;
1139         reg |= 0x00000002;
1140         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1142         /* Ensure that the wake up mode is set to SW_WAKEUP */
1143         out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1145         /* Check the standby status */
1146         do {
1147             if (((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00040000) != 0x0))
1148                 break;
1149         } while (--max_tries);
1150         if (max_tries == 0) {
1151             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
1152         }
1154         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
1155         out32(cm_base + cm_iva_iva_clkctrl_offset, 0x00000000);
1157         max_tries = 100;
1158         do {
1159             if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) == 0x30000)
1160                 break;
1161         } while (--max_tries);
1162         if (max_tries == 0) {
1163            GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
1164         }
1166         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
1167         out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x00000000);
1169         max_tries = 100;
1170         do {
1171             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) == 0x30000);
1172                 break;
1173         } while (--max_tries);
1174         if (max_tries == 0) {
1175             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 CLKCTRL");
1176         }
1178         /* put IVA into HW Auto mode */
1179         out32(cm_base + cm_iva_clkstctrl_offset, 0x00000003);
1181         max_tries = 100;
1182         /* Check CLK ACTIVITY bit */
1184         while(((in32(cm_base + cm_iva_clkstctrl_offset) & 0x00000100) != 0x0) && --max_tries);
1185         if (max_tries == 0)
1186             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_disable: WARNING - CLK ACTIVITY bit did not go off");
1188         // IVA sub-system resets - Assert reset for IVA logic and SL2
1189         out32(pm_base + rm_iva_rstctrl_offset, 0x00000004);
1190         max_tries = 200;
1191         while(--max_tries);
1193         // IVA sub-system resets - Assert reset for IVA logic, SL2, and sequencer1
1194         out32(pm_base + rm_iva_rstctrl_offset, 0x00000005);
1195         max_tries = 200;
1196         while(--max_tries);
1198         // IVA sub-system resets - Assert reset for IVA logic, SL2, sequencer1 and sequencer2
1199         out32(pm_base + rm_iva_rstctrl_offset, 0x00000007);
1200     }
1201     else {
1202         GT_0trace(curTrace, GT_3CLASS, "ivahd still in use");
1203     }
1205     pthread_mutex_unlock(&ipu_pm_state.mtx);
1206     return EOK;
1209 int ipu_pm_ivahd_enable()
1211     uintptr_t pm_base = 0;
1212     uintptr_t cm_base = 0;
1213     uint32_t reg = 0;
1214     unsigned int pwrst = 0;
1215     int max_tries = 100;
1216     enum processor_version omap_rev;
1217     uint32_t pm_iva_pwrstctrl_offset;
1218     uint32_t cm_iva_clkstctrl_offset;
1219     uint32_t cm_iva_iva_clkctrl_offset;
1220     uint32_t cm_iva_sl2_clkctrl_offset;
1221     uint32_t rm_iva_rstctrl_offset;
1222     uint32_t rm_iva_iva_context_offset;
1223     uint32_t pm_iva_pwrstst_offset;
1225     pthread_mutex_lock(&ipu_pm_state.mtx);
1227     if (++ipu_pm_state.ivahd_use_cnt == 1) {
1228         pm_base = (uintptr_t)prm_base_va;
1229         cm_base = (uintptr_t)cm2_base_va;
1231         omap_rev = get_omap_version();
1232         if (omap_rev < 0) {
1233             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1234                                  omap_rev, "Error while reading the OMAP REVISION");
1235             return -EIO;
1236         }
1238         if (omap_rev == OMAP_5430_es20) {
1239             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1240             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1241             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1242             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1243             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1244             rm_iva_iva_context_offset = RM_IVA_IVA_CONTEXT_ES20_OFFSET;
1245             pm_iva_pwrstst_offset = PM_IVA_PWRSTST_ES20_OFFSET;
1246         }
1247         else {
1248             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1249             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1250             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1251             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1252             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1253             rm_iva_iva_context_offset = RM_IVA_IVA_CONTEXT_OFFSET;
1254             pm_iva_pwrstst_offset = PM_IVA_PWRSTST_OFFSET;
1255         }
1256         /* Read the IVAHD Context register to check if the memory content has been lost */
1257         reg = in32(pm_base + rm_iva_iva_context_offset);
1258         /* Clear the context register by writing 1 to bit 8,9 and 10 */
1259         out32(pm_base + rm_iva_iva_context_offset, 0x700);
1261         /*Display power state*/
1262         pwrst = in32(pm_base + pm_iva_pwrstst_offset);
1263         GT_1trace(curTrace, GT_4CLASS, "###: off state reg bit = 0x%x\n", (pwrst & 0x03000003));
1264         /*Clear the power status reg by writting 1'a into the requred bits*/
1265         out32(pm_base + pm_iva_pwrstst_offset, 0x03000000);
1267         /* Ensure power state is set to ON */
1268         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1269         reg &= 0xFFFFFFFC;
1270         reg |= 0x00000003;
1271         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1273         /* Ensure that the wake up mode is set to SW_WAKEUP */
1274         out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1276         max_tries = 100;
1277         while(((in32(pm_base + pm_iva_pwrstst_offset) & 0x00100000) != 0) && --max_tries);
1278         if (max_tries == 0)
1279             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_enable: WARNING - PwrSt did not transition");
1281         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
1282         out32(cm_base + cm_iva_iva_clkctrl_offset, 0x00000001);
1284         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
1285         out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x00000001);
1287         /* Wait until the CLK_ACTIVITY bit is set */
1288         max_tries = 100;
1289         while (((in32(cm_base + cm_iva_clkstctrl_offset) & 0x00000100) == 0x0) && --max_tries);
1290         if (max_tries == 0)
1291             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_enable: WARNING - Clk_ACTIVITY bit is not set");
1293         /* Release ICONT1 and SL2/IVAHD first, wait for few usec  then release ICONT2 */
1294         reg = in32(pm_base + rm_iva_rstctrl_offset);
1295         reg &= 0xFFFFFFFB;
1296         out32(pm_base + rm_iva_rstctrl_offset, reg);
1298         max_tries = 100;
1299         usleep(100);
1300         do {
1301             if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) == 0x0)
1302                 break;
1303         } while(--max_tries);
1304         if (max_tries == 0) {
1305             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD clk control");
1306             return -EIO;
1307         }
1309         max_tries = 100;
1310         do {
1311             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) == 0x00000)
1312                 break;
1313         } while(--max_tries);
1314         if (max_tries == 0) {
1315             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 clk control");
1316             return -EIO;
1317         }
1319         max_tries = 100;
1320         do {
1321             if((in32(cm_base + CM_L3_2_L3_2_CLKCTRL_OFFSET) & 0x30001) == 0x00001)
1322                 break;
1323         } while(--max_tries);
1324         if (max_tries == 0) {
1325             GT_0trace(curTrace, GT_4CLASS," ** Error in L3 clk control");
1326             return -EIO;
1327         }
1329         /* Ensure IVAHD and SL2 is functional */
1330         max_tries = 100;
1331         do {
1332         if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030001) == 0x00001)
1333             break;
1334         } while(--max_tries);
1335         if (max_tries == 0) {
1336             GT_0trace(curTrace, GT_4CLASS," ** IVAHD is not functional");
1337             return -EIO;
1338         }
1340         max_tries = 100;
1341         do {
1342             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030001) == 0x00001)
1343                 break;
1344         } while(--max_tries);
1345         if (max_tries == 0) {
1346             GT_0trace(curTrace, GT_4CLASS," ** SL2 is not functional");
1347             return -EIO;
1348         }
1349     } else {
1350         GT_0trace(curTrace, GT_3CLASS, "ivahd already acquired");
1351     }
1353     pthread_mutex_unlock(&ipu_pm_state.mtx);
1354     return EOK;
1357 int ipu_pm_ivahd_off()
1359     uintptr_t pm_base = 0;
1360     uintptr_t cm_base = 0;
1361     uint32_t reg = 0;
1362     int32_t max_tries = 0;
1363     bool ivahd_enabled = false;
1364     bool sl2_enabled = false;
1365     enum processor_version omap_rev;
1366     uint32_t pm_iva_pwrstctrl_offset;
1367     uint32_t cm_iva_clkstctrl_offset;
1368     uint32_t cm_iva_iva_clkctrl_offset;
1369     uint32_t cm_iva_sl2_clkctrl_offset;
1370     uint32_t rm_iva_rstctrl_offset;
1371     uint32_t pm_iva_pwrstst_offset;
1373     pm_base = (uintptr_t)prm_base_va;
1374     cm_base = (uintptr_t)cm2_base_va;
1376     omap_rev = get_omap_version();
1377     if (omap_rev < 0) {
1378         GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1379                              omap_rev, "Error while reading the OMAP REVISION");
1380         return -EIO;
1381     }
1383     if (omap_rev == OMAP_5430_es20) {
1384         pm_iva_pwrstst_offset = PM_IVA_PWRSTST_ES20_OFFSET;
1385         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1386         cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1387         cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1388         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1389         rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1390     }
1391     else {
1392         pm_iva_pwrstst_offset = PM_IVA_PWRSTST_OFFSET;
1393         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1394         cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1395         cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1396         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1397         rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1398     }
1400     reg = in32(pm_base + pm_iva_pwrstst_offset);
1401     reg = reg & 0x00000007;
1403     if (reg != 0x00000000) {
1404         /* set IVAHD to SW_WKUP */
1405         out32(cm_base + cm_iva_clkstctrl_offset, 0x2);
1406         max_tries = 100;
1407         /* Check for ivahd module and disable if it is enabled */
1408         if ((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x1) != 0) {
1409             out32(cm_base + cm_iva_iva_clkctrl_offset, 0x0);
1410             ivahd_enabled = 1;
1411         }
1412         /* Check for sl2 module and disable if it is enabled */
1413         if ((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x1) != 0) {
1414             out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x0);
1415             sl2_enabled = 1;
1416         }
1417         if (ivahd_enabled || sl2_enabled) {
1418             while (((in32(cm_base + cm_iva_clkstctrl_offset) & 0x00000100) == 0x0) && --max_tries);
1419             if (max_tries == 0) {
1420                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM:IVAHD DOMAIN is Not Enabled after retries");
1421             }
1422         }
1424         /* Set IVAHD PD to OFF */
1425         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1426         reg = (reg & 0xFFFFFFFC) | 0x0;
1427         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1429         max_tries = 100;
1430         while (((in32(pm_base + pm_iva_pwrstst_offset) & 0x00100000) != 0) && --max_tries);
1431         if (max_tries == 0) {
1432            GT_0trace(curTrace, GT_4CLASS,"IPU_PM: IVAHD Power Domain is in transition after retries");
1433         }
1435         if (ivahd_enabled) {
1436             max_tries = 100;
1437             while (((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) != 0x30000) && --max_tries);
1438             if (max_tries == 0) {
1439                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the IVAHD Module after retries");
1440             }
1441         }
1442         if (sl2_enabled) {
1443             max_tries = 100;
1444             while (((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) != 0x30000) && --max_tries);
1445             if (max_tries == 0) {
1446                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the SL2 Module after retries");
1447             }
1448         }
1449         /* Set IVAHD to HW_AUTO */
1450         out32(cm_base + cm_iva_clkstctrl_offset, 0x3);
1451         /* Check the reset states and assert resets */
1452         if (in32(pm_base + rm_iva_rstctrl_offset) != 0x7) {
1453             out32(pm_base + rm_iva_rstctrl_offset, 0x7);
1454         }
1455     }
1457     return EOK;
1460 int ipu_pm_ivahd_on()
1462     uintptr_t pm_base = 0;
1463     uintptr_t cm_base = 0;
1464     uint32_t reg = 0;
1465     enum processor_version omap_rev;
1466     uint32_t pm_iva_pwrstctrl_offset;
1467     uint32_t cm_iva_clkstctrl_offset;
1469     pm_base = (uintptr_t)prm_base_va;
1470     cm_base = (uintptr_t)cm2_base_va;
1472     omap_rev = get_omap_version();
1473     if (omap_rev < 0) {
1474         GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1475                              omap_rev, "Error while reading the OMAP REVISION");
1476         return -EIO;
1477     }
1479     if (omap_rev == OMAP_5430_es20) {
1480         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1481         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1482     }
1483     else {
1484         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1485         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1486     }
1488     /* Set the power state to ON */
1489     reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1490     reg &= 0xFFFFFFFC;
1491     reg |= 0x00000002;
1492     out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1494     /* Ensure that the wake up mode is set to SW_WAKEUP */
1495     out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1497     /* put IVA into HW Auto mode */
1498     reg = in32(cm_base + cm_iva_clkstctrl_offset);
1499     reg |= 0x00000003;
1500     out32(cm_base + cm_iva_clkstctrl_offset, reg);
1502     return EOK;
1505 int ipu_pm_led_enable(unsigned int mode, unsigned int intensity)
1507     int ret = 0;
1509     //ret = camflash_config(mode, intensity);
1511     if (ret != -1)
1512         last_led_req = mode;
1514     return ret;
1517 int ipu_pm_alloc_sdma(int num_chs, int* channels)
1519     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma++");
1521     if(DMAAllocation == false) {
1522         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1523         return -1;
1524     }
1525     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma--");
1526     return 0;
1529 int ipu_pm_free_sdma(int num_chs, int* channels)
1531     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma++");
1533     if(DMAAllocation == false) {
1534         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1535         return -1;
1536     }
1537     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma--");
1538     return 0;
1541 int ipu_pm_camera_enable(unsigned int mode, unsigned int on)
1543     int ret = 0;
1545     //ret = campower_config(mode, on);
1547     if (mode < NUM_CAM_MODES && ret == 0)
1548         last_camera_req[mode] = on;
1550     return ret;
1553 int ipu_pm_get_max_freq(unsigned int proc, unsigned int * freq)
1555     int status = EOK;
1557     switch (proc) {
1558         case RPRM_IVAHD:
1559             /* Would like to replace the below with a call to powerman */
1560             *freq = IVAHD_FREQ_MAX_IN_HZ;
1561             break;
1562         default:
1563             status = -ENOENT;
1564             break;
1565     }
1567     return status;
1570 #ifdef QNX_PM_ENABLE
1571 static int ipu_pm_power_init(void)
1573     /*Allocate SDMA channels*/
1574     memset(&sdma_req, 0, sizeof(sdma_req));
1575     sdma_req.length = MAX_DUCATI_CHANNELS;
1576     sdma_req.flags = RSRCDBMGR_DMA_CHANNEL | RSRCDBMGR_FLAG_RANGE;
1577     sdma_req.start = DUCATI_CHANNEL_START;
1578     sdma_req.end = DUCATI_CHANNEL_END;
1579     if (rsrcdbmgr_attach(&sdma_req, 1) == -1) {
1580         DMAAllocation = false;
1581         GT_1trace(curTrace, GT_4CLASS,
1582         "ipu_pm_power_init: DMA channel allocation FAILED: %s", strerror(errno));
1583     }
1584     else {
1585         GT_0trace(curTrace, GT_3CLASS,
1586             "ipu_pm_power_init: DMA channels ALLOCATED");
1587         DMAAllocation = true;
1588     }
1590     return EOK;
1593 static void ipu_pm_power_deinit(void)
1595     if(DMAAllocation){
1596         if (rsrcdbmgr_detach(&sdma_req, 1) == -1) {
1597             GT_1trace(curTrace, GT_4CLASS,
1598                       "ipu_pm_power_deinit: DMA channel deallocation FAILED!!%s",
1599                       strerror(errno));
1600         }
1601         DMAAllocation = false;
1602     }
1603     return;
1606 static int ipu_pm_powman_init(void)
1608     int status = EOK;
1610     syslink_auth_active = powman_auth_create("SYSLINK_NEEDS_CORE_ACTIVE");
1611     if(!syslink_auth_active) {
1612         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1613                 "syslink_auth_active create failure");
1614         return -ENOMEM;
1616     }
1618     syslink_auth_oswr = powman_auth_create("SYSLINK_NEEDS_PREVENT_OSWR");
1619     if(!syslink_auth_oswr) {
1620         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1621                 "syslink_auth_oswr create failure");
1622         return -ENOMEM;
1623     }
1625     int retry = 100;
1627     /* look for server  */
1628     cpudll_coid = name_open( CPUDLL_RECV_NAME, 0);
1629     while (cpudll_coid == -1 && retry-- > 0) {
1630         sleep(1);
1631         cpudll_coid = name_open (CPUDLL_RECV_NAME, 0);
1632     }
1634     if (cpudll_coid == -1) {
1635         GT_setFailureReason (curTrace, GT_4CLASS, "connect to cpudll", EINVAL,
1636                              "Couldn't connect to CPU DLL!");
1637         return EINVAL;
1638     }
1640     /* get IVA OPPs   */
1641     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1642     dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1643     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_iva_opp, sizeof(cpudll_iva_opp) ) == -1)  {
1644         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1645                             "Could not get list of IVA OPPs.");
1646         return -ENOMEM;
1647     }
1649     /* get CORE OPPs   */
1650     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1651     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1652     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_core_opp, sizeof(cpudll_core_opp) ) == -1)  {
1653         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1654                             "Could not get list of Core OPPs.");
1655         return -ENOMEM;
1656     }
1657     return status;
1660 static void ipu_pm_powman_deinit(void)
1662     int status = EOK;
1664     if (syslink_auth_active) {
1665         status = powman_auth_destroy(syslink_auth_active);
1666         if (status < 0) {
1667             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1668                              status,
1669                              "powman_auth_destroy syslink_auth_active failure");
1670         }
1671         syslink_auth_active = NULL;
1672     }
1673     if (syslink_auth_oswr) {
1674         status = powman_auth_destroy(syslink_auth_oswr);
1675         if (status < 0) {
1676             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1677                                status,
1678                                "powman_auth_destroy syslink_auth_oswr failure");
1679         }
1680         syslink_auth_oswr = NULL;
1681     }
1683     // close the channel
1684     dvfsMessage.dvfs.type   = (cpudll_type_e)closeClient;
1685     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 ) == -1) {
1686         GT_setFailureReason(curTrace, GT_4CLASS, "powman_deinit", ENOMEM,
1687                             "Could not close client connection to server.");
1688     }
1690     name_close(cpudll_coid);
1691     cpudll_coid = -1;
1694 //no special callback needed in our case so define the default.
1695 int powman_delayed_callback(unsigned ns, void (*func) (void *), void *data)
1697     return (powman_delayed_callback_default(ns, func, data));
1700 static void tell_powman_auth_oswr(int need)
1702     int r;
1703     r = powman_auth_state(syslink_auth_oswr, need);
1704     if(r != 0) {
1705         GT_setFailureReason(curTrace, GT_4CLASS, "tell_powman_auth_oswr", r,
1706                                         "powerman authority :cannot set state");
1707     }
1710 int ipu_pm_set_bandwidth(unsigned int bandwidth)
1712     int err;
1713     int oppIndex = CPUDLL_MAX_OPP_STATES-1;
1715     /* Camera needs OPPOV (highest OPP) which will be moving from index 1 to 2.
1716      * Find the greatest non-zero element to find the highest OPP and select it.
1717      */
1718     while ( (cpudll_core_opp.states[oppIndex] == 0) && (oppIndex > 0) ){
1719         oppIndex--;
1720     }
1722     dvfsMessage.dvfs.type   = setDomainOPP;
1723     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1725     dvfsMessage.dvfs.req_opp = cpudll_core_opp.states[ bandwidth>=COREOPP100?oppIndex:0 ];
1726     err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1727     if(err != EOK) {
1728         GT_1trace(curTrace, GT_4CLASS," ** Error setting CORE OPP: %s", strerror(errno));
1729     }
1730     return EOK;
1733 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1735     int err = EOK;
1736     cpudll_iva_opp_t req = 0;
1738     if (request->target_rsrc == RPRM_IVAHD) {
1739         if (request->rate > FREQ_266Mhz)
1740             req = CPUDLL_IVA_OPPTURBO;
1741         else if ((request->rate > FREQ_133Mhz) &&
1742                  (request->rate <= FREQ_266Mhz))
1743             req = CPUDLL_IVA_OPP100;
1744         else if ((request->rate > NO_FREQ_CONSTRAINT) &&
1745                  (request->rate <= FREQ_133Mhz))
1746             req = CPUDLL_IVA_OPP50;
1747         else if (request->rate == NO_FREQ_CONSTRAINT)
1748             req = CPUDLL_IVA_OPPNONE;
1750         dvfsMessage.dvfs.req_opp = cpudll_iva_opp.states[req];
1751         dvfsMessage.dvfs.type   = setDomainOPP;
1752         dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1754         err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1755         if(err != EOK) {
1756             GT_2trace(curTrace, GT_4CLASS," ** Error setting IVA OPP %d: %s", req, strerror(err));
1757         }
1758     }
1759     return err;
1761 #else
1762 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1764     return EOK;
1767 int ipu_pm_set_bandwidth(unsigned int bandwidth)
1769     return EOK;
1771 #endif
1773 #ifdef BENELLI_SELF_HIBERNATION
1775 static int configure_timer (int val, int reload)
1777     int status = 0;
1778     struct itimerspec timeout;
1779     timeout.it_value.tv_sec = val;
1780     timeout.it_value.tv_nsec = 0;
1781     timeout.it_interval.tv_sec = reload;
1782     timeout.it_interval.tv_nsec = 0;
1783     status = timer_settime(ipu_pm_state.hibernation_timer, 0, &timeout, NULL);
1784     if (status != 0) {
1785         status = -errno;
1786     }
1787     return status;
1790 /* Function implements hibernation and watch dog timer
1791  * The functionality is based on following states
1792  * RESET:        Timer is disabed
1793  * OFF:            Timer is OFF
1794  * ON:            Timer running
1795  * HIBERNATE:    Waking up for benelli cores to hibernate
1796  * WD_RESET:    Waiting for Benelli cores to complete hibernation
1797  */
1798 int ipu_pm_timer_state(int event)
1800     int retval = 0;
1802     if (!ipu_pm_state.attached)
1803         goto exit;
1805     switch (event) {
1806         case PM_HIB_TIMER_RESET:
1807             /* disable timer and remove irq handler */
1808             //Stop the timer
1809             configure_timer(0, 0);
1810             ipu_pm_state.hib_timer_state = PM_HIB_TIMER_RESET;
1811             break;
1813         case PM_HIB_TIMER_DELETE:
1814             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF) {
1815                 /*Stop the Timer*/
1816                 configure_timer(0, 0);
1817                 /* Delete the timer */
1818                 retval = timer_delete(ipu_pm_state.hibernation_timer);
1819                }
1820               break;
1822         case PM_HIB_TIMER_OFF:
1823             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1824                 /*Stop the Timer*/
1825                 configure_timer(0, 0);
1826                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_OFF;
1827             }
1828             break;
1830         case PM_HIB_TIMER_ON:
1831             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET||
1832                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF||
1833                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_DELETE||
1834                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1836                 /*Enable the timer*/
1837                 /*Start the Timer*/
1838                 configure_timer(syslink_hib_timeout / 1000, 0);
1839                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_ON;
1840             }
1841             break;
1842     }
1844 exit:
1845     if (retval < 0) {
1846       GT_setFailureReason (curTrace,
1847                            GT_4CLASS,
1848                            "ipu_pm_timer_state",
1849                            retval,
1850                            "ipu_pm_timer_state failed");
1851     }
1853     return retval;
1856 /*
1857   Function to save the MMU, Mailbox context before going to hibernation
1858  *
1859  */
1860 int ipu_pm_save_ctx(int proc_id)
1862     int retval = 0;
1863     int flag;
1864     int num_loaded_cores = 0;
1865     int core0_loaded;
1866     int core1_loaded;
1867     unsigned long timeout;
1868     unsigned short core0_id = MultiProc_getId(CORE0);
1869     unsigned short core1_id = MultiProc_getId("CORE1");
1870     unsigned short dsp_id = MultiProc_getId("DSP");
1871     struct itimerspec value;
1872     uint64_t pa = 0, da = 0;
1873     u32 len = 0;
1875     /* get M3's load flag */
1876     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
1877     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
1879     /* Because of the current scheme, we need to check
1880      * if CORE1 is enabled and we need to shut it down too
1881      * CORE0 is the only one sending the hibernate message
1882     */
1883     pthread_mutex_lock(&ipu_pm_state.mtx);
1885     if (core0Idle == NULL) {
1886         if (proc_id == core0_id) {
1887             retval = get_res_info(RSC_SUSPENDADDR, "0", &da, &pa, &len);
1888             if (retval == 0) {
1889                 /* BIOS flags to know the state of IPU cores */
1890                 core0Idle = (void *)mmap_device_io(0x1000, ROUND_DOWN(pa, 0x1000));
1891                 if ((uintptr_t)core0Idle == MAP_DEVICE_FAILED) {
1892                     core0Idle = NULL;
1893                     retval = -ENOMEM;
1894                     goto exit;
1895                 }
1897                 core0Idle = (void *)((uint32_t)core0Idle + ((uint32_t)pa - ROUND_DOWN((uint32_t)pa, 0x1000)));
1898                 core1Idle = (void *)core0Idle + sizeof(void *);
1899             }
1900             else {
1901                 goto exit;
1902             }
1903         }
1904     }
1906     if (proc_id == core0_id || proc_id == core1_id) {
1907         timer_gettime(ipu_pm_state.hibernation_timer, &value);
1908         if (value.it_value.tv_sec || value.it_value.tv_nsec)
1909             goto exit;
1911         if (!core0_loaded)
1912             goto exit;
1914         /* If already down don't kill it twice */
1915         if (ipu_pm_state.proc_state & CORE0_PROC_DOWN) {
1916             GT_0trace(curTrace, GT_4CLASS, "ipu already hibernated");
1917             goto exit;
1918         }
1920         !TESTBITREG32((uintptr_t)m3_clkstctrl,
1921                       CM_MPU_M3_CLKSTCTRL_CLKACTIVITY_BIT)) {
1922         retval = ArchIpcInt_sendInterrupt(core0_id,
1923                                           ipu_pm_state.cfg.int_id,
1924                                           RP_MBOX_HIBERNATION);
1926         num_loaded_cores = core1_loaded + core0_loaded;
1927         flag = 1;
1928         timeout = WAIT_FOR_IDLE_TIMEOUT;
1929         /* Wait fot Benelli to hibernate */
1930         do {
1931             /* Checking if IPU is really in idle */
1932             if (NUM_IDLE_CORES == num_loaded_cores) {
1933                 flag = 0;
1934                 break;
1935             } else {
1936                 usleep(1000);
1937             }
1938         } while ( --timeout != 0);
1940         if (flag) {
1941             GT_0trace(curTrace, GT_4CLASS, "Benelli Cores are NOT really Idle");
1942             goto error;
1943         }
1945         ipu_pm_timer_state(PM_HIB_TIMER_OFF);
1946         retval = Omap5430IpcInt_mboxSaveCtxt(core0_id);
1947         if(retval != OMAP5430IPCINT_SUCCESS){
1948             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1949                                 retval,
1950                                 "Error while saving the MailBox context");
1951             goto error;
1952         }
1954         if (core1_loaded) {
1955 #ifdef BENELLI_WATCHDOG_TIMER
1956             save_gpt_context(GPTIMER_11);
1957             ipu_pm_gpt_stop(GPTIMER_11);
1958             ipu_pm_gpt_disable(GPTIMER_11);
1959 #endif
1960             if (GPT4InUse == TRUE)
1961                 save_gpt_context(GPTIMER_4);
1963             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
1964                                  Omap5430BenelliProc_CtrlCmd_Suspend, NULL);
1965             if (retval < 0) {
1966                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1967                                     retval, "Error while suspending CORE1");
1968                 goto error;
1969             }
1970             GT_0trace(curTrace, GT_4CLASS, "Sleep CORE1");
1971         }
1973 #ifdef BENELLI_WATCHDOG_TIMER
1974         save_gpt_context(GPTIMER_9);
1975         ipu_pm_gpt_stop(GPTIMER_9);
1976         ipu_pm_gpt_disable(GPTIMER_9);
1977 #endif
1978         if (GPT3InUse == TRUE)
1979             save_gpt_context(GPTIMER_3);
1981         ipu_pm_state.proc_state |= CORE1_PROC_DOWN;
1982         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
1983                                  Omap5430BenelliProc_CtrlCmd_Suspend, NULL);
1984         if (retval < 0) {
1985             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
1986                                 "Error while suspending CORE0");
1987             goto error;
1988         }
1989         GT_0trace(curTrace, GT_4CLASS, "Sleep CORE0");
1990         ipu_pm_state.proc_state |= CORE0_PROC_DOWN;
1992         ipu_pm_ivahd_off();
1994         // Advise that Ducati is hibernating
1995         pthread_mutex_lock(&syslink_hib_mutex);
1996         syslink_hib_hibernating = TRUE;
1997         pthread_mutex_unlock(&syslink_hib_mutex);
1998     }
1999     else if (proc_id == dsp_id) {
2000         //TODO: Add support for DSP.
2001     }
2002     else
2003         goto error;
2005 #ifdef QNX_PM_ENABLE
2006     if (oswr_prevent == 1) {
2007         tell_powman_auth_oswr(0); // Passing 1 prevents OSWR and 0 allows OSWR
2008         oswr_prevent = 0;
2009     }
2010 #endif
2011        /* If there is a message in the mbox restore
2012      * immediately after save.
2013      */
2014     if (PENDING_MBOX_MSG)
2015         goto restore;
2017 exit:
2018     pthread_mutex_unlock(&ipu_pm_state.mtx);
2019     return 0;
2020 error:
2021     GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
2022                         "Aborting hibernation process");
2023     ipu_pm_timer_state(PM_HIB_TIMER_ON);
2024     pthread_mutex_unlock(&ipu_pm_state.mtx);
2025     return retval;
2026 restore:
2027     GT_0trace(curTrace, GT_4CLASS,
2028               "Starting restore_ctx since messages pending in mbox");
2029     pthread_mutex_unlock(&ipu_pm_state.mtx);
2030     ipu_pm_restore_ctx(proc_id);
2032     return retval;
2036 /* Function to check if a processor is shutdown
2037  * if shutdown then restore context else return.
2038  */
2039 int ipu_pm_restore_ctx(int proc_id)
2041     int retval = 0;
2042     int core0_loaded;
2043     int core1_loaded;
2044     unsigned short core0_id = MultiProc_getId(CORE0);
2045     unsigned short core1_id = MultiProc_getId("CORE1");
2046     unsigned short dsp_id = MultiProc_getId("DSP");
2048     /*If feature not supported by proc, return*/
2049     if (proc_id == dsp_id)
2050         return 0;
2052     /* Check if the M3 was loaded */
2053     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
2054     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
2056     /* Because of the current scheme, we need to check
2057      * if CORE1 is enable and we need to enable it too
2058      * In both cases we should check if for both cores
2059      * and enable them if they were loaded.
2060      */
2061     pthread_mutex_lock(&ipu_pm_state.mtx);
2063     /* Restart the hib timer */
2064     if (syslink_hib_enable) {
2065         ipu_pm_timer_state(PM_HIB_TIMER_ON);
2066     }
2067 #ifdef QNX_PM_ENABLE
2068     if(oswr_prevent == 0) {
2069         tell_powman_auth_oswr(1); // Passing 1 prevents OSWR and 0 allows OSWR
2070         oswr_prevent = 1;
2071     }
2072 #endif
2073     if (proc_id == core0_id || proc_id == core1_id) {
2074         if (!(ipu_pm_state.proc_state & CORE0_PROC_DOWN) || !core0_loaded) {
2075             goto exit;
2076         }
2078         if (ProcMgr_getState(ipu_pm_state.proc_handles[core0_id]) != ProcMgr_State_Suspended) {
2079             goto exit;
2080         }
2082         retval = Omap5430IpcInt_mboxRestoreCtxt(core0_id);
2083         if(retval != OMAP5430IPCINT_SUCCESS){
2084             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2085                                 retval,
2086                                 "Not able to restore Mail Box context");
2087             goto error;
2088         }
2090 #ifdef BENELLI_WATCHDOG_TIMER
2091         ipu_pm_gpt_enable(GPTIMER_9);
2092         restore_gpt_context(GPTIMER_9);
2093         ipu_pm_gpt_start(GPTIMER_9);
2094 #endif
2095         if (GPT3InUse == TRUE) {
2096             ipu_pm_gpt_enable(GPTIMER_3);
2097             restore_gpt_context(GPTIMER_3);
2098         }
2100         GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE0");
2101         ipu_pm_state.proc_state &= ~CORE0_PROC_DOWN;
2102         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
2103                                  Omap5430BenelliProc_CtrlCmd_Resume, NULL);
2104         if (retval < 0){
2105             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2106                                 retval, "Not able to resume CORE0");
2107             goto error;
2108         }
2110         if (core1_loaded) {
2111 #ifdef BENELLI_WATCHDOG_TIMER
2112             ipu_pm_gpt_enable(GPTIMER_11);
2113             restore_gpt_context(GPTIMER_11);
2114             ipu_pm_gpt_start(GPTIMER_11);
2115 #endif
2116             if (GPT4InUse == TRUE) {
2117                 ipu_pm_gpt_enable(GPTIMER_4);
2118                 restore_gpt_context(GPTIMER_4);
2119             }
2121             GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE1");
2122             ipu_pm_state.proc_state &= ~CORE1_PROC_DOWN;
2123             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
2124                                      Omap5430BenelliProc_CtrlCmd_Resume, NULL);
2125             if (retval < 0){
2126                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2127                                     retval, "Not able to resume CORE1");
2128                 goto error;
2129             }
2130         }
2131         pthread_mutex_lock(&syslink_hib_mutex);
2132         // Once we are active, signal any thread waiting for end of hibernation
2133         syslink_hib_hibernating = FALSE;
2134         pthread_cond_broadcast(&syslink_hib_cond);
2135         pthread_mutex_unlock(&syslink_hib_mutex);
2136     }
2137     else
2138         goto error;
2139 exit:
2140     /* turn on benelli hibernation timer */
2141     if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF ||
2142         ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET) {
2143             ipu_pm_timer_state(PM_HIB_TIMER_ON);
2144     }
2145     pthread_mutex_unlock(&ipu_pm_state.mtx);
2146     return retval;
2147 error:
2148     pthread_mutex_unlock(&ipu_pm_state.mtx);
2149     return -EINVAL;
2152 /* ISR for Timer*/
2153 static void ipu_pm_timer_interrupt (union sigval val)
2155     ipu_pm_save_ctx(MultiProc_getId(CORE0));
2156     return;
2158 #else // BENELLI_SELF_HIBERNATION
2160 int ipu_pm_restore_ctx(int proc_id)
2162     return 0;
2164 #endif // BENELLI_SELF_HIBERNATION
2166 int ipu_pm_attach(int proc_id)
2168     int retval = EOK;
2169 #ifdef BENELLI_WATCHDOG_TIMER
2170     OsalIsr_Params isrParams;
2171 #endif
2173     if (proc_id > MultiProc_MAXPROCESSORS) {
2174         return -EINVAL;
2175     }
2177     if (proc_id == MultiProc_getId(CORE0)) {
2178         ipu_pm_state.loaded_procs |= CORE0_LOADED;
2179 #ifdef BENELLI_WATCHDOG_TIMER
2180         ipu_pm_gpt_enable(GPTIMER_9);
2181         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2182         isrParams.fxnArgs = (Ptr)GPTIMER_9;
2183         isrParams.intId = OMAP54XX_IRQ_GPT9;
2184         isrParams.sharedInt = FALSE;
2185         ipu_pm_state.gpt9IsrObject =
2186             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2187                            isrParams.fxnArgs, &isrParams);
2188         if(ipu_pm_state.gpt9IsrObject != NULL) {
2189             if (OsalIsr_install(ipu_pm_state.gpt9IsrObject) < 0) {
2190                 retval = -ENOMEM;
2191             }
2192         }
2193         else {
2194             retval = -ENOMEM;
2195         }
2196 #endif
2197 #ifndef SYSLINK_SYSBIOS_SMP
2198     }
2199     else if (proc_id == MultiProc_getId("CORE1")) {
2200 #endif
2201         ipu_pm_state.loaded_procs |= CORE1_LOADED;
2202 #ifdef BENELLI_WATCHDOG_TIMER
2203         ipu_pm_gpt_enable(GPTIMER_11);
2204         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2205         isrParams.fxnArgs = (Ptr)GPTIMER_11;
2206         isrParams.intId = OMAP54XX_IRQ_GPT11;
2207         isrParams.sharedInt = FALSE;
2208         ipu_pm_state.gpt11IsrObject =
2209             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2210                            isrParams.fxnArgs, &isrParams);
2211         if(ipu_pm_state.gpt11IsrObject != NULL) {
2212             if (OsalIsr_install(ipu_pm_state.gpt11IsrObject) < 0) {
2213                 retval = -ENOMEM;
2214             }
2215         }
2216         else {
2217             retval = -ENOMEM;
2218         }
2219 #endif
2220     }
2221     else if (proc_id == MultiProc_getId("DSP")) {
2222         ipu_pm_state.loaded_procs |= DSP_LOADED;
2223 #ifdef BENELLI_WATCHDOG_TIMER
2224         ipu_pm_gpt_enable(GPTIMER_6);
2225         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2226         isrParams.fxnArgs = (Ptr)GPTIMER_6;
2227         isrParams.intId = OMAP54XX_IRQ_GPT6;
2228         isrParams.sharedInt = FALSE;
2229         ipu_pm_state.gpt6IsrObject =
2230             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2231                            isrParams.fxnArgs, &isrParams);
2232         if(ipu_pm_state.gpt6IsrObject != NULL) {
2233             if (OsalIsr_install(ipu_pm_state.gpt6IsrObject) < 0) {
2234                 retval = -ENOMEM;
2235             }
2236         }
2237         else {
2238             retval = -ENOMEM;
2239         }
2240 #endif
2241     }
2243     if (retval >= 0)
2244         retval = ProcMgr_open(&ipu_pm_state.proc_handles[proc_id], proc_id);
2246     if (retval < 0) {
2247 #ifdef BENELLI_WATCHDOG_TIMER
2248         if (proc_id == MultiProc_getId(CORE0)) {
2249             if (ipu_pm_state.gpt9IsrObject) {
2250                 OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
2251                 OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
2252                 ipu_pm_state.gpt9IsrObject = NULL;
2253             }
2254             ipu_pm_gpt_stop(GPTIMER_9);
2255             ipu_pm_gpt_disable(GPTIMER_9);
2256 #ifndef SYSLINK_SYSBIOS_SMP
2257         }
2258         else if (proc_id == MultiProc_getId("CORE1")) {
2259 #endif
2260             if (ipu_pm_state.gpt11IsrObject) {
2261                 OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
2262                 ipu_pm_state.gpt11IsrObject = NULL;
2263             }
2264             ipu_pm_gpt_stop(GPTIMER_11);
2265             ipu_pm_gpt_disable(GPTIMER_11);
2266         }
2267         else if (proc_id == MultiProc_getId("DSP")) {
2268             if (ipu_pm_state.gpt6IsrObject) {
2269                 OsalIsr_uninstall(ipu_pm_state.gpt6IsrObject);
2270                 OsalIsr_delete(&ipu_pm_state.gpt6IsrObject);
2271                 ipu_pm_state.gpt6IsrObject = NULL;
2272             }
2273             ipu_pm_gpt_stop(GPTIMER_6);
2274             ipu_pm_gpt_disable(GPTIMER_6);
2275         }
2276 #endif
2278     }
2279     else {
2280         ipu_pm_state.attached[proc_id] = TRUE;
2281     }
2283     return retval;
2286 int ipu_pm_detach(int proc_id)
2288     int retval = EOK;
2290     if (proc_id > MultiProc_MAXPROCESSORS) {
2291         return -EINVAL;
2292     }
2294     ipu_pm_state.attached[proc_id] = FALSE;
2296 #ifdef BENELLI_SELF_HIBERNATION
2297     if (core0Idle != NULL) {
2298         munmap_device_io(ROUND_DOWN((uint32_t)core0Idle, 0x1000),
2299                          0x1000);
2300         core0Idle = NULL;
2301         core1Idle = NULL;
2302     }
2303 #endif
2305     if (proc_id == MultiProc_getId(CORE0)) {
2306 #ifdef BENELLI_WATCHDOG_TIMER
2307         OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
2308         OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
2309         ipu_pm_state.gpt9IsrObject = NULL;
2310         ipu_pm_gpt_stop(GPTIMER_9);
2311         ipu_pm_gpt_disable(GPTIMER_9);
2312 #endif
2313         ipu_pm_state.loaded_procs &= ~CORE0_LOADED;
2314 #ifndef SYSLINK_SYSBIOS_SMP
2315     }
2316     else if (proc_id == MultiProc_getId("CORE1")) {
2317 #endif
2318 #ifdef BENELLI_WATCHDOG_TIMER
2319         OsalIsr_uninstall(ipu_pm_state.gpt11IsrObject);
2320         OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
2321         ipu_pm_state.gpt11IsrObject = NULL;
2322         ipu_pm_gpt_stop(GPTIMER_11);
2323         ipu_pm_gpt_disable(GPTIMER_11);
2324 #endif
2325         ipu_pm_state.loaded_procs &= ~CORE1_LOADED;
2326     }
2327     else if (proc_id == MultiProc_getId("DSP")) {
2328 #ifdef BENELLI_WATCHDOG_TIMER
2329         OsalIsr_uninstall(ipu_pm_state.gpt6IsrObject);
2330         OsalIsr_delete(&ipu_pm_state.gpt6IsrObject);
2331         ipu_pm_state.gpt6IsrObject = NULL;
2332         ipu_pm_gpt_stop(GPTIMER_6);
2333         ipu_pm_gpt_disable(GPTIMER_6);
2334 #endif
2335         ipu_pm_state.loaded_procs &= ~DSP_LOADED;
2336     }
2338     if (ipu_pm_state.proc_handles[proc_id]) {
2339         ProcMgr_close(&ipu_pm_state.proc_handles[proc_id]);
2340         ipu_pm_state.proc_handles[proc_id] = NULL;
2341     }
2343     return retval;
2346 int ipu_pm_setup(ipu_pm_config *cfg)
2348     int retval = EOK;
2349     int i = 0;
2350 #ifdef BENELLI_SELF_HIBERNATION
2351     struct sigevent signal_event;
2352 #endif
2354     if (ipu_pm_state.is_setup == false) {
2355         pthread_mutex_init(&ipu_pm_state.mtx, NULL);
2357         if (cfg == NULL) {
2358             retval = -EINVAL;
2359             goto exit;
2360         }
2361         if (cfg->num_procs > MultiProc_MAXPROCESSORS) {
2362             retval = -EINVAL;
2363             goto exit;
2364         }
2366         memcpy(&ipu_pm_state.cfg, cfg, sizeof(ipu_pm_config));
2368 #ifdef BENELLI_SELF_HIBERNATION
2369         /* MBOX flag to check if there are pending messages */
2370         a9_m3_mbox = (void *)mmap_device_io(0x1000, A9_M3_MBOX);
2371         if ((uintptr_t)a9_m3_mbox == MAP_DEVICE_FAILED) {
2372             a9_m3_mbox = NULL;
2373             retval = -ENOMEM;
2374             goto exit;
2375         }
2377         if (syslink_hib_enable) {
2378             SIGEV_THREAD_INIT (&signal_event, ipu_pm_timer_interrupt, NULL,
2379                                NULL);
2380             retval = timer_create(CLOCK_REALTIME, &signal_event,
2381                                   &ipu_pm_state.hibernation_timer);
2382             if (retval < 0) {
2383                 retval = -errno;
2384                 goto exit;
2385             }
2386         }
2387 #endif
2389         cm2_base_va = (void *)mmap_device_io(CM2_SIZE, CM2_BASE);
2390         if ((uintptr_t)cm2_base_va == MAP_DEVICE_FAILED) {
2391             cm2_base_va = NULL;
2392             retval = -errno;
2393             goto exit;
2394         }
2395 #ifdef BENELLI_SELF_HIBERNATION
2396         m3_clkstctrl = cm2_base_va + CM_MPU_M3_CLKCTRL_OFFSET;
2397 #endif
2399         prm_base_va = (void *)mmap_device_io(PRM_SIZE, PRM_BASE);
2400         if ((uintptr_t)prm_base_va == MAP_DEVICE_FAILED) {
2401             prm_base_va = NULL;
2402             retval = -errno;
2403             goto exit;
2404         }
2406         cm_core_aon_base_va = (void*)mmap_device_io(CM_CORE_AON_SIZE, CM_CORE_AON_BASE);
2407         if((uintptr_t)cm_core_aon_base_va == MAP_DEVICE_FAILED) {
2408             cm_core_aon_base_va = NULL;
2409             retval = -errno;
2410             goto exit;
2411         }
2413         map_gpt_regs();
2414 #ifdef QNX_PM_ENABLE
2415         ipu_pm_powman_init();
2416         ipu_pm_power_init();
2417 #endif
2418         for (i = 0; i < NUM_CAM_MODES; i++)
2419             last_camera_req[i] = 0;
2420         last_led_req = 0;
2422         ipu_pm_state.is_setup = true;
2423     }
2425 exit:
2426     if (retval != EOK) {
2427         unmap_gpt_regs();
2428         if (prm_base_va) {
2429             munmap(prm_base_va, PRM_SIZE);
2430             prm_base_va = NULL;
2431         }
2432         if (cm2_base_va) {
2433             munmap(cm2_base_va, CM2_SIZE);
2434             cm2_base_va = NULL;
2435         }
2436 #ifdef BENELLI_SELF_HIBERNATION
2437         m3_clkstctrl = NULL;
2439         if (a9_m3_mbox) {
2440             munmap(a9_m3_mbox, 0x1000);
2441             a9_m3_mbox = NULL;
2442         }
2443 #endif
2444         ipu_pm_state.loaded_procs = 0;
2445         pthread_mutex_destroy(&ipu_pm_state.mtx);
2446     }
2447     return retval;
2450 int ipu_pm_destroy()
2452     int i = 0;
2454     if (ipu_pm_state.is_setup) {
2455         for (i = 0; i < NUM_CAM_MODES; i++) {
2456             if (last_camera_req[i])
2457                 ipu_pm_camera_enable(i, 0);
2458         }
2459         if (last_led_req)
2460             ipu_pm_led_enable(0, 0);
2462 #ifdef QNX_PM_ENABLE
2463         ipu_pm_power_deinit();
2464         ipu_pm_powman_deinit();
2465 #endif
2467         unmap_gpt_regs();
2468 #ifdef BENELLI_SELF_HIBERNATION
2469         if (syslink_hib_enable) {
2470             /*Stop the Timer*/
2471             configure_timer(0, 0);
2472             /* Delete the timer */
2473             timer_delete(ipu_pm_state.hibernation_timer);
2474         }
2475         if (a9_m3_mbox) {
2476             munmap(a9_m3_mbox, 0x1000);
2477             a9_m3_mbox = NULL;
2478         }
2479         m3_clkstctrl = NULL;
2480 #endif
2481         if (cm2_base_va) {
2482             munmap(cm2_base_va, CM2_SIZE);
2483             cm2_base_va = NULL;
2484         }
2485         if (prm_base_va) {
2486             munmap(prm_base_va, PRM_SIZE);
2487             prm_base_va = NULL;
2488         }
2489         pthread_mutex_destroy(&ipu_pm_state.mtx);
2490         ipu_pm_state.proc_state = 0;
2491         ipu_pm_state.loaded_procs = 0;
2492         ipu_pm_state.ivahd_use_cnt = 0;
2493         ipu_pm_state.is_setup = false;
2494     }
2495     return EOK;