Merge remote-tracking branch 'origin/ipc-3.20-next' into ipc-next
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / family / omap5430 / ipu / ipu_pm.c
1 /*
2  *  Copyright (c) 2011-2013, 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     uint16_t core1_id = MultiProc_getId("CORE1");
593     uint16_t dsp_id = MultiProc_getId("DSP");
595     switch ((uint32_t)fxnArgs) {
596         case GPTIMER_9:
597             num = 9;
598             ProcMgr_setState(ipu_pm_state.proc_handles[core0_id],
599                              ProcMgr_State_Watchdog);
600             break;
601         case GPTIMER_11:
602             num = 11;
603             ProcMgr_setState(ipu_pm_state.proc_handles[core1_id],
604                              ProcMgr_State_Watchdog);
605             break;
606         case GPTIMER_6:
607             num = 6;
608             ProcMgr_setState(ipu_pm_state.proc_handles[dsp_id],
609                              ProcMgr_State_Watchdog);
610             break;
611         default:
612             num = 0;
613             break;
614     }
615     // what to do here?
616     GT_1trace(curTrace, GT_4CLASS,
617               "ipu_pm_gptimer_interrupt: GPTimer %d expired!", num);
619     return 0;
621 #endif
623 int ipu_pm_gpt_enable(int num)
625     GPTIMER_REGS * GPTRegs = NULL;
626     uintptr_t GPTClkCtrl = NULL;
627     int max_tries = 100;
629     if (num == GPTIMER_3) {
630         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
631         GPTRegs = GPT3Base;
632         GPT3InUse = TRUE;
633     }
634     else if (num == GPTIMER_4) {
635         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
636         GPTRegs = GPT4Base;
637         GPT4InUse = TRUE;
638     }
639     else if (num == GPTIMER_9) {
640         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
641         GPTRegs = GPT9Base;
642         GPT9InUse = TRUE;
643     }
644     else if (num == GPTIMER_11) {
645         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
646         GPTRegs = GPT11Base;
647         GPT11InUse = TRUE;
648     }
649     else if (num == GPTIMER_5) {
650         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
651         GPTRegs = GPT5Base;
652         GPT5InUse = TRUE;
653         // make sure abe clock is enabled as it is source for gpt5
654         out32((uintptr_t)(cm_core_aon_base_va + CM_ABE_CLKSTCTRL_OFFSET), 0x2);
655     }
656     else if (num == GPTIMER_6) {
657         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
658         GPTRegs = GPT6Base;
659         GPT6InUse = TRUE;
660         // make sure abe clock is enabled as it is source for gpt6
661         out32((uintptr_t)(cm_core_aon_base_va + CM_ABE_CLKSTCTRL_OFFSET), 0x2);
662     }
663     else {
664         return -EINVAL;
665     }
667     /* Enable GPT MODULEMODE and set CLKSEL to SYS_CLK*/
668     out32(GPTClkCtrl, 0x2);
669     do {
670         if (!(in32(GPTClkCtrl) & 0x30000))
671             break;
672     } while (--max_tries);
673     if (max_tries == 0) {
674         ipu_pm_gpt_disable(num);
675         return -EIO;
676     }
678     /* Set Smart-idle wake-up-capable */
679     out32((uintptr_t)&GPTRegs->tiocp_cfg, 0xC);
681     return EOK;
684 int ipu_pm_gpt_disable(int num)
686     uintptr_t GPTClkCtrl = NULL;
687     GPTIMER_REGS *GPTRegs = NULL;
688     UINT32 reg = 0;
690     if (num == GPTIMER_3) {
691         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
692         GPTRegs = GPT3Base;
693         GPT3InUse = FALSE;
694     }
695     else if (num == GPTIMER_4) {
696         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
697         GPTRegs = GPT4Base;
698         GPT4InUse = FALSE;
699     }
700     else if (num == GPTIMER_9) {
701         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
702         GPTRegs = GPT9Base;
703         GPT9InUse = FALSE;
704     }
705     else if (num == GPTIMER_11) {
706         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
707         GPTRegs = GPT11Base;
708         GPT11InUse = FALSE;
709     }
710     else if (num == GPTIMER_5) {
711         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
712         GPTRegs = GPT5Base;
713         GPT5InUse = FALSE;
714     }
715     else if (num == GPTIMER_6) {
716         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
717         GPTRegs = GPT6Base;
718         GPT6InUse = FALSE;
719     }
720     else {
721         return -EINVAL;
722     }
724     /*Check if Clock is Enabled*/
725     reg = in32(GPTClkCtrl);
726     if ((reg & 0x3) == 0x2) {
727         /* Clear any pending interrupt to allow idle */
728         reg = in32((uintptr_t)&GPTRegs->irqstatus);
729         if (reg) {
730             out32((uintptr_t)&GPTRegs->irqstatus, reg);
731         }
733         /*Disable the Timer*/
734         reg = in32(GPTClkCtrl);
735         reg &= 0xFFFFFFFC;
736         out32(GPTClkCtrl, reg);
737     }
738     else {
739         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_disable", -EINVAL,
740                             "gpt clock is not enabled!");
741         return -EINVAL;
742     }
743     return EOK;
746 int ipu_pm_gpt_start (int num)
748     GPTIMER_REGS * GPTRegs = NULL;
749     uint32_t reg = 0;
751     if (num == GPTIMER_3) {
752         GPTRegs = GPT3Base;
753     }
754     else if (num == GPTIMER_4) {
755         GPTRegs = GPT4Base;
756     }
757     else if (num == GPTIMER_9) {
758         GPTRegs = GPT9Base;
759     }
760     else if (num == GPTIMER_11) {
761         GPTRegs = GPT11Base;
762     }
763     else if (num == GPTIMER_5) {
764         GPTRegs = GPT5Base;
765     }
766     else if (num == GPTIMER_6) {
767         GPTRegs = GPT6Base;
768     }
769     else {
770         return -EINVAL;
771     }
773     /*Start the Timer*/
774     reg = in32((uintptr_t)&GPTRegs->tclr);
775     reg |=0x1;
776     out32((uintptr_t)&GPTRegs->tclr, reg);
778     return EOK;
781 int ipu_pm_gpt_stop(int num)
783     uintptr_t GPTClkCtrl = NULL;
784     GPTIMER_REGS * GPTRegs = NULL;
785     uint32_t reg = 0;
787     if (num == GPTIMER_3) {
788         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
789         GPTRegs = GPT3Base;
790     }
791     else if (num == GPTIMER_4) {
792         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
793         GPTRegs = GPT4Base;
794     }
795     else if (num == GPTIMER_9) {
796         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
797         GPTRegs = GPT9Base;
798     }
799     else if (num == GPTIMER_11) {
800         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
801         GPTRegs = GPT11Base;
802     }
803     else if (num == GPTIMER_5) {
804         GPTClkCtrl = (uintptr_t)GPT5ClkCtrl;
805         GPTRegs = GPT5Base;
806     }
807     else if (num == GPTIMER_6) {
808         GPTClkCtrl = (uintptr_t)GPT6ClkCtrl;
809         GPTRegs = GPT6Base;
810     }
811     else {
812         return -EINVAL;
813     }
815     /*Check if Clock is Enabled*/
816     reg = in32(GPTClkCtrl);
817     if ((reg & 0x3) == 0x2) {
819         /*Stop the Timer*/
820         reg = in32((uintptr_t)&GPTRegs->tclr);
821         reg &=0xFFFFFFFE;
822         out32((uintptr_t)&GPTRegs->tclr, reg);
823     }
824     else {
825         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_stop", -EINVAL,
826                             "gpt clock is not enabled!");
827         return -EINVAL;
828     };
830     return EOK;
833 void save_gpt_context(int num)
835     GPTIMER_REGS *GPTRegs = NULL;
836     GPTIMER_REGS *GPTSaved = NULL;
837     bool *GPTRestore = NULL;
839     if (num == GPTIMER_3) {
840         GPTRegs = GPT3Base;
841         GPTSaved = &GPT3Reg_saved;
842         GPTRestore = &GPT3Saved;
843     }
844     else if (num == GPTIMER_4) {
845         GPTRegs = GPT4Base;
846         GPTSaved = &GPT4Reg_saved;
847         GPTRestore = &GPT4Saved;
848     }
849     else if (num == GPTIMER_9) {
850         GPTRegs = GPT9Base;
851         GPTSaved = &GPT9Reg_saved;
852         GPTRestore = &GPT9Saved;
853     }
854     else if (num == GPTIMER_11) {
855         GPTRegs = GPT11Base;
856         GPTSaved = &GPT11Reg_saved;
857         GPTRestore = &GPT11Saved;
858     }
859     else if (num == GPTIMER_5) {
860         GPTRegs = GPT5Base;
861         GPTSaved = &GPT5Reg_saved;
862         GPTRestore = &GPT5Saved;
863     }
864     else if (num == GPTIMER_6) {
865         GPTRegs = GPT6Base;
866         GPTSaved = &GPT6Reg_saved;
867         GPTRestore = &GPT6Saved;
868     }
869     else {
870         return;
871     }
873     GPTSaved->tiocp_cfg = in32((uintptr_t)&GPTRegs->tiocp_cfg);
874     GPTSaved->tcrr = in32((uintptr_t)&GPTRegs->tcrr);
875     GPTSaved->irqenable_set = in32((uintptr_t)&GPTRegs->irqenable_set);
876     GPTSaved->irqstatus_raw = in32((uintptr_t)&GPTRegs->irqstatus_raw);
877     GPTSaved->irqstatus = in32((uintptr_t)&GPTRegs->irqstatus);
878     GPTSaved->irqwakeen = in32((uintptr_t)&GPTRegs->irqwakeen);
879     GPTSaved->tclr = in32((uintptr_t)&GPTRegs->tclr);
880     GPTSaved->tldr = in32((uintptr_t)&GPTRegs->tldr);
881     GPTSaved->ttgr = in32((uintptr_t)&GPTRegs->ttgr);
882     GPTSaved->tmar = in32((uintptr_t)&GPTRegs->tmar);
883     GPTSaved->tsicr = in32((uintptr_t)&GPTRegs->tsicr);
884     *GPTRestore = TRUE;
887 void restore_gpt_context(int num)
889     GPTIMER_REGS *GPTRegs = NULL;
890     GPTIMER_REGS *GPTSaved = NULL;
891     bool *GPTRestore = NULL;
893     if (num == GPTIMER_3) {
894         GPTRegs = GPT3Base;
895         GPTSaved = &GPT3Reg_saved;
896         GPTRestore = &GPT3Saved;
897     }
898     else if (num == GPTIMER_4) {
899         GPTRegs = GPT4Base;
900         GPTSaved = &GPT4Reg_saved;
901         GPTRestore = &GPT4Saved;
902     }
903     else if (num == GPTIMER_9) {
904         GPTRegs = GPT9Base;
905         GPTSaved = &GPT9Reg_saved;
906         GPTRestore = &GPT9Saved;
907     }
908     else if (num == GPTIMER_11) {
909         GPTRegs = GPT11Base;
910         GPTSaved = &GPT11Reg_saved;
911         GPTRestore = &GPT11Saved;
912     }
913     else if (num == GPTIMER_5) {
914         GPTRegs = GPT5Base;
915         GPTSaved = &GPT5Reg_saved;
916         GPTRestore = &GPT5Saved;
917     }
918     else if (num == GPTIMER_6) {
919         GPTRegs = GPT6Base;
920         GPTSaved = &GPT6Reg_saved;
921         GPTRestore = &GPT6Saved;
922     }
923     else {
924         return;
925     }
927     if (*GPTRestore) {
928         *GPTRestore = FALSE;
929         out32((uintptr_t)&GPTRegs->tiocp_cfg, GPTSaved->tiocp_cfg);
930         out32((uintptr_t)&GPTRegs->irqenable_set, GPTSaved->irqenable_set);
931         out32((uintptr_t)&GPTRegs->tcrr, GPTSaved->tcrr);
932         out32((uintptr_t)&GPTRegs->irqstatus_raw, GPTSaved->irqstatus_raw);
933         out32((uintptr_t)&GPTRegs->irqstatus, GPTSaved->irqstatus);
934         out32((uintptr_t)&GPTRegs->irqwakeen, GPTSaved->irqwakeen);
935         out32((uintptr_t)&GPTRegs->tclr, GPTSaved->tclr);
936         out32((uintptr_t)&GPTRegs->tldr, GPTSaved->tldr);
937         out32((uintptr_t)&GPTRegs->ttgr, GPTSaved->ttgr);
938         out32((uintptr_t)&GPTRegs->tmar, GPTSaved->tmar);
939         out32((uintptr_t)&GPTRegs->tsicr, GPTSaved->tsicr);
940     }
943 int ipu_pm_ivaseq0_disable()
945     uintptr_t pm_base = 0;
946     uint32_t reg = 0;
947     enum processor_version omap_rev;
948     uint32_t rm_iva_rstctrl_offset;
950     pthread_mutex_lock(&ipu_pm_state.mtx);
952     if (ipu_pm_state.ivaseq0_use_cnt-- == 1) {
953         pm_base = (uintptr_t)prm_base_va;
955         omap_rev = get_omap_version();
956         if (omap_rev < 0) {
957             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
958                                  omap_rev, "Error while reading the OMAP REVISION");
959             return -EIO;
960         }
962         if (omap_rev == OMAP_5430_es20) {
963             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
964         }
965         else {
966             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
967         }
969         reg = in32(pm_base + rm_iva_rstctrl_offset);
970         reg |= 0x1;
971         out32(pm_base + rm_iva_rstctrl_offset, reg);
972     }
973     else {
974         GT_0trace(curTrace, GT_3CLASS, "ivaseq0 still in use");
975     }
977     pthread_mutex_unlock(&ipu_pm_state.mtx);
978     return EOK;
981 int ipu_pm_ivaseq0_enable()
983     uintptr_t pm_base = 0;
984     uint32_t reg = 0;
985     enum processor_version omap_rev;
986     uint32_t rm_iva_rstctrl_offset;
988     pthread_mutex_lock(&ipu_pm_state.mtx);
989     if (++ipu_pm_state.ivaseq0_use_cnt == 1) {
990         pm_base = (uintptr_t)prm_base_va;
992         omap_rev = get_omap_version();
993         if (omap_rev < 0) {
994             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
995                                  omap_rev, "Error while reading the OMAP REVISION");
996             return -EIO;
997         }
999         if (omap_rev == OMAP_5430_es20) {
1000             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1001         }
1002         else {
1003             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1004         }
1006         reg = in32(pm_base + rm_iva_rstctrl_offset);
1007         reg &= 0xFFFFFFFE;
1008         out32(pm_base + rm_iva_rstctrl_offset, reg);
1009     }
1010     else {
1011         GT_0trace(curTrace, GT_3CLASS, "ivaseq0 still in use");
1012     }
1014     pthread_mutex_unlock(&ipu_pm_state.mtx);
1015     return EOK;
1018 int ipu_pm_ivaseq1_disable()
1020     uintptr_t pm_base = 0;
1021     uint32_t reg = 0;
1022     enum processor_version omap_rev;
1023     uint32_t rm_iva_rstctrl_offset;
1025     pthread_mutex_lock(&ipu_pm_state.mtx);
1027     if (ipu_pm_state.ivaseq1_use_cnt-- == 1) {
1028         pm_base = (uintptr_t)prm_base_va;
1030         omap_rev = get_omap_version();
1031         if (omap_rev < 0) {
1032             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
1033                                  omap_rev, "Error while reading the OMAP REVISION");
1034             return -EIO;
1035         }
1037         if (omap_rev == OMAP_5430_es20) {
1038             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1039         }
1040         else {
1041             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1042         }
1044         reg = in32(pm_base + rm_iva_rstctrl_offset);
1045         reg |= 0x2;
1046         out32(pm_base + rm_iva_rstctrl_offset, reg);
1047     }
1048     else {
1049         GT_0trace(curTrace, GT_3CLASS, "ivaseq1 still in use");
1050     }
1052     pthread_mutex_unlock(&ipu_pm_state.mtx);
1053     return EOK;
1056 int ipu_pm_ivaseq1_enable()
1058     uintptr_t pm_base = 0;
1059     uint32_t reg = 0;
1060     enum processor_version omap_rev;
1061     uint32_t rm_iva_rstctrl_offset;
1063     pthread_mutex_lock(&ipu_pm_state.mtx);
1064     if (++ipu_pm_state.ivaseq1_use_cnt == 1) {
1065         pm_base = (uintptr_t)prm_base_va;
1067         omap_rev = get_omap_version();
1068         if (omap_rev < 0) {
1069             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivaseq0_disable",
1070                                  omap_rev, "Error while reading the OMAP REVISION");
1071             return -EIO;
1072         }
1074         if (omap_rev == OMAP_5430_es20) {
1075             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1076         }
1077         else {
1078             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1079         }
1081         reg = in32(pm_base + rm_iva_rstctrl_offset);
1082         reg &= 0xFFFFFFFD;
1083         out32(pm_base + rm_iva_rstctrl_offset, reg);
1084     }
1085     else {
1086         GT_0trace(curTrace, GT_3CLASS, "ivaseq1 still in use");
1087     }
1089     pthread_mutex_unlock(&ipu_pm_state.mtx);
1090     return EOK;
1093 int ipu_pm_ivahd_disable()
1095     uintptr_t pm_base = 0;
1096     uintptr_t cm_base = 0;
1097     uint32_t reg = 0;
1098     int max_tries = 100;
1099     enum processor_version omap_rev;
1100     uint32_t pm_iva_pwrstctrl_offset;
1101     uint32_t cm_iva_clkstctrl_offset;
1102     uint32_t cm_iva_iva_clkctrl_offset;
1103     uint32_t cm_iva_sl2_clkctrl_offset;
1104     uint32_t rm_iva_rstctrl_offset;
1106     pthread_mutex_lock(&ipu_pm_state.mtx);
1108     if (ipu_pm_state.ivahd_use_cnt-- == 1) {
1109         omap_rev = get_omap_version();
1110         if (omap_rev < 0) {
1111             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_disable",
1112                                  omap_rev, "Error while reading the OMAP REVISION");
1113             return -EIO;
1114         }
1115         pm_base = (uintptr_t)prm_base_va;
1116         cm_base = (uintptr_t)cm2_base_va;
1118         if (omap_rev == OMAP_5430_es20) {
1119             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1120             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1121             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1122             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1123             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1124         }
1125         else {
1126             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1127             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1128             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1129             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1130             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1131         }
1133         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1134         reg &= 0xFFFFFFFC;
1135         reg |= 0x00000002;
1136         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1138         /* Ensure that the wake up mode is set to SW_WAKEUP */
1139         out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1141 #ifndef OMAP5_VIRTIO
1142         /* Check the standby status */
1143         do {
1144             if (((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00040000) != 0x0))
1145                 break;
1146         } while (--max_tries);
1147         if (max_tries == 0) {
1148             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
1149         }
1150 #endif
1152         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
1153         out32(cm_base + cm_iva_iva_clkctrl_offset, 0x00000000);
1154 #ifndef OMAP5_VIRTIO
1155         max_tries = 100;
1156         do {
1157             if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) == 0x30000)
1158                 break;
1159         } while (--max_tries);
1160         if (max_tries == 0) {
1161            GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
1162         }
1163 #endif
1165         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
1166         out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x00000000);
1167 #ifndef OMAP5_VIRTIO
1168         max_tries = 100;
1169         do {
1170             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) == 0x30000);
1171                 break;
1172         } while (--max_tries);
1173         if (max_tries == 0) {
1174             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 CLKCTRL");
1175         }
1176 #endif
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 */
1183 #ifndef OMAP5_VIRTIO
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");
1187 #endif
1189         // IVA sub-system resets - Assert reset for IVA logic and SL2
1190         out32(pm_base + rm_iva_rstctrl_offset, 0x00000004);
1191         max_tries = 200;
1192         while(--max_tries);
1194         // IVA sub-system resets - Assert reset for IVA logic, SL2, and sequencer1
1195         out32(pm_base + rm_iva_rstctrl_offset, 0x00000005);
1196         max_tries = 200;
1197         while(--max_tries);
1199         // IVA sub-system resets - Assert reset for IVA logic, SL2, sequencer1 and sequencer2
1200         out32(pm_base + rm_iva_rstctrl_offset, 0x00000007);
1201     }
1202     else {
1203         GT_0trace(curTrace, GT_3CLASS, "ivahd still in use");
1204     }
1206     pthread_mutex_unlock(&ipu_pm_state.mtx);
1207     return EOK;
1210 int ipu_pm_ivahd_enable()
1212     uintptr_t pm_base = 0;
1213     uintptr_t cm_base = 0;
1214     uint32_t reg = 0;
1215     unsigned int pwrst = 0;
1216     int max_tries = 100;
1217     enum processor_version omap_rev;
1218     uint32_t pm_iva_pwrstctrl_offset;
1219     uint32_t cm_iva_clkstctrl_offset;
1220     uint32_t cm_iva_iva_clkctrl_offset;
1221     uint32_t cm_iva_sl2_clkctrl_offset;
1222     uint32_t rm_iva_rstctrl_offset;
1223     uint32_t rm_iva_iva_context_offset;
1224     uint32_t pm_iva_pwrstst_offset;
1226     pthread_mutex_lock(&ipu_pm_state.mtx);
1228     if (++ipu_pm_state.ivahd_use_cnt == 1) {
1229         pm_base = (uintptr_t)prm_base_va;
1230         cm_base = (uintptr_t)cm2_base_va;
1232         omap_rev = get_omap_version();
1233         if (omap_rev < 0) {
1234             GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1235                                  omap_rev, "Error while reading the OMAP REVISION");
1236             return -EIO;
1237         }
1239         if (omap_rev == OMAP_5430_es20) {
1240             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1241             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1242             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1243             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1244             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1245             rm_iva_iva_context_offset = RM_IVA_IVA_CONTEXT_ES20_OFFSET;
1246             pm_iva_pwrstst_offset = PM_IVA_PWRSTST_ES20_OFFSET;
1247         }
1248         else {
1249             pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1250             cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1251             cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1252             cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1253             rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1254             rm_iva_iva_context_offset = RM_IVA_IVA_CONTEXT_OFFSET;
1255             pm_iva_pwrstst_offset = PM_IVA_PWRSTST_OFFSET;
1256         }
1257         /* Read the IVAHD Context register to check if the memory content has been lost */
1258         reg = in32(pm_base + rm_iva_iva_context_offset);
1259         /* Clear the context register by writing 1 to bit 8,9 and 10 */
1260         out32(pm_base + rm_iva_iva_context_offset, 0x700);
1262         /*Display power state*/
1263         pwrst = in32(pm_base + pm_iva_pwrstst_offset);
1264         GT_1trace(curTrace, GT_4CLASS, "###: off state reg bit = 0x%x\n", (pwrst & 0x03000003));
1265         /*Clear the power status reg by writting 1'a into the requred bits*/
1266         out32(pm_base + pm_iva_pwrstst_offset, 0x03000000);
1268         /* Ensure power state is set to ON */
1269         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1270         reg &= 0xFFFFFFFC;
1271         reg |= 0x00000003;
1272         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1274         /* Ensure that the wake up mode is set to SW_WAKEUP */
1275         out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1277 #ifndef OMAP5_VIRTIO
1278         max_tries = 100;
1279         while(((in32(pm_base + pm_iva_pwrstst_offset) & 0x00100000) != 0) && --max_tries);
1280         if (max_tries == 0)
1281             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_enable: WARNING - PwrSt did not transition");
1282 #endif
1284         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
1285         out32(cm_base + cm_iva_iva_clkctrl_offset, 0x00000001);
1287         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
1288         out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x00000001);
1290         /* Wait until the CLK_ACTIVITY bit is set */
1291 #ifndef OMAP5_VIRTIO
1292         max_tries = 100;
1293         while (((in32(cm_base + cm_iva_clkstctrl_offset) & 0x00000100) == 0x0) && --max_tries);
1294         if (max_tries == 0)
1295             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_enable: WARNING - Clk_ACTIVITY bit is not set");
1296 #endif
1298         /* Release ICONT1 and SL2/IVAHD first, wait for few usec  then release ICONT2 */
1299         reg = in32(pm_base + rm_iva_rstctrl_offset);
1300         reg &= 0xFFFFFFFB;
1301         out32(pm_base + rm_iva_rstctrl_offset, reg);
1302 #ifndef OMAP5_VIRTIO
1303         max_tries = 100;
1304         usleep(100);
1305         do {
1306             if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) == 0x0)
1307                 break;
1308         } while(--max_tries);
1309         if (max_tries == 0) {
1310             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD clk control");
1311             return -EIO;
1312         }
1314         max_tries = 100;
1315         do {
1316             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) == 0x00000)
1317                 break;
1318         } while(--max_tries);
1319         if (max_tries == 0) {
1320             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 clk control");
1321             return -EIO;
1322         }
1324         max_tries = 100;
1325         do {
1326             if((in32(cm_base + CM_L3_2_L3_2_CLKCTRL_OFFSET) & 0x30001) == 0x00001)
1327                 break;
1328         } while(--max_tries);
1329         if (max_tries == 0) {
1330             GT_0trace(curTrace, GT_4CLASS," ** Error in L3 clk control");
1331             return -EIO;
1332         }
1334         /* Ensure IVAHD and SL2 is functional */
1335         max_tries = 100;
1336         do {
1337         if((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030001) == 0x00001)
1338             break;
1339         } while(--max_tries);
1340         if (max_tries == 0) {
1341             GT_0trace(curTrace, GT_4CLASS," ** IVAHD is not functional");
1342             return -EIO;
1343         }
1345         max_tries = 100;
1346         do {
1347             if((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030001) == 0x00001)
1348                 break;
1349         } while(--max_tries);
1350         if (max_tries == 0) {
1351             GT_0trace(curTrace, GT_4CLASS," ** SL2 is not functional");
1352             return -EIO;
1353         }
1354 #endif
1355     } else {
1356         GT_0trace(curTrace, GT_3CLASS, "ivahd already acquired");
1357     }
1359     pthread_mutex_unlock(&ipu_pm_state.mtx);
1360     return EOK;
1363 int ipu_pm_ivahd_off()
1365     uintptr_t pm_base = 0;
1366     uintptr_t cm_base = 0;
1367     uint32_t reg = 0;
1368     int32_t max_tries = 0;
1369     bool ivahd_enabled = false;
1370     bool sl2_enabled = false;
1371     enum processor_version omap_rev;
1372     uint32_t pm_iva_pwrstctrl_offset;
1373     uint32_t cm_iva_clkstctrl_offset;
1374     uint32_t cm_iva_iva_clkctrl_offset;
1375     uint32_t cm_iva_sl2_clkctrl_offset;
1376     uint32_t rm_iva_rstctrl_offset;
1377     uint32_t pm_iva_pwrstst_offset;
1379     pm_base = (uintptr_t)prm_base_va;
1380     cm_base = (uintptr_t)cm2_base_va;
1382     omap_rev = get_omap_version();
1383     if (omap_rev < 0) {
1384         GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1385                              omap_rev, "Error while reading the OMAP REVISION");
1386         return -EIO;
1387     }
1389     if (omap_rev == OMAP_5430_es20) {
1390         pm_iva_pwrstst_offset = PM_IVA_PWRSTST_ES20_OFFSET;
1391         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1392         cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_ES20_OFFSET;
1393         cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_ES20_OFFSET;
1394         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1395         rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_ES20_OFFSET;
1396     }
1397     else {
1398         pm_iva_pwrstst_offset = PM_IVA_PWRSTST_OFFSET;
1399         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1400         cm_iva_iva_clkctrl_offset = CM_IVA_IVA_CLKCTRL_OFFSET;
1401         cm_iva_sl2_clkctrl_offset = CM_IVA_SL2_CLKCTRL_OFFSET;
1402         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1403         rm_iva_rstctrl_offset = RM_IVA_RSTCTRL_OFFSET;
1404     }
1406     reg = in32(pm_base + pm_iva_pwrstst_offset);
1407     reg = reg & 0x00000007;
1409     if (reg != 0x00000000) {
1410         /* set IVAHD to SW_WKUP */
1411         out32(cm_base + cm_iva_clkstctrl_offset, 0x2);
1412         max_tries = 100;
1413         /* Check for ivahd module and disable if it is enabled */
1414         if ((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x1) != 0) {
1415             out32(cm_base + cm_iva_iva_clkctrl_offset, 0x0);
1416             ivahd_enabled = 1;
1417         }
1418         /* Check for sl2 module and disable if it is enabled */
1419         if ((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x1) != 0) {
1420             out32(cm_base + cm_iva_sl2_clkctrl_offset, 0x0);
1421             sl2_enabled = 1;
1422         }
1423         if (ivahd_enabled || sl2_enabled) {
1424             while (((in32(cm_base + cm_iva_clkstctrl_offset) & 0x00000100) == 0x0) && --max_tries);
1425             if (max_tries == 0) {
1426                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM:IVAHD DOMAIN is Not Enabled after retries");
1427             }
1428         }
1430         /* Set IVAHD PD to OFF */
1431         reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1432         reg = (reg & 0xFFFFFFFC) | 0x0;
1433         out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1435         max_tries = 100;
1436         while (((in32(pm_base + pm_iva_pwrstst_offset) & 0x00100000) != 0) && --max_tries);
1437         if (max_tries == 0) {
1438            GT_0trace(curTrace, GT_4CLASS,"IPU_PM: IVAHD Power Domain is in transition after retries");
1439         }
1441         if (ivahd_enabled) {
1442             max_tries = 100;
1443             while (((in32(cm_base + cm_iva_iva_clkctrl_offset) & 0x00030000) != 0x30000) && --max_tries);
1444             if (max_tries == 0) {
1445                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the IVAHD Module after retries");
1446             }
1447         }
1448         if (sl2_enabled) {
1449             max_tries = 100;
1450             while (((in32(cm_base + cm_iva_sl2_clkctrl_offset) & 0x00030000) != 0x30000) && --max_tries);
1451             if (max_tries == 0) {
1452                 GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the SL2 Module after retries");
1453             }
1454         }
1455         /* Set IVAHD to HW_AUTO */
1456         out32(cm_base + cm_iva_clkstctrl_offset, 0x3);
1457         /* Check the reset states and assert resets */
1458         if (in32(pm_base + rm_iva_rstctrl_offset) != 0x7) {
1459             out32(pm_base + rm_iva_rstctrl_offset, 0x7);
1460         }
1461     }
1463     return EOK;
1466 int ipu_pm_ivahd_on()
1468     uintptr_t pm_base = 0;
1469     uintptr_t cm_base = 0;
1470     uint32_t reg = 0;
1471     enum processor_version omap_rev;
1472     uint32_t pm_iva_pwrstctrl_offset;
1473     uint32_t cm_iva_clkstctrl_offset;
1475     pm_base = (uintptr_t)prm_base_va;
1476     cm_base = (uintptr_t)cm2_base_va;
1478     omap_rev = get_omap_version();
1479     if (omap_rev < 0) {
1480         GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_enable",
1481                              omap_rev, "Error while reading the OMAP REVISION");
1482         return -EIO;
1483     }
1485     if (omap_rev == OMAP_5430_es20) {
1486         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_ES20_OFFSET;
1487         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_ES20_OFFSET;
1488     }
1489     else {
1490         pm_iva_pwrstctrl_offset = PM_IVA_PWRSTCTRL_OFFSET;
1491         cm_iva_clkstctrl_offset = CM_IVA_CLKSTCTRL_OFFSET;
1492     }
1494     /* Set the power state to ON */
1495     reg = in32(pm_base + pm_iva_pwrstctrl_offset);
1496     reg &= 0xFFFFFFFC;
1497     reg |= 0x00000002;
1498     out32(pm_base + pm_iva_pwrstctrl_offset, reg);
1500     /* Ensure that the wake up mode is set to SW_WAKEUP */
1501     out32(cm_base + cm_iva_clkstctrl_offset, 0x00000002);
1503     /* put IVA into HW Auto mode */
1504     reg = in32(cm_base + cm_iva_clkstctrl_offset);
1505     reg |= 0x00000003;
1506     out32(cm_base + cm_iva_clkstctrl_offset, reg);
1508     return EOK;
1511 int ipu_pm_led_enable(unsigned int mode, unsigned int intensity)
1513     int ret = 0;
1515     //ret = camflash_config(mode, intensity);
1517     if (ret != -1)
1518         last_led_req = mode;
1520     return ret;
1523 int ipu_pm_alloc_sdma(int num_chs, int* channels)
1525     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma++");
1527     if(DMAAllocation == false) {
1528         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1529         return -1;
1530     }
1531     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma--");
1532     return 0;
1535 int ipu_pm_free_sdma(int num_chs, int* channels)
1537     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma++");
1539     if(DMAAllocation == false) {
1540         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1541         return -1;
1542     }
1543     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma--");
1544     return 0;
1547 int ipu_pm_camera_enable(unsigned int mode, unsigned int on)
1549     int ret = 0;
1551     //ret = campower_config(mode, on);
1553     if (mode < NUM_CAM_MODES && ret == 0)
1554         last_camera_req[mode] = on;
1556     return ret;
1559 int ipu_pm_get_max_freq(unsigned int proc, unsigned int * freq)
1561     int status = EOK;
1563     switch (proc) {
1564         case RPRM_IVAHD:
1565             /* Would like to replace the below with a call to powerman */
1566             *freq = IVAHD_FREQ_MAX_IN_HZ;
1567             break;
1568         default:
1569             status = -ENOENT;
1570             break;
1571     }
1573     return status;
1576 #ifdef QNX_PM_ENABLE
1577 static int ipu_pm_power_init(void)
1579     /*Allocate SDMA channels*/
1580     memset(&sdma_req, 0, sizeof(sdma_req));
1581     sdma_req.length = MAX_DUCATI_CHANNELS;
1582     sdma_req.flags = RSRCDBMGR_DMA_CHANNEL | RSRCDBMGR_FLAG_RANGE;
1583     sdma_req.start = DUCATI_CHANNEL_START;
1584     sdma_req.end = DUCATI_CHANNEL_END;
1585     if (rsrcdbmgr_attach(&sdma_req, 1) == -1) {
1586         DMAAllocation = false;
1587         GT_1trace(curTrace, GT_4CLASS,
1588         "ipu_pm_power_init: DMA channel allocation FAILED: %s", strerror(errno));
1589     }
1590     else {
1591         GT_0trace(curTrace, GT_3CLASS,
1592             "ipu_pm_power_init: DMA channels ALLOCATED");
1593         DMAAllocation = true;
1594     }
1596     return EOK;
1599 static void ipu_pm_power_deinit(void)
1601     if(DMAAllocation){
1602         if (rsrcdbmgr_detach(&sdma_req, 1) == -1) {
1603             GT_1trace(curTrace, GT_4CLASS,
1604                       "ipu_pm_power_deinit: DMA channel deallocation FAILED!!%s",
1605                       strerror(errno));
1606         }
1607         DMAAllocation = false;
1608     }
1609     return;
1612 static int ipu_pm_powman_init(void)
1614     int status = EOK;
1616     syslink_auth_active = powman_auth_create("SYSLINK_NEEDS_CORE_ACTIVE");
1617     if(!syslink_auth_active) {
1618         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1619                 "syslink_auth_active create failure");
1620         return -ENOMEM;
1622     }
1624     syslink_auth_oswr = powman_auth_create("SYSLINK_NEEDS_PREVENT_OSWR");
1625     if(!syslink_auth_oswr) {
1626         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1627                 "syslink_auth_oswr create failure");
1628         return -ENOMEM;
1629     }
1631     int retry = 100;
1633     /* look for server  */
1634     cpudll_coid = name_open( CPUDLL_RECV_NAME, 0);
1635     while (cpudll_coid == -1 && retry-- > 0) {
1636         sleep(1);
1637         cpudll_coid = name_open (CPUDLL_RECV_NAME, 0);
1638     }
1640     if (cpudll_coid == -1) {
1641         GT_setFailureReason (curTrace, GT_4CLASS, "connect to cpudll", EINVAL,
1642                              "Couldn't connect to CPU DLL!");
1643         return EINVAL;
1644     }
1646     /* get IVA OPPs   */
1647     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1648     dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1649     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_iva_opp, sizeof(cpudll_iva_opp) ) == -1)  {
1650         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1651                             "Could not get list of IVA OPPs.");
1652         return -ENOMEM;
1653     }
1655     /* get CORE OPPs   */
1656     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1657     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1658     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_core_opp, sizeof(cpudll_core_opp) ) == -1)  {
1659         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1660                             "Could not get list of Core OPPs.");
1661         return -ENOMEM;
1662     }
1663     return status;
1666 static void ipu_pm_powman_deinit(void)
1668     int status = EOK;
1670     if (syslink_auth_active) {
1671         status = powman_auth_destroy(syslink_auth_active);
1672         if (status < 0) {
1673             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1674                              status,
1675                              "powman_auth_destroy syslink_auth_active failure");
1676         }
1677         syslink_auth_active = NULL;
1678     }
1679     if (syslink_auth_oswr) {
1680         status = powman_auth_destroy(syslink_auth_oswr);
1681         if (status < 0) {
1682             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1683                                status,
1684                                "powman_auth_destroy syslink_auth_oswr failure");
1685         }
1686         syslink_auth_oswr = NULL;
1687     }
1689     // close the channel
1690     dvfsMessage.dvfs.type   = (cpudll_type_e)closeClient;
1691     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 ) == -1) {
1692         GT_setFailureReason(curTrace, GT_4CLASS, "powman_deinit", ENOMEM,
1693                             "Could not close client connection to server.");
1694     }
1696     name_close(cpudll_coid);
1697     cpudll_coid = -1;
1700 //no special callback needed in our case so define the default.
1701 int powman_delayed_callback(unsigned ns, void (*func) (void *), void *data)
1703     return (powman_delayed_callback_default(ns, func, data));
1706 static void tell_powman_auth_oswr(int need)
1708     int r;
1709     r = powman_auth_state(syslink_auth_oswr, need);
1710     if(r != 0) {
1711         GT_setFailureReason(curTrace, GT_4CLASS, "tell_powman_auth_oswr", r,
1712                                         "powerman authority :cannot set state");
1713     }
1716 int ipu_pm_set_bandwidth(unsigned int bandwidth)
1718     int err;
1719     int oppIndex = CPUDLL_MAX_OPP_STATES-1;
1721     /* Camera needs OPPOV (highest OPP) which will be moving from index 1 to 2.
1722      * Find the greatest non-zero element to find the highest OPP and select it.
1723      */
1724     while ( (cpudll_core_opp.states[oppIndex] == 0) && (oppIndex > 0) ){
1725         oppIndex--;
1726     }
1728     dvfsMessage.dvfs.type   = setDomainOPP;
1729     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1731     dvfsMessage.dvfs.req_opp = cpudll_core_opp.states[ bandwidth>=COREOPP100?oppIndex:0 ];
1732     err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1733     if(err != EOK) {
1734         GT_1trace(curTrace, GT_4CLASS," ** Error setting CORE OPP: %s", strerror(errno));
1735     }
1736     return EOK;
1739 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1741     int err = EOK;
1742     cpudll_iva_opp_t req = 0;
1744     if (request->target_rsrc == RPRM_IVAHD) {
1745         if (request->rate > FREQ_266Mhz)
1746             req = CPUDLL_IVA_OPPTURBO;
1747         else if ((request->rate > FREQ_133Mhz) &&
1748                  (request->rate <= FREQ_266Mhz))
1749             req = CPUDLL_IVA_OPP100;
1750         else if ((request->rate > NO_FREQ_CONSTRAINT) &&
1751                  (request->rate <= FREQ_133Mhz))
1752             req = CPUDLL_IVA_OPP50;
1753         else if (request->rate == NO_FREQ_CONSTRAINT)
1754             req = CPUDLL_IVA_OPPNONE;
1756         dvfsMessage.dvfs.req_opp = cpudll_iva_opp.states[req];
1757         dvfsMessage.dvfs.type   = setDomainOPP;
1758         dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1760         err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1761         if(err != EOK) {
1762             GT_2trace(curTrace, GT_4CLASS," ** Error setting IVA OPP %d: %s", req, strerror(err));
1763         }
1764     }
1765     return err;
1767 #else
1768 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1770     return EOK;
1773 int ipu_pm_set_bandwidth(unsigned int bandwidth)
1775     return EOK;
1777 #endif
1779 #ifdef BENELLI_SELF_HIBERNATION
1781 static int configure_timer (int val, int reload)
1783     int status = 0;
1784     struct itimerspec timeout;
1785     timeout.it_value.tv_sec = val;
1786     timeout.it_value.tv_nsec = 0;
1787     timeout.it_interval.tv_sec = reload;
1788     timeout.it_interval.tv_nsec = 0;
1789     status = timer_settime(ipu_pm_state.hibernation_timer, 0, &timeout, NULL);
1790     if (status != 0) {
1791         status = -errno;
1792     }
1793     return status;
1796 /* Function implements hibernation and watch dog timer
1797  * The functionality is based on following states
1798  * RESET:        Timer is disabed
1799  * OFF:            Timer is OFF
1800  * ON:            Timer running
1801  * HIBERNATE:    Waking up for benelli cores to hibernate
1802  * WD_RESET:    Waiting for Benelli cores to complete hibernation
1803  */
1804 int ipu_pm_timer_state(int event)
1806     int retval = 0;
1808     if (!ipu_pm_state.attached)
1809         goto exit;
1811     switch (event) {
1812         case PM_HIB_TIMER_RESET:
1813             /* disable timer and remove irq handler */
1814             //Stop the timer
1815             configure_timer(0, 0);
1816             ipu_pm_state.hib_timer_state = PM_HIB_TIMER_RESET;
1817             break;
1819         case PM_HIB_TIMER_DELETE:
1820             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF) {
1821                 /*Stop the Timer*/
1822                 configure_timer(0, 0);
1823                 /* Delete the timer */
1824                 retval = timer_delete(ipu_pm_state.hibernation_timer);
1825                }
1826               break;
1828         case PM_HIB_TIMER_OFF:
1829             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1830                 /*Stop the Timer*/
1831                 configure_timer(0, 0);
1832                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_OFF;
1833             }
1834             break;
1836         case PM_HIB_TIMER_ON:
1837             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET||
1838                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF||
1839                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_DELETE||
1840                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1842                 /*Enable the timer*/
1843                 /*Start the Timer*/
1844                 configure_timer(syslink_hib_timeout / 1000, 0);
1845                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_ON;
1846             }
1847             break;
1848     }
1850 exit:
1851     if (retval < 0) {
1852       GT_setFailureReason (curTrace,
1853                            GT_4CLASS,
1854                            "ipu_pm_timer_state",
1855                            retval,
1856                            "ipu_pm_timer_state failed");
1857     }
1859     return retval;
1862 /*
1863   Function to save the MMU, Mailbox context before going to hibernation
1864  *
1865  */
1866 int ipu_pm_save_ctx(int proc_id)
1868     int retval = 0;
1869     int flag;
1870     int num_loaded_cores = 0;
1871     int core0_loaded;
1872     int core1_loaded;
1873     unsigned long timeout;
1874     unsigned short core0_id = MultiProc_getId(CORE0);
1875     unsigned short core1_id = MultiProc_getId("CORE1");
1876     unsigned short dsp_id = MultiProc_getId("DSP");
1877     struct itimerspec value;
1878     uint64_t pa = 0, da = 0;
1879     u32 len = 0;
1881     /* get M3's load flag */
1882     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
1883     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
1885     /* Because of the current scheme, we need to check
1886      * if CORE1 is enabled and we need to shut it down too
1887      * CORE0 is the only one sending the hibernate message
1888     */
1889     pthread_mutex_lock(&ipu_pm_state.mtx);
1891     if (core0Idle == NULL) {
1892         if (proc_id == core0_id) {
1893             retval = get_res_info(RSC_SUSPENDADDR, "0", &da, &pa, &len);
1894             if (retval == 0) {
1895                 /* BIOS flags to know the state of IPU cores */
1896                 core0Idle = (void *)mmap_device_io(0x1000, ROUND_DOWN(pa, 0x1000));
1897                 if ((uintptr_t)core0Idle == MAP_DEVICE_FAILED) {
1898                     core0Idle = NULL;
1899                     retval = -ENOMEM;
1900                     goto exit;
1901                 }
1903                 core0Idle = (void *)((uint32_t)core0Idle + ((uint32_t)pa - ROUND_DOWN((uint32_t)pa, 0x1000)));
1904                 core1Idle = (void *)core0Idle + sizeof(void *);
1905             }
1906             else {
1907                 goto exit;
1908             }
1909         }
1910     }
1912     if (proc_id == core0_id || proc_id == core1_id) {
1913         timer_gettime(ipu_pm_state.hibernation_timer, &value);
1914         if (value.it_value.tv_sec || value.it_value.tv_nsec)
1915             goto exit;
1917         if (!core0_loaded)
1918             goto exit;
1920         /* If already down don't kill it twice */
1921         if (ipu_pm_state.proc_state & CORE0_PROC_DOWN) {
1922             GT_0trace(curTrace, GT_4CLASS, "ipu already hibernated");
1923             goto exit;
1924         }
1926         !TESTBITREG32((uintptr_t)m3_clkstctrl,
1927                       CM_MPU_M3_CLKSTCTRL_CLKACTIVITY_BIT)) {
1928         retval = ArchIpcInt_sendInterrupt(core0_id,
1929                                           ipu_pm_state.cfg.int_id,
1930                                           RP_MBOX_HIBERNATION);
1932         num_loaded_cores = core1_loaded + core0_loaded;
1933         flag = 1;
1934         timeout = WAIT_FOR_IDLE_TIMEOUT;
1935         /* Wait fot Benelli to hibernate */
1936         do {
1937             /* Checking if IPU is really in idle */
1938             if (NUM_IDLE_CORES == num_loaded_cores) {
1939                 flag = 0;
1940                 break;
1941             } else {
1942                 usleep(1000);
1943             }
1944         } while ( --timeout != 0);
1946         if (flag) {
1947             GT_0trace(curTrace, GT_4CLASS, "Benelli Cores are NOT really Idle");
1948             goto error;
1949         }
1951         ipu_pm_timer_state(PM_HIB_TIMER_OFF);
1952         retval = Omap5430IpcInt_mboxSaveCtxt(core0_id);
1953         if(retval != OMAP5430IPCINT_SUCCESS){
1954             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1955                                 retval,
1956                                 "Error while saving the MailBox context");
1957             goto error;
1958         }
1960         if (core1_loaded) {
1961 #ifdef BENELLI_WATCHDOG_TIMER
1962             save_gpt_context(GPTIMER_11);
1963             ipu_pm_gpt_stop(GPTIMER_11);
1964             ipu_pm_gpt_disable(GPTIMER_11);
1965 #endif
1966             if (GPT4InUse == TRUE)
1967                 save_gpt_context(GPTIMER_4);
1969             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
1970                                  Omap5430BenelliProc_CtrlCmd_Suspend, NULL);
1971             if (retval < 0) {
1972                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1973                                     retval, "Error while suspending CORE1");
1974                 goto error;
1975             }
1976             GT_0trace(curTrace, GT_4CLASS, "Sleep CORE1");
1977         }
1979 #ifdef BENELLI_WATCHDOG_TIMER
1980         save_gpt_context(GPTIMER_9);
1981         ipu_pm_gpt_stop(GPTIMER_9);
1982         ipu_pm_gpt_disable(GPTIMER_9);
1983 #endif
1984         if (GPT3InUse == TRUE)
1985             save_gpt_context(GPTIMER_3);
1987         ipu_pm_state.proc_state |= CORE1_PROC_DOWN;
1988         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
1989                                  Omap5430BenelliProc_CtrlCmd_Suspend, NULL);
1990         if (retval < 0) {
1991             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
1992                                 "Error while suspending CORE0");
1993             goto error;
1994         }
1995         GT_0trace(curTrace, GT_4CLASS, "Sleep CORE0");
1996         ipu_pm_state.proc_state |= CORE0_PROC_DOWN;
1998         ipu_pm_ivahd_off();
2000         // Advise that Ducati is hibernating
2001         pthread_mutex_lock(&syslink_hib_mutex);
2002         syslink_hib_hibernating = TRUE;
2003         pthread_mutex_unlock(&syslink_hib_mutex);
2004     }
2005     else if (proc_id == dsp_id) {
2006         //TODO: Add support for DSP.
2007     }
2008     else
2009         goto error;
2011 #ifdef QNX_PM_ENABLE
2012     if (oswr_prevent == 1) {
2013         tell_powman_auth_oswr(0); // Passing 1 prevents OSWR and 0 allows OSWR
2014         oswr_prevent = 0;
2015     }
2016 #endif
2017        /* If there is a message in the mbox restore
2018      * immediately after save.
2019      */
2020     if (PENDING_MBOX_MSG)
2021         goto restore;
2023 exit:
2024     pthread_mutex_unlock(&ipu_pm_state.mtx);
2025     return 0;
2026 error:
2027     GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
2028                         "Aborting hibernation process");
2029     ipu_pm_timer_state(PM_HIB_TIMER_ON);
2030     pthread_mutex_unlock(&ipu_pm_state.mtx);
2031     return retval;
2032 restore:
2033     GT_0trace(curTrace, GT_4CLASS,
2034               "Starting restore_ctx since messages pending in mbox");
2035     pthread_mutex_unlock(&ipu_pm_state.mtx);
2036     ipu_pm_restore_ctx(proc_id);
2038     return retval;
2042 /* Function to check if a processor is shutdown
2043  * if shutdown then restore context else return.
2044  */
2045 int ipu_pm_restore_ctx(int proc_id)
2047     int retval = 0;
2048     int core0_loaded;
2049     int core1_loaded;
2050     unsigned short core0_id = MultiProc_getId(CORE0);
2051     unsigned short core1_id = MultiProc_getId("CORE1");
2052     unsigned short dsp_id = MultiProc_getId("DSP");
2054     /*If feature not supported by proc, return*/
2055     if (proc_id == dsp_id)
2056         return 0;
2058     /* Check if the M3 was loaded */
2059     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
2060     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
2062     /* Because of the current scheme, we need to check
2063      * if CORE1 is enable and we need to enable it too
2064      * In both cases we should check if for both cores
2065      * and enable them if they were loaded.
2066      */
2067     pthread_mutex_lock(&ipu_pm_state.mtx);
2069     /* Restart the hib timer */
2070     if (syslink_hib_enable) {
2071         ipu_pm_timer_state(PM_HIB_TIMER_ON);
2072     }
2073 #ifdef QNX_PM_ENABLE
2074     if(oswr_prevent == 0) {
2075         tell_powman_auth_oswr(1); // Passing 1 prevents OSWR and 0 allows OSWR
2076         oswr_prevent = 1;
2077     }
2078 #endif
2079     if (proc_id == core0_id || proc_id == core1_id) {
2080         if (!(ipu_pm_state.proc_state & CORE0_PROC_DOWN) || !core0_loaded) {
2081             goto exit;
2082         }
2084         if (ProcMgr_getState(ipu_pm_state.proc_handles[core0_id]) != ProcMgr_State_Suspended) {
2085             goto exit;
2086         }
2088         retval = Omap5430IpcInt_mboxRestoreCtxt(core0_id);
2089         if(retval != OMAP5430IPCINT_SUCCESS){
2090             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2091                                 retval,
2092                                 "Not able to restore Mail Box context");
2093             goto error;
2094         }
2096 #ifdef BENELLI_WATCHDOG_TIMER
2097         ipu_pm_gpt_enable(GPTIMER_9);
2098         restore_gpt_context(GPTIMER_9);
2099         ipu_pm_gpt_start(GPTIMER_9);
2100 #endif
2101         if (GPT3InUse == TRUE) {
2102             ipu_pm_gpt_enable(GPTIMER_3);
2103             restore_gpt_context(GPTIMER_3);
2104         }
2106         GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE0");
2107         ipu_pm_state.proc_state &= ~CORE0_PROC_DOWN;
2108         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
2109                                  Omap5430BenelliProc_CtrlCmd_Resume, NULL);
2110         if (retval < 0){
2111             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2112                                 retval, "Not able to resume CORE0");
2113             goto error;
2114         }
2116         if (core1_loaded) {
2117 #ifdef BENELLI_WATCHDOG_TIMER
2118             ipu_pm_gpt_enable(GPTIMER_11);
2119             restore_gpt_context(GPTIMER_11);
2120             ipu_pm_gpt_start(GPTIMER_11);
2121 #endif
2122             if (GPT4InUse == TRUE) {
2123                 ipu_pm_gpt_enable(GPTIMER_4);
2124                 restore_gpt_context(GPTIMER_4);
2125             }
2127             GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE1");
2128             ipu_pm_state.proc_state &= ~CORE1_PROC_DOWN;
2129             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
2130                                      Omap5430BenelliProc_CtrlCmd_Resume, NULL);
2131             if (retval < 0){
2132                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
2133                                     retval, "Not able to resume CORE1");
2134                 goto error;
2135             }
2136         }
2137         pthread_mutex_lock(&syslink_hib_mutex);
2138         // Once we are active, signal any thread waiting for end of hibernation
2139         syslink_hib_hibernating = FALSE;
2140         pthread_cond_broadcast(&syslink_hib_cond);
2141         pthread_mutex_unlock(&syslink_hib_mutex);
2142     }
2143     else
2144         goto error;
2145 exit:
2146     /* turn on benelli hibernation timer */
2147     if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF ||
2148         ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET) {
2149             ipu_pm_timer_state(PM_HIB_TIMER_ON);
2150     }
2151     pthread_mutex_unlock(&ipu_pm_state.mtx);
2152     return retval;
2153 error:
2154     pthread_mutex_unlock(&ipu_pm_state.mtx);
2155     return -EINVAL;
2158 /* ISR for Timer*/
2159 static void ipu_pm_timer_interrupt (union sigval val)
2161     ipu_pm_save_ctx(MultiProc_getId(CORE0));
2162     return;
2164 #else // BENELLI_SELF_HIBERNATION
2166 int ipu_pm_restore_ctx(int proc_id)
2168     return 0;
2170 #endif // BENELLI_SELF_HIBERNATION
2172 int ipu_pm_attach(int proc_id)
2174     int retval = EOK;
2175 #ifdef BENELLI_WATCHDOG_TIMER
2176     OsalIsr_Params isrParams;
2177 #endif
2179     if (proc_id > MultiProc_MAXPROCESSORS) {
2180         return -EINVAL;
2181     }
2183     if (proc_id == MultiProc_getId(CORE0)) {
2184         ipu_pm_state.loaded_procs |= CORE0_LOADED;
2185 #ifdef BENELLI_WATCHDOG_TIMER
2186         ipu_pm_gpt_enable(GPTIMER_9);
2187         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2188         isrParams.fxnArgs = (Ptr)GPTIMER_9;
2189         isrParams.intId = OMAP54XX_IRQ_GPT9;
2190         isrParams.sharedInt = FALSE;
2191         ipu_pm_state.gpt9IsrObject =
2192             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2193                            isrParams.fxnArgs, &isrParams);
2194         if(ipu_pm_state.gpt9IsrObject != NULL) {
2195             if (OsalIsr_install(ipu_pm_state.gpt9IsrObject) < 0) {
2196                 retval = -ENOMEM;
2197             }
2198         }
2199         else {
2200             retval = -ENOMEM;
2201         }
2202 #endif
2203 #ifndef SYSLINK_SYSBIOS_SMP
2204     }
2205     else if (proc_id == MultiProc_getId("CORE1")) {
2206 #endif
2207         ipu_pm_state.loaded_procs |= CORE1_LOADED;
2208 #ifdef BENELLI_WATCHDOG_TIMER
2209         ipu_pm_gpt_enable(GPTIMER_11);
2210         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2211         isrParams.fxnArgs = (Ptr)GPTIMER_11;
2212         isrParams.intId = OMAP54XX_IRQ_GPT11;
2213         isrParams.sharedInt = FALSE;
2214         ipu_pm_state.gpt11IsrObject =
2215             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2216                            isrParams.fxnArgs, &isrParams);
2217         if(ipu_pm_state.gpt11IsrObject != NULL) {
2218             if (OsalIsr_install(ipu_pm_state.gpt11IsrObject) < 0) {
2219                 retval = -ENOMEM;
2220             }
2221         }
2222         else {
2223             retval = -ENOMEM;
2224         }
2225 #endif
2226     }
2227     else if (proc_id == MultiProc_getId("DSP")) {
2228         ipu_pm_state.loaded_procs |= DSP_LOADED;
2229 #ifdef BENELLI_WATCHDOG_TIMER
2230         ipu_pm_gpt_enable(GPTIMER_6);
2231         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
2232         isrParams.fxnArgs = (Ptr)GPTIMER_6;
2233         isrParams.intId = OMAP54XX_IRQ_GPT6;
2234         isrParams.sharedInt = FALSE;
2235         ipu_pm_state.gpt6IsrObject =
2236             OsalIsr_create(&ipu_pm_gptimer_interrupt,
2237                            isrParams.fxnArgs, &isrParams);
2238         if(ipu_pm_state.gpt6IsrObject != NULL) {
2239             if (OsalIsr_install(ipu_pm_state.gpt6IsrObject) < 0) {
2240                 retval = -ENOMEM;
2241             }
2242         }
2243         else {
2244             retval = -ENOMEM;
2245         }
2246 #endif
2247     }
2249     if (retval >= 0)
2250         retval = ProcMgr_open(&ipu_pm_state.proc_handles[proc_id], proc_id);
2252     if (retval < 0) {
2253 #ifdef BENELLI_WATCHDOG_TIMER
2254         if (proc_id == MultiProc_getId(CORE0)) {
2255             if (ipu_pm_state.gpt9IsrObject) {
2256                 OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
2257                 OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
2258                 ipu_pm_state.gpt9IsrObject = NULL;
2259             }
2260             ipu_pm_gpt_stop(GPTIMER_9);
2261             ipu_pm_gpt_disable(GPTIMER_9);
2262 #ifndef SYSLINK_SYSBIOS_SMP
2263         }
2264         else if (proc_id == MultiProc_getId("CORE1")) {
2265 #endif
2266             if (ipu_pm_state.gpt11IsrObject) {
2267                 OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
2268                 ipu_pm_state.gpt11IsrObject = NULL;
2269             }
2270             ipu_pm_gpt_stop(GPTIMER_11);
2271             ipu_pm_gpt_disable(GPTIMER_11);
2272         }
2273         else if (proc_id == MultiProc_getId("DSP")) {
2274             if (ipu_pm_state.gpt6IsrObject) {
2275                 OsalIsr_uninstall(ipu_pm_state.gpt6IsrObject);
2276                 OsalIsr_delete(&ipu_pm_state.gpt6IsrObject);
2277                 ipu_pm_state.gpt6IsrObject = NULL;
2278             }
2279             ipu_pm_gpt_stop(GPTIMER_6);
2280             ipu_pm_gpt_disable(GPTIMER_6);
2281         }
2282 #endif
2284     }
2285     else {
2286         ipu_pm_state.attached[proc_id] = TRUE;
2287     }
2289     return retval;
2292 int ipu_pm_detach(int proc_id)
2294     int retval = EOK;
2296     if (proc_id > MultiProc_MAXPROCESSORS) {
2297         return -EINVAL;
2298     }
2300     ipu_pm_state.attached[proc_id] = FALSE;
2302 #ifdef BENELLI_SELF_HIBERNATION
2303     if (core0Idle != NULL) {
2304         munmap_device_io(ROUND_DOWN((uint32_t)core0Idle, 0x1000),
2305                          0x1000);
2306         core0Idle = NULL;
2307         core1Idle = NULL;
2308     }
2309 #endif
2311     if (proc_id == MultiProc_getId(CORE0)) {
2312 #ifdef BENELLI_WATCHDOG_TIMER
2313         OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
2314         OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
2315         ipu_pm_state.gpt9IsrObject = NULL;
2316         ipu_pm_gpt_stop(GPTIMER_9);
2317         ipu_pm_gpt_disable(GPTIMER_9);
2318 #endif
2319         ipu_pm_state.loaded_procs &= ~CORE0_LOADED;
2320 #ifndef SYSLINK_SYSBIOS_SMP
2321     }
2322     else if (proc_id == MultiProc_getId("CORE1")) {
2323 #endif
2324 #ifdef BENELLI_WATCHDOG_TIMER
2325         OsalIsr_uninstall(ipu_pm_state.gpt11IsrObject);
2326         OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
2327         ipu_pm_state.gpt11IsrObject = NULL;
2328         ipu_pm_gpt_stop(GPTIMER_11);
2329         ipu_pm_gpt_disable(GPTIMER_11);
2330 #endif
2331         ipu_pm_state.loaded_procs &= ~CORE1_LOADED;
2332     }
2333     else if (proc_id == MultiProc_getId("DSP")) {
2334 #ifdef BENELLI_WATCHDOG_TIMER
2335         OsalIsr_uninstall(ipu_pm_state.gpt6IsrObject);
2336         OsalIsr_delete(&ipu_pm_state.gpt6IsrObject);
2337         ipu_pm_state.gpt6IsrObject = NULL;
2338         ipu_pm_gpt_stop(GPTIMER_6);
2339         ipu_pm_gpt_disable(GPTIMER_6);
2340 #endif
2341         ipu_pm_state.loaded_procs &= ~DSP_LOADED;
2342     }
2344     if (ipu_pm_state.proc_handles[proc_id]) {
2345         ProcMgr_close(&ipu_pm_state.proc_handles[proc_id]);
2346         ipu_pm_state.proc_handles[proc_id] = NULL;
2347     }
2349     return retval;
2352 int ipu_pm_setup(ipu_pm_config *cfg)
2354     int retval = EOK;
2355     int i = 0;
2356 #ifdef BENELLI_SELF_HIBERNATION
2357     struct sigevent signal_event;
2358 #endif
2360     if (ipu_pm_state.is_setup == false) {
2361         pthread_mutex_init(&ipu_pm_state.mtx, NULL);
2363         if (cfg == NULL) {
2364             retval = -EINVAL;
2365             goto exit;
2366         }
2367         if (cfg->num_procs > MultiProc_MAXPROCESSORS) {
2368             retval = -EINVAL;
2369             goto exit;
2370         }
2372         memcpy(&ipu_pm_state.cfg, cfg, sizeof(ipu_pm_config));
2374 #ifdef BENELLI_SELF_HIBERNATION
2375         /* MBOX flag to check if there are pending messages */
2376         a9_m3_mbox = (void *)mmap_device_io(0x1000, A9_M3_MBOX);
2377         if ((uintptr_t)a9_m3_mbox == MAP_DEVICE_FAILED) {
2378             a9_m3_mbox = NULL;
2379             retval = -ENOMEM;
2380             goto exit;
2381         }
2383         if (syslink_hib_enable) {
2384             SIGEV_THREAD_INIT (&signal_event, ipu_pm_timer_interrupt, NULL,
2385                                NULL);
2386             retval = timer_create(CLOCK_REALTIME, &signal_event,
2387                                   &ipu_pm_state.hibernation_timer);
2388             if (retval < 0) {
2389                 retval = -errno;
2390                 goto exit;
2391             }
2392         }
2393 #endif
2395         cm2_base_va = (void *)mmap_device_io(CM2_SIZE, CM2_BASE);
2396         if ((uintptr_t)cm2_base_va == MAP_DEVICE_FAILED) {
2397             cm2_base_va = NULL;
2398             retval = -errno;
2399             goto exit;
2400         }
2401 #ifdef BENELLI_SELF_HIBERNATION
2402         m3_clkstctrl = cm2_base_va + CM_MPU_M3_CLKCTRL_OFFSET;
2403 #endif
2405         prm_base_va = (void *)mmap_device_io(PRM_SIZE, PRM_BASE);
2406         if ((uintptr_t)prm_base_va == MAP_DEVICE_FAILED) {
2407             prm_base_va = NULL;
2408             retval = -errno;
2409             goto exit;
2410         }
2412         cm_core_aon_base_va = (void*)mmap_device_io(CM_CORE_AON_SIZE, CM_CORE_AON_BASE);
2413         if((uintptr_t)cm_core_aon_base_va == MAP_DEVICE_FAILED) {
2414             cm_core_aon_base_va = NULL;
2415             retval = -errno;
2416             goto exit;
2417         }
2419         map_gpt_regs();
2420 #ifdef QNX_PM_ENABLE
2421         ipu_pm_powman_init();
2422         ipu_pm_power_init();
2423 #endif
2424         for (i = 0; i < NUM_CAM_MODES; i++)
2425             last_camera_req[i] = 0;
2426         last_led_req = 0;
2428         ipu_pm_state.is_setup = true;
2429     }
2431 exit:
2432     if (retval != EOK) {
2433         unmap_gpt_regs();
2434         if (prm_base_va) {
2435             munmap(prm_base_va, PRM_SIZE);
2436             prm_base_va = NULL;
2437         }
2438         if (cm2_base_va) {
2439             munmap(cm2_base_va, CM2_SIZE);
2440             cm2_base_va = NULL;
2441         }
2442 #ifdef BENELLI_SELF_HIBERNATION
2443         m3_clkstctrl = NULL;
2445         if (a9_m3_mbox) {
2446             munmap(a9_m3_mbox, 0x1000);
2447             a9_m3_mbox = NULL;
2448         }
2449 #endif
2450         ipu_pm_state.loaded_procs = 0;
2451         pthread_mutex_destroy(&ipu_pm_state.mtx);
2452     }
2453     return retval;
2456 int ipu_pm_destroy()
2458     int i = 0;
2460     if (ipu_pm_state.is_setup) {
2461         for (i = 0; i < NUM_CAM_MODES; i++) {
2462             if (last_camera_req[i])
2463                 ipu_pm_camera_enable(i, 0);
2464         }
2465         if (last_led_req)
2466             ipu_pm_led_enable(0, 0);
2468 #ifdef QNX_PM_ENABLE
2469         ipu_pm_power_deinit();
2470         ipu_pm_powman_deinit();
2471 #endif
2473         unmap_gpt_regs();
2474 #ifdef BENELLI_SELF_HIBERNATION
2475         if (syslink_hib_enable) {
2476             /*Stop the Timer*/
2477             configure_timer(0, 0);
2478             /* Delete the timer */
2479             timer_delete(ipu_pm_state.hibernation_timer);
2480         }
2481         if (a9_m3_mbox) {
2482             munmap(a9_m3_mbox, 0x1000);
2483             a9_m3_mbox = NULL;
2484         }
2485         m3_clkstctrl = NULL;
2486 #endif
2487         if (cm2_base_va) {
2488             munmap(cm2_base_va, CM2_SIZE);
2489             cm2_base_va = NULL;
2490         }
2491         if (prm_base_va) {
2492             munmap(prm_base_va, PRM_SIZE);
2493             prm_base_va = NULL;
2494         }
2495         pthread_mutex_destroy(&ipu_pm_state.mtx);
2496         ipu_pm_state.proc_state = 0;
2497         ipu_pm_state.loaded_procs = 0;
2498         ipu_pm_state.ivahd_use_cnt = 0;
2499         ipu_pm_state.is_setup = false;
2500     }
2501     return EOK;