]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/ipc3x_dev/ti/syslink/rpmsg-resmgr/hlos/knl/Qnx/family/omap4430/ipu_pm.c
Moved files from the ipc3x_dev branch in syslink_qnx repository into direct
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / rpmsg-resmgr / hlos / knl / Qnx / family / omap4430 / ipu_pm.c
1 /*
2  *  @file       ipu_pm.c
3  *
4  *  @brief      power management for remote processors.
5  *
6  *  ============================================================================
7  *
8  *  Copyright (c) 2011, Texas Instruments Incorporated
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *  *  Redistributions of source code must retain the above copyright
15  *     notice, this list of conditions and the following disclaimer.
16  *
17  *  *  Redistributions in binary form must reproduce the above copyright
18  *     notice, this list of conditions and the following disclaimer in the
19  *     documentation and/or other materials provided with the distribution.
20  *
21  *  *  Neither the name of Texas Instruments Incorporated nor the names of
22  *     its contributors may be used to endorse or promote products derived
23  *     from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *  Contact information for paper mail:
37  *  Texas Instruments
38  *  Post Office Box 655303
39  *  Dallas, Texas 75265
40  *  Contact information:
41  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
42  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
43  *  ============================================================================
44  *
45  */
47 /* Standard headers */
48 #include <ti/syslink/Std.h>
50 /*QNX specific header include */
51 #include <errno.h>
52 #include <unistd.h>
53 #include <sys/iofunc.h>
54 #include <sys/dispatch.h>
55 #include <sys/netmgr.h>
56 #include <sys/rsrcdbmgr.h>
57 #include <sys/rsrcdbmsg.h>
58 #define QNX_PM_ENABLE
59 #ifdef QNX_PM_ENABLE
60 #include <sys/powman.h>
61 #include <cpu_dll_msg.h>
62 #endif
64 /* Module headers */
65 #include <ipu_pm.h>
66 #include <_ipu_pm.h>
67 #include <sys/mman.h>
68 #include <hw/inout.h>
69 #include <time.h>
70 #include <sys/siginfo.h>
71 #include <stdbool.h>
72 #include <ti/ipc/MultiProc.h>
73 #include <ti/syslink/ProcMgr.h>
74 #include <OMAP4430DucatiProc.h>
75 #include <ArchIpcInt.h>
76 #include <_Omap4430IpcInt.h>
77 #include <rpmsg-resmgrdrv.h>
79 #include <OMAP4430DucatiHalReset.h>
80 #include <OMAP4430DucatiEnabler.h>
82 #include <camera/camdrv.h>
83 #include <Omap4430IpcInt.h>
84 #include <ti/syslink/utils/OsalPrint.h>
85 #include <rprcfmt.h>
86 #include <Bitops.h>
87 #include <_rpmsg.h>
89 /* Defines the ipu_pm state object, which contains all the module
90  * specific information. */
91 struct ipu_pm_module_object {
92     atomic_t ref_count;
93     /* Reference count */
94     ipu_pm_config cfg;
95     /* Module configuration */
96     pthread_mutex_t mtx;
97     /* Handle of gate to be used for local thread safety */
98     int ivahd_use_cnt;
99     /* Count of ivahd users */
100     int ivaseq0_use_cnt;
101     /* Count of ivaseq0 users */
102     int ivaseq1_use_cnt;
103     /* Count of ivaseq1 users */
104     ProcMgr_Handle proc_handles[MultiProc_MAXPROCESSORS];
105     /* Array of processor handles */
106     uint32_t loaded_procs;
107     /* Info on which procs are loaded */
108     uint32_t proc_state;
109     /* Current state of the remote procs */
110     timer_t hibernation_timer;
111     /* Timer used for hibernation */
112     int hib_timer_state;
113     /* State of the hibernation timer */
114     OsalIsr_Handle gpt9IsrObject;
115     /* ISR handle for gpt9 WDT */
116     OsalIsr_Handle gpt11IsrObject;
117     /* ISR handle for gpt11 WDT */
118     bool attached[MultiProc_MAXPROCESSORS];
119     /* Indicates whether the ipu_pm module is attached. */
120     bool is_setup;
121     /* Indicates whether the ipu_pm module is setup. */
122 };
124 static struct ipu_pm_module_object ipu_pm_state = {
125     .ivahd_use_cnt = 0,
126     .loaded_procs = 0,
127     .proc_state = 0,
128 } ;
130 /*******************************************************************************
131 *   Lenth of Boot code
132 *******************************************************************************/
133 #define LENGTH_BOOT_CODE1  14
135 /*******************************************************************************
136 *   Hex code to set for Stack setting, Interrupt vector setting
137 *   and instruction to put ICONT in WFI mode.
138 *   This shall be placed at TCM_BASE_ADDRESS of given IVAHD, which is
139 *   0x0000 locally after reset.
140 *******************************************************************************/
142 const unsigned int IVAHD_memory_wfi1[LENGTH_BOOT_CODE1] = {
143 0xEA000006,
144 0xEAFFFFFE,
145 0xEAFFFFFE,
146 0xEAFFFFFE,
147 0xEAFFFFFE,
148 0xEAFFFFFE,
149 0xEAFFFFFE,
150 0xEAFFFFFE,
151 0xE3A00000,
152 0xEE070F9A,
153 0xEE070F90,
154 0xE3A00000,
155 0xEAFFFFFE,
156 0xEAFFFFF1
157 };
159 enum processor_version {
160     OMAP_4430 = 0,
161     OMAP_4460,
162     OMAP_4470,
163     ERROR_CONTROL_ID = -1,
164     INVALID_SI_VERSION = -2
165 };
167 extern Bool syslink_hib_enable;
168 extern uint32_t syslink_hib_timeout;
169 extern Bool syslink_hib_hibernating;
170 extern pthread_mutex_t syslink_hib_mutex;
171 extern pthread_cond_t syslink_hib_cond;
173 #define DUCATI_SELF_HIBERNATION
174 #define DUCATI_WATCHDOG_TIMER
176 /* A9 state flag 0000 | 0000 Ducati internal use*/
177 #define CORE0_PROC_DOWN        0x00010000
178 #define CORE1_PROC_DOWN        0x00020000
180 #define CORE0_LOADED 0x1
181 #define CORE1_LOADED 0x2
182 #define DSP_LOADED   0x4
184 #ifdef DUCATI_SELF_HIBERNATION
185 /* A9-M3 mbox status */
186 #define A9_M3_MBOX 0x4A0F4000
187 #define MBOX_MESSAGE_STATUS 0x000000CC
189 /* Flag provided by BIOS */
190 #define IDLE_FLAG_DUCATI_ADDR_MAP_BASE 0x9F0F0000
191 #define IDLE_FLAG_PHY_ADDR_OFFSET   0x2D8
193 /* BIOS flags states for each core in IPU */
194 static void *core0Idle = NULL;
195 static void *core1Idle = NULL;
196 static void *a9_m3_mbox = NULL;
197 static void *m3_clkstctrl = NULL;
199 #define NUM_IDLE_CORES ((in32((uintptr_t)core1Idle) << 1) + \
200                         (in32((uintptr_t)core0Idle)))
201 #define PENDING_MBOX_MSG in32((uintptr_t)a9_m3_mbox + MBOX_MESSAGE_STATUS)
203 extern Bool rpmsg_resmgr_allow_hib (UInt16 proc_id);
204 #endif
206 #ifdef QNX_PM_ENABLE
207 static struct powauth *syslink_auth_active = NULL;
208 static struct powauth *syslink_auth_oswr = NULL;
210 enum {core_active, core_inactive, core_off};
211 static int ipu_pm_powman_init(void);
212 static void tell_powman_auth_oswr(int need);
213 static BOOL oswr_prevent = FALSE;
215 #endif
217 typedef struct GPTIMER_REGS {
218     uint32_t tidr;
219     uint32_t space[3];
220     uint32_t tiocp_cfg;
221     uint32_t space1[3];
222     uint32_t reserved;
223     uint32_t irqstatus_raw;
224     uint32_t irqstatus;
225     uint32_t irqenable_set;
226     uint32_t irqenable_clr;
227     uint32_t irqwakeen;
228     uint32_t tclr;
229     uint32_t tcrr;
230     uint32_t tldr;
231     uint32_t ttgr;
232     uint32_t twps;
233     uint32_t tmar;
234     uint32_t tcar1;
235     uint32_t tsicr;
236     uint32_t tcar2;
237 } GPTIMER_REGS;
239 #define OMAP44XX_IRQ_GPT9 77
240 #define OMAP44XX_IRQ_GPT11 79
242 #define GPTIMER3_BASE        0x48034000
243 #define GPTIMER4_BASE        0x48036000
244 #define GPTIMER9_BASE        0x4803E000
245 #define GPTIMER11_BASE       0x48088000
247 static void *GPT3Base = 0;
248 static void *GPT3ClkCtrl =0;
249 static bool GPT3Saved = FALSE;
250 static bool GPT3InUse = FALSE;
251 static void *GPT4Base = 0;
252 static void *GPT4ClkCtrl =0;
253 static bool GPT4Saved = FALSE;
254 static bool GPT4InUse = FALSE;
255 static void *GPT9Base = 0;
256 static void *GPT9ClkCtrl =0;
257 static bool GPT9Saved = FALSE;
258 static bool GPT9InUse = FALSE;
259 static void *GPT11Base = 0;
260 static void *GPT11ClkCtrl =0;
261 static bool GPT11Saved = FALSE;
262 static bool GPT11InUse = FALSE;
264 static GPTIMER_REGS GPT3Reg_saved;
265 static GPTIMER_REGS GPT4Reg_saved;
266 static GPTIMER_REGS GPT9Reg_saved;
267 static GPTIMER_REGS GPT11Reg_saved;
269 static void *prm_base_va = NULL;
270 static void *cm2_base_va = NULL;
272 #define MAX_DUCATI_CHANNELS   4
273 #define DUCATI_CHANNEL_START 25
274 #define DUCATI_CHANNEL_END   28
275 static bool DMAAllocation = false;
276 static rsrc_request_t sdma_req;
278 // Note, the number of camera modes is tied to enum campower_mode_t, which can
279 // be found in camera/camdrv.h
280 #define NUM_CAM_MODES 3
281 static unsigned last_camera_req[NUM_CAM_MODES];
282 static unsigned last_led_req = 0;
284 #define PRM_SIZE                    0x2000
285 #define PRM_BASE                    0x4A306000
286 #define PRM_CM_SYS_CLKSEL_OFFSET    0x110
287 #define PM_IVAHD_PWRSTCTRL_OFFSET   0xF00
288 #define PM_IVAHD_PWRST_OFFSET       0xF04
289 #define RM_IVAHD_RSTCTRL_OFFSET     0xF10
290 #define RM_IVAHD_IVAHD_CONTEXT_OFFSET   0xF24
292 #define CM2_SIZE                        0x2000
293 #define CM2_BASE                        0x4A008000
294 #define CM_L3_2_L3_2_CLKCTRL_OFFSET     0x820
295 #define CM_MPU_M3_CLKCTRL_OFFSET        0x900
296 #define CM_IVAHD_CLKSTCTRL_OFFSET       0xF00
297 #define CM_IVAHD_IVAHD_CLKCTRL_OFFSET   0xF20
298 #define CM_IVAHD_SL2_CLKCTRL_OFFSET     0xF28
299 #define CM_L4PER_GPTIMER3_CLKCTRL_OFFSET  0x1440
300 #define CM_L4PER_GPTIMER4_CLKCTRL_OFFSET  0x1448
301 #define CM_L4PER_GPTIMER9_CLKCTRL_OFFSET  0x1450
302 #define CM_L4PER_GPTIMER11_CLKCTRL_OFFSET 0x1430
304 #define ID_CODE_BASE   0x4A002000
305 #define ID_CODE_OFFSET 0x204
307 #define OMAP4430_ES1_2   0xB852
308 #define OMAP4430_ES21_22 0xB95C
309 #define OMAP4460_ES1_11  0xB94E
310 #define OMAP4470_ES1     0xB975
311 #define COREOPP100 1000000
313 static dvfsMsg_t dvfsMessage;
314 static int cpudll_coid = -1;
315 static reply_getListOfDomainOPPs_t cpudll_iva_opp = { {0} };  /* for result of getDomainOPP (IVA)*/
316 static reply_getListOfDomainOPPs_t cpudll_core_opp = { {0} };  /* for result of getDomainOPP (CORE)*/
318 enum processor_version get_omap_version (void)
320     uintptr_t id_code_base = NULL;
321     enum processor_version omap_rev;
322     uint32_t reg;
324     id_code_base = mmap_device_io(0x1000, ID_CODE_BASE);
325     if (id_code_base == MAP_DEVICE_FAILED){
326         GT_setFailureReason (curTrace, GT_4CLASS, "get_omap_version",
327                              ERROR_CONTROL_ID,
328                              "Unable to map ID_CODE register");
329         return ERROR_CONTROL_ID;
330     }
332     reg = in32(id_code_base + ID_CODE_OFFSET);
333     reg &= 0x0FFFF000;
334     reg = reg >> 12;
336     switch (reg) {
337         case OMAP4430_ES1_2:
338         case OMAP4430_ES21_22:
339             omap_rev = OMAP_4430;
340             break;
342         case OMAP4460_ES1_11:
343             omap_rev = OMAP_4460;
344             break;
346         case OMAP4470_ES1:
347             omap_rev = OMAP_4470;
348             break;
350         default:
351             omap_rev = INVALID_SI_VERSION;
352             break;
353     }
355     if (id_code_base)
356         munmap_device_io(id_code_base, 0x1000);
358     return omap_rev;
361 /* Function to Map the required registers for
362 * GPT configuration
363 */
364 int map_gpt_regs(void)
366     int retval = 0;
368     GPT3ClkCtrl = cm2_base_va + CM_L4PER_GPTIMER3_CLKCTRL_OFFSET;
370     GPT3Base = (void *)mmap_device_io(0x1000, GPTIMER3_BASE);
371     if ((uintptr_t)GPT3Base == MAP_DEVICE_FAILED) {
372         retval = -ENOMEM;
373         GPT3Base = NULL;
374         goto exit;
375     }
377     GPT4ClkCtrl = cm2_base_va + CM_L4PER_GPTIMER4_CLKCTRL_OFFSET;
379     GPT4Base = (void *)mmap_device_io(0x1000, GPTIMER4_BASE);
380     if ((uintptr_t)GPT4Base == MAP_DEVICE_FAILED) {
381         retval = -ENOMEM;
382         GPT4Base = NULL;
383         goto exit;
384     }
386     GPT9ClkCtrl = cm2_base_va + CM_L4PER_GPTIMER9_CLKCTRL_OFFSET;
388     GPT9Base = (void *)mmap_device_io(0x1000, GPTIMER9_BASE);
389     if ((uintptr_t)GPT9Base == MAP_DEVICE_FAILED) {
390         retval = -ENOMEM;
391         GPT9Base = NULL;
392         goto exit;
393     }
395     GPT11ClkCtrl = cm2_base_va + CM_L4PER_GPTIMER11_CLKCTRL_OFFSET;
397     GPT11Base = (void *)mmap_device_io(0x1000, GPTIMER11_BASE);
398     if ((uintptr_t)GPT11Base == MAP_DEVICE_FAILED) {
399         retval = -ENOMEM;
400         GPT11Base = NULL;
401         goto exit;
402     }
403     return EOK;
405 exit:
406     GPT11ClkCtrl = NULL;
407     if (GPT9Base) {
408         munmap(GPT9Base, 0x1000);
409         GPT9Base = NULL;
410     }
411     GPT9ClkCtrl = NULL;
412     if (GPT4Base) {
413         munmap(GPT4Base, 0x1000);
414         GPT4Base = NULL;
415     }
416     GPT4ClkCtrl = NULL;
417     if (GPT3Base) {
418         munmap(GPT3Base, 0x1000);
419         GPT3Base = NULL;
420     }
421     GPT3ClkCtrl = NULL;
422     return retval;
425 void unmap_gpt_regs(void)
427     if(GPT11Base != NULL)
428         munmap(GPT11Base, 0x1000);
430     GPT11Base = NULL;
432     GPT11ClkCtrl = NULL;
434     if(GPT9Base != NULL)
435         munmap(GPT9Base, 0x1000);
437     GPT9Base = NULL;
439     GPT9ClkCtrl = NULL;
441     if(GPT4Base != NULL)
442         munmap(GPT4Base, 0x1000);
444     GPT4Base = NULL;
446     GPT4ClkCtrl = NULL;
448     if(GPT3Base != NULL)
449         munmap(GPT3Base, 0x1000);
451     GPT3Base = NULL;
453     GPT3ClkCtrl = NULL;
456 #ifdef DUCATI_WATCHDOG_TIMER
458 /* Interrupt clear function*/
459 static Bool ipu_pm_clr_gptimer_interrupt(Ptr fxnArgs)
461     UINT32 reg;
462     uint32_t num = (uint32_t)fxnArgs;
463     GPTIMER_REGS *GPTRegs = NULL;
465     if (num == GPTIMER_3) {
466         GPTRegs = GPT3Base;
467     }
468     else if (num == GPTIMER_4) {
469         GPTRegs = GPT4Base;
470     }
471     else if (num == GPTIMER_9) {
472         GPTRegs = GPT9Base;
473     }
474     else if (num == GPTIMER_11) {
475         GPTRegs = GPT11Base;
476     }
477     else {
478         return TRUE;
479     }
481     reg = in32((uintptr_t)&GPTRegs->irqstatus);
482     reg |= 0x2;
484     /*Clear Overflow event */
485     out32((uintptr_t)&GPTRegs->irqstatus, reg);
486     reg = in32((uintptr_t)&GPTRegs->irqstatus);
488     /*Always return TRUE for ISR*/
489     return TRUE;
492 /* ISR for GP Timer*/
493 static Bool ipu_pm_gptimer_interrupt(Ptr fxnArgs)
495     int num;
496     uint16_t core0_id = MultiProc_getId("CORE0");
497     uint16_t core1_id = MultiProc_getId("CORE1");
499     switch ((uint32_t)fxnArgs) {
500         case GPTIMER_9:
501             num = 9;
502             ProcMgr_setState(ipu_pm_state.proc_handles[core0_id],
503                              ProcMgr_State_Watchdog);
504             break;
505         case GPTIMER_11:
506             num = 11;
507             ProcMgr_setState(ipu_pm_state.proc_handles[core1_id],
508                              ProcMgr_State_Watchdog);
509             break;
510         default:
511             num = 0;
512             break;
513     }
514     // what to do here?
515     GT_1trace(curTrace, GT_4CLASS,
516               "ipu_pm_gptimer_interrupt: GPTimer %d expired!", num);
518     return 0;
520 #endif
522 int ipu_pm_gpt_enable(int num)
524     GPTIMER_REGS * GPTRegs = NULL;
525     uintptr_t GPTClkCtrl = NULL;
526     int max_tries = 100;
528     if (num == GPTIMER_3) {
529         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
530         GPTRegs = GPT3Base;
531         GPT3InUse = TRUE;
532     }
533     else if (num == GPTIMER_4) {
534         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
535         GPTRegs = GPT4Base;
536         GPT4InUse = TRUE;
537     }
538     else if (num == GPTIMER_9) {
539         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
540         GPTRegs = GPT9Base;
541         GPT9InUse = TRUE;
542     }
543     else if (num == GPTIMER_11) {
544         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
545         GPTRegs = GPT11Base;
546         GPT11InUse = TRUE;
547     }
548     else {
549         return -EINVAL;
550     }
552     /* Enable GPT MODULEMODE and set CLKSEL to SYS_CLK*/
553     out32(GPTClkCtrl, 0x2);
554     do {
555         if (!(in32(GPTClkCtrl) & 0x30000))
556             break;
557     } while (--max_tries);
558     if (max_tries == 0) {
559         ipu_pm_gpt_disable(num);
560         return -EIO;
561     }
563     /* Set Smart-idle wake-up-capable */
564     out32((uintptr_t)&GPTRegs->tiocp_cfg, 0xC);
566     return EOK;
569 int ipu_pm_gpt_disable(int num)
571     uintptr_t GPTClkCtrl = NULL;
572     GPTIMER_REGS *GPTRegs = NULL;
573     UINT32 reg = 0;
575     if (num == GPTIMER_3) {
576         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
577         GPTRegs = GPT3Base;
578         GPT3InUse = FALSE;
579     }
580     else if (num == GPTIMER_4) {
581         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
582         GPTRegs = GPT4Base;
583         GPT4InUse = FALSE;
584     }
585     else if (num == GPTIMER_9) {
586         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
587         GPTRegs = GPT9Base;
588         GPT9InUse = FALSE;
589     }
590     else if (num == GPTIMER_11) {
591         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
592         GPTRegs = GPT11Base;
593         GPT11InUse = FALSE;
594     }
595     else {
596         return -EINVAL;
597     }
599     /*Check if Clock is Enabled*/
600     reg = in32(GPTClkCtrl);
601     if ((reg & 0x3) == 0x2) {
602         /* Clear any pending interrupt to allow idle */
603         reg = in32((uintptr_t)&GPTRegs->irqstatus);
604         if (reg) {
605             out32((uintptr_t)&GPTRegs->irqstatus, reg);
606         }
608         /*Disable the Timer*/
609         reg = in32(GPTClkCtrl);
610         reg &= 0xFFFFFFFC;
611         out32(GPTClkCtrl, reg);
612     }
613     else {
614         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_disable", -EINVAL,
615                             "gpt clock is not enabled!");
616         return -EINVAL;
617     }
618     return EOK;
621 int ipu_pm_gpt_start (int num)
623     GPTIMER_REGS * GPTRegs = NULL;
624     uint32_t reg = 0;
626     if (num == GPTIMER_3) {
627         GPTRegs = GPT3Base;
628     }
629     else if (num == GPTIMER_4) {
630         GPTRegs = GPT4Base;
631     }
632     else if (num == GPTIMER_9) {
633         GPTRegs = GPT9Base;
634     }
635     else if (num == GPTIMER_11) {
636         GPTRegs = GPT11Base;
637     }
638     else {
639         return -EINVAL;
640     }
642     /*Start the Timer*/
643     reg = in32((uintptr_t)&GPTRegs->tclr);
644     reg |=0x1;
645     out32((uintptr_t)&GPTRegs->tclr, reg);
647     return EOK;
650 int ipu_pm_gpt_stop(int num)
652     uintptr_t GPTClkCtrl = NULL;
653     GPTIMER_REGS * GPTRegs = NULL;
654     uint32_t reg = 0;
656     if (num == GPTIMER_3) {
657         GPTClkCtrl = (uintptr_t)GPT3ClkCtrl;
658         GPTRegs = GPT3Base;
659     }
660     else if (num == GPTIMER_4) {
661         GPTClkCtrl = (uintptr_t)GPT4ClkCtrl;
662         GPTRegs = GPT4Base;
663     }
664     else if (num == GPTIMER_9) {
665         GPTClkCtrl = (uintptr_t)GPT9ClkCtrl;
666         GPTRegs = GPT9Base;
667     }
668     else if (num == GPTIMER_11) {
669         GPTClkCtrl = (uintptr_t)GPT11ClkCtrl;
670         GPTRegs = GPT11Base;
671     }
672     else {
673         return -EINVAL;
674     }
676     /*Check if Clock is Enabled*/
677     reg = in32(GPTClkCtrl);
678     if ((reg & 0x3) == 0x2) {
680         /*Stop the Timer*/
681         reg = in32((uintptr_t)&GPTRegs->tclr);
682         reg &=0xFFFFFFFE;
683         out32((uintptr_t)&GPTRegs->tclr, reg);
684     }
685     else {
686         GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_gpt_stop", -EINVAL,
687                             "gpt clock is not enabled!");
688         return -EINVAL;
689     };
691     return EOK;
694 void save_gpt_context(int num)
696     GPTIMER_REGS *GPTRegs = NULL;
697     GPTIMER_REGS *GPTSaved = NULL;
698     bool *GPTRestore = NULL;
700     if (num == GPTIMER_3) {
701         GPTRegs = GPT3Base;
702         GPTSaved = &GPT3Reg_saved;
703         GPTRestore = &GPT3Saved;
704     }
705     else if (num == GPTIMER_4) {
706         GPTRegs = GPT4Base;
707         GPTSaved = &GPT4Reg_saved;
708         GPTRestore = &GPT4Saved;
709     }
710     else if (num == GPTIMER_9) {
711         GPTRegs = GPT9Base;
712         GPTSaved = &GPT9Reg_saved;
713         GPTRestore = &GPT9Saved;
714     }
715     else if (num == GPTIMER_11) {
716         GPTRegs = GPT11Base;
717         GPTSaved = &GPT11Reg_saved;
718         GPTRestore = &GPT11Saved;
719     }
720     else {
721         return;
722     }
724     GPTSaved->tiocp_cfg = in32((uintptr_t)&GPTRegs->tiocp_cfg);
725     GPTSaved->tcrr = in32((uintptr_t)&GPTRegs->tcrr);
726     GPTSaved->irqenable_set = in32((uintptr_t)&GPTRegs->irqenable_set);
727     GPTSaved->irqstatus_raw = in32((uintptr_t)&GPTRegs->irqstatus_raw);
728     GPTSaved->irqstatus = in32((uintptr_t)&GPTRegs->irqstatus);
729     GPTSaved->irqwakeen = in32((uintptr_t)&GPTRegs->irqwakeen);
730     GPTSaved->tclr = in32((uintptr_t)&GPTRegs->tclr);
731     GPTSaved->tldr = in32((uintptr_t)&GPTRegs->tldr);
732     GPTSaved->ttgr = in32((uintptr_t)&GPTRegs->ttgr);
733     GPTSaved->tmar = in32((uintptr_t)&GPTRegs->tmar);
734     GPTSaved->tsicr = in32((uintptr_t)&GPTRegs->tsicr);
735     *GPTRestore = TRUE;
738 void restore_gpt_context(int num)
740     GPTIMER_REGS *GPTRegs = NULL;
741     GPTIMER_REGS *GPTSaved = NULL;
742     bool *GPTRestore = NULL;
744     if (num == GPTIMER_3) {
745         GPTRegs = GPT3Base;
746         GPTSaved = &GPT3Reg_saved;
747         GPTRestore = &GPT3Saved;
748     }
749     else if (num == GPTIMER_4) {
750         GPTRegs = GPT4Base;
751         GPTSaved = &GPT4Reg_saved;
752         GPTRestore = &GPT4Saved;
753     }
754     else if (num == GPTIMER_9) {
755         GPTRegs = GPT9Base;
756         GPTSaved = &GPT9Reg_saved;
757         GPTRestore = &GPT9Saved;
758     }
759     else if (num == GPTIMER_11) {
760         GPTRegs = GPT11Base;
761         GPTSaved = &GPT11Reg_saved;
762         GPTRestore = &GPT11Saved;
763     }
764     else {
765         return;
766     }
768     if (*GPTRestore) {
769         *GPTRestore = FALSE;
770         out32((uintptr_t)&GPTRegs->tiocp_cfg, GPTSaved->tiocp_cfg);
771         out32((uintptr_t)&GPTRegs->irqenable_set, GPTSaved->irqenable_set);
772         out32((uintptr_t)&GPTRegs->tcrr, GPTSaved->tcrr);
773         out32((uintptr_t)&GPTRegs->irqstatus_raw, GPTSaved->irqstatus_raw);
774         out32((uintptr_t)&GPTRegs->irqstatus, GPTSaved->irqstatus);
775         out32((uintptr_t)&GPTRegs->irqwakeen, GPTSaved->irqwakeen);
776         out32((uintptr_t)&GPTRegs->tclr, GPTSaved->tclr);
777         out32((uintptr_t)&GPTRegs->tldr, GPTSaved->tldr);
778         out32((uintptr_t)&GPTRegs->ttgr, GPTSaved->ttgr);
779         out32((uintptr_t)&GPTRegs->tmar, GPTSaved->tmar);
780         out32((uintptr_t)&GPTRegs->tsicr, GPTSaved->tsicr);
781     }
784 int ipu_pm_ivahd_standby_power_on_uboot()
786     unsigned int length =0;
787     volatile unsigned int *icont1_itcm_base_addr = NULL;
788     volatile unsigned int *icont2_itcm_base_addr = NULL;
789     /*--------------------------------------------------------------------------*/
790     /* Assigment of pointers                                                    */
791     /* A generic code shall take all address as input parameters                */
792     /*--------------------------------------------------------------------------*/
793     icont1_itcm_base_addr = (unsigned int *)mmap_device_io(0x1000, (L3_IVAHD_CONFIG+0x08000));
794     GT_1trace(curTrace, GT_4CLASS, "###icont1_itcm_base_addr= %u", icont1_itcm_base_addr);
795     icont2_itcm_base_addr = (unsigned int *)mmap_device_io(0x1000, (L3_IVAHD_CONFIG+0x18000));
796     GT_1trace(curTrace, GT_4CLASS, "###icont1_itcm_base_addr= %u", icont2_itcm_base_addr);
797     if((uintptr_t)icont1_itcm_base_addr == MAP_DEVICE_FAILED ||
798         (uintptr_t)icont2_itcm_base_addr == MAP_DEVICE_FAILED){
799         GT_0trace(curTrace, GT_4CLASS, "mapping l3 ivahdconfig failed");
800         if((uintptr_t)icont1_itcm_base_addr != MAP_DEVICE_FAILED )
801             munmap((void *)icont1_itcm_base_addr, 0x1000);
802         if((uintptr_t)icont2_itcm_base_addr != MAP_DEVICE_FAILED )
803             munmap((void *)icont2_itcm_base_addr, 0x1000);
804         return -1;
805     }
807     /*--------------------------------------------------------------------------*/
808     /* Copy boot code to ICONT1 & INCOT2 memory                                 */
809     /*--------------------------------------------------------------------------*/
810     GT_0trace(curTrace, GT_4CLASS, "###LOAD BOOT CODE");
812     for (length=0; length<LENGTH_BOOT_CODE1; length++) {
813         icont1_itcm_base_addr[length] = IVAHD_memory_wfi1[length];
814         icont2_itcm_base_addr[length] = IVAHD_memory_wfi1[length];
815     }
817     /*--------------------------------------------------------------------------*/
818     /* As ICONT goes in WFI and there are no pending VDMA transction            */
819     /* entire IVAHD will be go in standby mode and PRCM will fully control      */
820     /* further managment of IVAHD power state                                   */
821     /*--------------------------------------------------------------------------*/
822     munmap((void *)icont1_itcm_base_addr, 0x1000);
823     munmap((void *)icont2_itcm_base_addr, 0x1000);
825     return 0;
828 int ipu_pm_ivaseq0_disable()
830     return EOK;
833 int ipu_pm_ivaseq0_enable()
835     return EOK;
838 int ipu_pm_ivaseq1_disable()
840     return EOK;
843 int ipu_pm_ivaseq1_enable()
845     return EOK;
848 int ipu_pm_ivahd_disable()
850     uintptr_t pm_base = 0;
851     uintptr_t cm_base = 0;
852     uint32_t reg = 0;
853     int max_tries = 100;
855     pthread_mutex_lock(&ipu_pm_state.mtx);
857     if (ipu_pm_state.ivahd_use_cnt-- == 1) {
858         pm_base = (uintptr_t)prm_base_va;
859         cm_base = (uintptr_t)cm2_base_va;
861         reg = in32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET);
862         reg &= 0xFFFFFFFC;
863         reg |= 0x00000002;
864         out32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET, reg);
866         /* Ensure that the wake up mode is set to SW_WAKEUP */
867         out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, 0x00000002);
869         /* Check the standby status */
870         do {
871             if (((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x00040000) != 0x0))
872                 break;
873         } while (--max_tries);
874         if (max_tries == 0) {
875             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
876         }
878         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
879         out32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET, 0x00000000);
880         max_tries = 100;
881         do {
882             if((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x00030000) == 0x30000)
883                 break;
884         } while (--max_tries);
885         if (max_tries == 0) {
886            GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD standby status");
887         }
889         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
890         out32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET, 0x00000000);
891         max_tries = 100;
892         do {
893             if((in32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET) & 0x00030000) == 0x30000);
894                 break;
895         } while (--max_tries);
896         if (max_tries == 0) {
897             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 CLKCTRL");
898         }
900         /* put IVA into HW Auto mode */
901         reg = in32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET);
902         reg |= 0x00000003;
903         out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, reg);
905         max_tries = 100;
906         /* Check CLK ACTIVITY bit */
907         while(((in32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET) & 0x00000100) != 0x0) && --max_tries);
908         if (max_tries == 0)
909             GT_0trace(curTrace, GT_4CLASS, "SYSLINK: ivahd_disable: WARNING - CLK ACTIVITY bit did not go off");
911         /* Modifying the previous reset sequence - the new reset sequence asserts reset on
912          * SL2/IVAHD first, wait for 1 usec and then assert reset for ICONT1 and
913          * then for ICONT2 */
914         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
915         reg |= 0x4;
916         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
917         usleep(1);
918         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
919         reg |= 0x1;
920         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
921         usleep(1);
922         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
923         reg |= 0x2;
924         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
925     }
926     else {
927         GT_0trace(curTrace, GT_3CLASS, "ivahd still in use");
928     }
930     pthread_mutex_unlock(&ipu_pm_state.mtx);
931     return EOK;
934 int ipu_pm_ivahd_enable()
936     uintptr_t pm_base = 0;
937     uintptr_t cm_base = 0;
938     uint32_t reg = 0;
939     unsigned int pwrst = 0;
940     int max_tries = 0;
941     int flag = 0;
943     pthread_mutex_lock(&ipu_pm_state.mtx);
945     if (++ipu_pm_state.ivahd_use_cnt == 1) {
946         pm_base = (uintptr_t)prm_base_va;
947         cm_base = (uintptr_t)cm2_base_va;
949         /* Read the IVAHD Context register to check if the memory content has been lost */
950         reg = in32(pm_base + RM_IVAHD_IVAHD_CONTEXT_OFFSET);
951         /* Clear the context register by writing 1 to bit 8,9 and 10 */
952         out32(pm_base + RM_IVAHD_IVAHD_CONTEXT_OFFSET, 0x700);
954         /*Display power state*/
955         pwrst = in32(pm_base + PM_IVAHD_PWRST_OFFSET);
956         GT_1trace(curTrace, GT_4CLASS, "###: off state reg bit = 0x%x\n", (pwrst & 0x03000003));
957         /*Clear the pwer status reg by writting 1'a into the requred bits*/
958         out32(pm_base + PM_IVAHD_PWRST_OFFSET, 0x03000000);
960         /* Ensure power state is set to ON */
961         reg = in32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET);
962         reg &= 0xFFFFFFFC;
963         reg |= 0x00000003;
964         out32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET, reg);
966         // IVAHD_CM2:CM_IVAHD_IVAHD_CLKCTRL
967         out32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET, 0x00000001);
969         // IVAHD_CM2:CM_IVAHD_SL2_CLKCTRL
970         out32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET, 0x00000001);
972         /* Ensure that the wake up mode is set to SW_WAKEUP */
973         out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, 0x00000002);
974         if((pwrst & 0x03000000) == 0x00000000){
975             /* Wait until the CLK_ACTIVITY bit is set */
976             max_tries = 3;
977             while(max_tries--){
978                 if(((in32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET)) & 0x00000100) != 0x0){
979                     flag = 1;
980                     break;
981                 }
982                 usleep(100);
983             }
984         }
986         /* Release ICONT1 and SL2/IVAHD first, wait for few usec  then release ICONT2 */
987         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
988         reg &= 0xFFFFFFFB;
989         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
990         if(flag){
991             GT_0trace(curTrace, GT_4CLASS, "@@@ - CLK_ACTIVITY set");
992             GT_0trace(curTrace, GT_4CLASS, "$$ call LOAD CODE");
993             if(-1 == ipu_pm_ivahd_standby_power_on_uboot())
994                 GT_0trace(curTrace, GT_4CLASS, "$$ LOAD CODE FAILED");
995         }
996         else
997             GT_0trace(curTrace, GT_4CLASS, "@@@ - CLK_ACTIVITY Not set");
999         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
1000         reg &= 0xFFFFFFFE;
1001         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
1002         usleep(200);
1003         reg = in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET);
1004         reg &= 0xFFFFFFFD;
1005         out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, reg);
1006         max_tries = 100;
1007         do {
1008             if((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x00030000) == 0x0)
1009                 break;
1010         } while(--max_tries);
1011         if (max_tries == 0) {
1012             GT_0trace(curTrace, GT_4CLASS," ** Error in IVAHD clk control");
1013             return -EIO;
1014         }
1016         max_tries = 100;
1017         do {
1018             if((in32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET) & 0x00030000) == 0x00000)
1019                 break;
1020         } while(--max_tries);
1021         if (max_tries == 0) {
1022             GT_0trace(curTrace, GT_4CLASS," ** Error in SL2 clk control");
1023             return -EIO;
1024         }
1026         max_tries = 100;
1027         do {
1028             if((in32(cm_base + CM_L3_2_L3_2_CLKCTRL_OFFSET) & 0x30001) == 0x00001)
1029                 break;
1030         } while(--max_tries);
1031         if (max_tries == 0) {
1032             GT_0trace(curTrace, GT_4CLASS," ** Error in L3 clk control");
1033             return -EIO;
1034         }
1036         /* Ensure IVAHD and SL2 is functional */
1037         max_tries = 100;
1038         do {
1039         if((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x00030001) == 0x00001)
1040             break;
1041         } while(--max_tries);
1042         if (max_tries == 0) {
1043             GT_0trace(curTrace, GT_4CLASS," ** IVAHD is not functional");
1044             return -EIO;
1045         }
1047         max_tries = 100;
1048         do {
1049             if((in32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET) & 0x00030001) == 0x00001)
1050                 break;
1051         } while(--max_tries);
1052         if (max_tries == 0) {
1053             GT_0trace(curTrace, GT_4CLASS," ** SL2 is not functional");
1054             return -EIO;
1055         }
1056     } else {
1057         GT_0trace(curTrace, GT_3CLASS, "ivahd already acquired");
1058     }
1060     pthread_mutex_unlock(&ipu_pm_state.mtx);
1061     return EOK;
1064 int ipu_pm_ivahd_off()
1066     uintptr_t pm_base = 0;
1067     uintptr_t cm_base = 0;
1068     uint32_t reg = 0;
1069     int32_t max_tries = 0;
1070     bool ivahd_enabled = false;
1071     bool sl2_enabled = false;
1072     enum processor_version omap_rev;
1074     pm_base = (uintptr_t)prm_base_va;
1075     cm_base = (uintptr_t)cm2_base_va;
1077     omap_rev = get_omap_version();
1078     if (omap_rev < 0) {
1079         GT_setFailureReason (curTrace, GT_4CLASS, "ipu_pm_ivahd_off",
1080                              omap_rev, "Error while reading the OMAP REVISION");
1081         return EIO;
1082     }
1083     else if (omap_rev != OMAP_4430) {
1084         reg = in32(pm_base + PM_IVAHD_PWRST_OFFSET);
1085         reg = reg & 0x00000007;
1087         if (reg != 0x00000000) {
1088             /* set IVAHD to SW_WKUP */
1089             out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, 0x2);
1090             max_tries = 100;
1091             /* Check for ivahd module and disable if it is enabled */
1092             if ((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x1) != 0) {
1093                 out32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET, 0x0);
1094                 ivahd_enabled = 1;
1095             }
1096             /* Check for sl2 module and disable if it is enabled */
1097             if ((in32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET) & 0x1) != 0) {
1098                 out32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET, 0x0);
1099                 sl2_enabled = 1;
1100             }
1101             if (ivahd_enabled || sl2_enabled) {
1102                 while (((in32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET) & 0x00000100) == 0x0) && --max_tries);
1103                 if (max_tries == 0) {
1104                     GT_0trace(curTrace, GT_4CLASS,"IPU_PM:IVAHD DOMAIN is Not Enabled after retries");
1105                 }
1106             }
1108             /* Set IVAHD PD to OFF */
1109             reg = in32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET);
1110             reg = (reg & 0xFFFFFFFC) | 0x0;
1111             out32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET, reg);
1112             max_tries = 100;
1113             while (((in32(pm_base + PM_IVAHD_PWRST_OFFSET) & 0x00100000) != 0) && --max_tries);
1114             if (max_tries == 0) {
1115                GT_0trace(curTrace, GT_4CLASS,"IPU_PM: IVAHD Power Domain is in transition after retries");
1116             }
1118             if (ivahd_enabled) {
1119                 max_tries = 100;
1120                 while (((in32(cm_base + CM_IVAHD_IVAHD_CLKCTRL_OFFSET) & 0x00030000) != 0x30000) && --max_tries);
1121                 if (max_tries == 0) {
1122                     GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the IVAHD Module after retries");
1123                 }
1124             }
1125             if (sl2_enabled) {
1126                 max_tries = 100;
1127                 while (((in32(cm_base + CM_IVAHD_SL2_CLKCTRL_OFFSET) & 0x00030000) != 0x30000) && --max_tries);
1128                 if (max_tries == 0) {
1129                     GT_0trace(curTrace, GT_4CLASS,"IPU_PM: Stuck up in the SL2 Module after retries");
1130                 }
1131             }
1132             /* Set IVAHD to HW_AUTO */
1133             out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, 0x3);
1134             /* Check the reset states and assert resets */
1135             if (in32(pm_base + RM_IVAHD_RSTCTRL_OFFSET) != 0x7) {
1136                 out32(pm_base + RM_IVAHD_RSTCTRL_OFFSET, 0x7);
1137             }
1138         }
1139     }
1141     return EOK;
1144 int ipu_pm_ivahd_on()
1146     uintptr_t pm_base = 0;
1147     uintptr_t cm_base = 0;
1148     uint32_t reg = 0;
1150     pm_base = (uintptr_t)prm_base_va;
1151     cm_base = (uintptr_t)cm2_base_va;
1153     /* Set the power state to ON */
1154     reg = in32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET);
1155     reg &= 0xFFFFFFFC;
1156     reg |= 0x00000002;
1157     out32(pm_base + PM_IVAHD_PWRSTCTRL_OFFSET, reg);
1159     /* Ensure that the wake up mode is set to SW_WAKEUP */
1160     out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, 0x00000002);
1162     /* put IVA into HW Auto mode */
1163     reg = in32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET);
1164     reg |= 0x00000003;
1165     out32(cm_base + CM_IVAHD_CLKSTCTRL_OFFSET, reg);
1167     return EOK;
1170 int ipu_pm_led_enable(unsigned int mode, unsigned int intensity)
1172     int ret = 0;
1174     ret = camflash_config(mode, intensity);
1176     if (ret != -1)
1177         last_led_req = mode;
1179     return ret;
1182 int ipu_pm_alloc_sdma(int num_chs, int* channels)
1184     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma++");
1186     if(DMAAllocation == false) {
1187         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1188         return -1;
1189     }
1190     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_alloc_sdma--");
1191     return 0;
1194 int ipu_pm_free_sdma(int num_chs, int* channels)
1196     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma++");
1198     if(DMAAllocation == false) {
1199         GT_0trace(curTrace, GT_4CLASS, "Channel pool empty");
1200         return -1;
1201     }
1202     GT_0trace(curTrace, GT_3CLASS, "ipu_pm_free_sdma--");
1203     return 0;
1206 int ipu_pm_camera_enable(unsigned int mode, unsigned int on)
1208     int ret = 0;
1210     ret = campower_config(mode, on);
1212     if (mode < NUM_CAM_MODES && ret == 0)
1213         last_camera_req[mode] = on;
1215     return ret;
1218 int ipu_pm_get_max_freq(unsigned int proc, unsigned int * freq)
1220     int status = EOK;
1222     switch (proc) {
1223 #if 0 // TODO: need a way to return the max freq
1224         case RPRM_IPU:
1225                 *freq = IPU_FREQ_MAX;
1226             break;
1227         case RPRM_DSP:
1228                 *freq = DSP_FREQ_MAX;
1229             break;
1230 #endif
1231         default:
1232             status = -ENOENT;
1233             break;
1234     }
1236     return status;
1239 #ifdef QNX_PM_ENABLE
1240 static int ipu_pm_power_init(void)
1242     /*Allocate SDMA channels*/
1243     memset(&sdma_req, 0, sizeof(sdma_req));
1244     sdma_req.length = MAX_DUCATI_CHANNELS;
1245     sdma_req.flags = RSRCDBMGR_DMA_CHANNEL | RSRCDBMGR_FLAG_RANGE;
1246     sdma_req.start = DUCATI_CHANNEL_START;
1247     sdma_req.end = DUCATI_CHANNEL_END;
1248     if (rsrcdbmgr_attach(&sdma_req, 1) == -1) {
1249         DMAAllocation = false;
1250         GT_1trace(curTrace, GT_4CLASS,
1251         "ipu_pm_power_init: DMA channel allocation FAILED: %s", strerror(errno));
1252     }
1253     else {
1254         GT_0trace(curTrace, GT_3CLASS,
1255             "ipu_pm_power_init: DMA channels ALLOCATED");
1256         DMAAllocation = true;
1257     }
1259     return EOK;
1262 static void ipu_pm_power_deinit(void)
1264     if(DMAAllocation){
1265         if (rsrcdbmgr_detach(&sdma_req, 1) == -1) {
1266             GT_1trace(curTrace, GT_4CLASS,
1267                       "ipu_pm_power_deinit: DMA channel deallocation FAILED!!%s",
1268                       strerror(errno));
1269         }
1270         DMAAllocation = false;
1271     }
1272     return;
1275 static int ipu_pm_powman_init(void)
1277     int status = EOK;
1279     syslink_auth_active = powman_auth_create("SYSLINK_NEEDS_CORE_ACTIVE");
1280     if(!syslink_auth_active) {
1281         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1282                 "syslink_auth_active create failure");
1283         return -ENOMEM;
1285     }
1287     syslink_auth_oswr = powman_auth_create("SYSLINK_NEEDS_PREVENT_OSWR");
1288     if(!syslink_auth_oswr) {
1289         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1290                 "syslink_auth_oswr create failure");
1291         return -ENOMEM;
1292     }
1294     int retry = 100;
1296     /* look for server  */
1297     cpudll_coid = name_open( CPUDLL_RECV_NAME, 0);
1298     while (cpudll_coid == -1 && retry-- > 0) {
1299         sleep(1);
1300         cpudll_coid = name_open (CPUDLL_RECV_NAME, 0);
1301     }
1303     if (cpudll_coid == -1) {
1304         GT_setFailureReason (curTrace, GT_4CLASS, "connect to cpudll", EINVAL,
1305                              "Couldn't connect to CPU DLL!");
1306         return EINVAL;
1307     }
1309     /* get IVA OPPs   */
1310     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1311     dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1312     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_iva_opp, sizeof(cpudll_iva_opp) ) == -1)      {
1313         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1314                             "Could not get list of IVA OPPs.");
1315         return -ENOMEM;
1316     }
1318     /* get CORE OPPs   */
1319     dvfsMessage.dvfs.type   = getListOfDomainOPPs;
1320     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1321     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), &cpudll_core_opp, sizeof(cpudll_core_opp) ) == -1)  {
1322         GT_setFailureReason(curTrace, GT_4CLASS, "powman_init", ENOMEM,
1323                             "Could not get list of Core OPPs.");
1324         return -ENOMEM;
1325     }
1326     return status;
1329 static void ipu_pm_powman_deinit(void)
1331     int status = EOK;
1333     if (syslink_auth_active) {
1334         status = powman_auth_destroy(syslink_auth_active);
1335         if (status < 0) {
1336             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1337                              status,
1338                              "powman_auth_destroy syslink_auth_active failure");
1339         }
1340         syslink_auth_active = NULL;
1341     }
1342     if (syslink_auth_oswr) {
1343         status = powman_auth_destroy(syslink_auth_oswr);
1344         if (status < 0) {
1345             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_powman_deinit",
1346                                status,
1347                                "powman_auth_destroy syslink_auth_oswr failure");
1348         }
1349         syslink_auth_oswr = NULL;
1350     }
1352     // close the channel
1353     dvfsMessage.dvfs.type   = (cpudll_type_e)closeClient;
1354     if (MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 ) == -1) {
1355         GT_setFailureReason(curTrace, GT_4CLASS, "powman_deinit", ENOMEM,
1356                             "Could not close client connection to server.");
1357     }
1359     name_close(cpudll_coid);
1360     cpudll_coid = -1;
1363 //no special callback needed in our case so define the default.
1364 int powman_delayed_callback(unsigned ns, void (*func) (void *), void *data)
1366     return (powman_delayed_callback_default(ns, func, data));
1369 static void tell_powman_auth_oswr(int need)
1371     int r;
1372     r = powman_auth_state(syslink_auth_oswr, need);
1373     if(r != 0) {
1374         GT_setFailureReason(curTrace, GT_4CLASS, "tell_powman_auth_oswr", r,
1375                                         "powerman authority :cannot set state");
1376     }
1379 int ipu_pm_set_bandwidth(unsigned int bandwidth)
1381     int err;
1382     int oppIndex = CPUDLL_MAX_OPP_STATES-1;
1384     /* Camera needs OPPOV (highest OPP) which will be moving from index 1 to 2.
1385      * Find the greatest non-zero element to find the highest OPP and select it.
1386      */
1387     while ( (cpudll_core_opp.states[oppIndex] == 0) && (oppIndex > 0) ){
1388         oppIndex--;
1389     }
1391     dvfsMessage.dvfs.type   = setDomainOPP;
1392     dvfsMessage.dvfs.domain = CPUDLL_OMAP_CORE;
1394     dvfsMessage.dvfs.req_opp = cpudll_core_opp.states[ bandwidth>=COREOPP100?oppIndex:0 ];
1395     err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1396     if(err != EOK) {
1397         GT_1trace(curTrace, GT_4CLASS," ** Error setting CORE OPP: %s", strerror(errno));
1398     }
1399     return EOK;
1402 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1404     int err = EOK;
1405     cpudll_iva_opp_t req = 0;
1407     if (request->target_rsrc == RPRM_IVAHD) {
1408         if (request->rate > FREQ_266Mhz)
1409             req = CPUDLL_IVA_OPPTURBO;
1410         else if ((request->rate > FREQ_133Mhz) &&
1411                  (request->rate <= FREQ_266Mhz))
1412             req = CPUDLL_IVA_OPP100;
1413         else if ((request->rate > NO_FREQ_CONSTRAINT) &&
1414                  (request->rate <= FREQ_133Mhz))
1415             req = CPUDLL_IVA_OPP50;
1416         else if (request->rate == NO_FREQ_CONSTRAINT)
1417             req = CPUDLL_IVA_OPPNONE;
1419         dvfsMessage.dvfs.req_opp = cpudll_iva_opp.states[req];
1420         dvfsMessage.dvfs.type   = setDomainOPP;
1421         dvfsMessage.dvfs.domain = CPUDLL_OMAP_IVA;
1423         err = MsgSend( cpudll_coid, &dvfsMessage, sizeof( dvfsMessage ), NULL, 0 );
1424         if(err != EOK) {
1425             GT_2trace(curTrace, GT_4CLASS," ** Error setting IVA OPP %d: %s", req, strerror(err));
1426         }
1427     }
1428     return err;
1430 #else
1431 int ipu_pm_set_rate(struct ipu_pm_const_req * request)
1433     return EOK;
1435 #endif
1437 #ifdef DUCATI_SELF_HIBERNATION
1439 static int configure_timer (int val, int reload)
1441     int status = 0;
1442     struct itimerspec timeout;
1443     timeout.it_value.tv_sec = val;
1444     timeout.it_value.tv_nsec = 0;
1445     timeout.it_interval.tv_sec = reload;
1446     timeout.it_interval.tv_nsec = 0;
1447     status = timer_settime(ipu_pm_state.hibernation_timer, 0, &timeout, NULL);
1448     if (status != 0) {
1449         status = -errno;
1450     }
1451     return status;
1454 /* Function implements hibernation and watch dog timer
1455  * The functionality is based on following states
1456  * RESET:        Timer is disabed
1457  * OFF:            Timer is OFF
1458  * ON:            Timer running
1459  * HIBERNATE:    Waking up for ducati cores to hibernate
1460  * WD_RESET:    Waiting for Ducati cores to complete hibernation
1461  */
1462 int ipu_pm_timer_state(int event)
1464     int retval = 0;
1466     if (!ipu_pm_state.attached)
1467         goto exit;
1469     switch (event) {
1470         case PM_HIB_TIMER_RESET:
1471             /* disable timer and remove irq handler */
1472             //Stop the timer
1473             configure_timer(0, 0);
1474             ipu_pm_state.hib_timer_state = PM_HIB_TIMER_RESET;
1475             break;
1477         case PM_HIB_TIMER_DELETE:
1478             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF) {
1479                 /*Stop the Timer*/
1480                 configure_timer(0, 0);
1481                 /* Delete the timer */
1482                 retval = timer_delete(ipu_pm_state.hibernation_timer);
1483                }
1484               break;
1486         case PM_HIB_TIMER_OFF:
1487             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1488                 /*Stop the Timer*/
1489                 configure_timer(0, 0);
1490                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_OFF;
1491             }
1492             break;
1494         case PM_HIB_TIMER_ON:
1495             if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET||
1496                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF||
1497                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_DELETE||
1498                 ipu_pm_state.hib_timer_state == PM_HIB_TIMER_ON) {
1500                 /*Enable the timer*/
1501                 /*Start the Timer*/
1502                 configure_timer(syslink_hib_timeout / 1000, 0);
1503                 ipu_pm_state.hib_timer_state = PM_HIB_TIMER_ON;
1504             }
1505             break;
1506     }
1508 exit:
1509     if (retval < 0) {
1510       GT_setFailureReason (curTrace,
1511                            GT_4CLASS,
1512                            "ipu_pm_timer_state",
1513                            retval,
1514                            "ipu_pm_timer_state failed");
1515     }
1517     return retval;
1520 /*
1521   Function to save the MMU, Mailbox context before going to hibernation
1522  *
1523  */
1524 int ipu_pm_save_ctx(int proc_id)
1526     int retval = 0;
1527     int flag;
1528     int num_loaded_cores = 0;
1529     int core0_loaded;
1530     int core1_loaded;
1531     unsigned long timeout;
1532     unsigned short core0_id = MultiProc_getId("CORE0");
1533     unsigned short core1_id = MultiProc_getId("CORE1");
1534     unsigned short dsp_id = MultiProc_getId("DSP");
1535     struct itimerspec value;
1536     uint64_t pa = 0, da = 0;
1537     u32 len = 0;
1539     /* get M3's load flag */
1540     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
1541     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
1543     /* Because of the current scheme, we need to check
1544      * if CORE1 is enabled and we need to shut it down too
1545      * CORE0 is the only one sending the hibernate message
1546     */
1547     pthread_mutex_lock(&ipu_pm_state.mtx);
1549     if (core0Idle == NULL) {
1550         if (proc_id == core0_id) {
1551             retval = get_resource_info(RSC_SUSPENDADDR, "0", &da, &pa, &len);
1552             if (retval == 0) {
1553                 /* BIOS flags to know the state of IPU cores */
1554                 core0Idle = (void *)mmap_device_io(0x1000, ROUND_DOWN(pa, 0x1000));
1555                 if ((uintptr_t)core0Idle == MAP_DEVICE_FAILED) {
1556                     core0Idle = NULL;
1557                     retval = -ENOMEM;
1558                     goto exit;
1559                 }
1561                 core0Idle = (void *)((uint32_t)core0Idle + ((uint32_t)pa - ROUND_DOWN((uint32_t)pa, 0x1000)));
1562                 core1Idle = (void *)core0Idle + sizeof(void *);
1563             }
1564             else {
1565                 goto exit;
1566             }
1567         }
1568     }
1570     if (proc_id == core0_id || proc_id == core1_id) {
1571         timer_gettime(ipu_pm_state.hibernation_timer, &value);
1572         if (value.it_value.tv_sec || value.it_value.tv_nsec)
1573             goto exit;
1575         if (!core0_loaded)
1576             goto exit;
1578         /* If already down don't kill it twice */
1579         if (ipu_pm_state.proc_state & CORE0_PROC_DOWN) {
1580             GT_0trace(curTrace, GT_4CLASS, "ipu already hibernated");
1581             goto exit;
1582         }
1584         if (rpmsg_resmgr_allow_hib(core0_id) &&
1585             rpmsg_resmgr_allow_hib(core1_id) &&
1586             !TESTBITREG32((uintptr_t)m3_clkstctrl,
1587                           CM_MPU_M3_CLKSTCTRL_CLKACTIVITY_BIT)) {
1588             retval = ArchIpcInt_sendInterrupt(core0_id,
1589                                               ipu_pm_state.cfg.int_id,
1590                                               RP_MBOX_HIBERNATION);
1591         }
1592         else {
1593             /* restart timer */
1594             configure_timer(syslink_hib_timeout / 1000, 0);
1595             goto exit;
1596         }
1598         num_loaded_cores = core1_loaded + core0_loaded;
1599         flag = 1;
1600         timeout = WAIT_FOR_IDLE_TIMEOUT;
1601         /* Wait fot Ducati to hibernate */
1602         do {
1603             /* Checking if IPU is really in idle */
1604             if (NUM_IDLE_CORES == num_loaded_cores) {
1605                 flag = 0;
1606                 break;
1607             } else {
1608                 usleep(1000);
1609             }
1610         } while ( --timeout != 0);
1612         if (flag) {
1613             GT_0trace(curTrace, GT_4CLASS, "Ducati Cores are NOT really Idle");
1614             goto error;
1615         }
1617         ipu_pm_timer_state(PM_HIB_TIMER_OFF);
1618         retval = Omap4430IpcInt_mboxSaveCtxt(core0_id);
1619         if(retval != OMAP4430IPCINT_SUCCESS){
1620             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1621                                 retval,
1622                                 "Error while saving the MailBox context");
1623             goto error;
1624         }
1626         if (core1_loaded) {
1627 #ifdef DUCATI_WATCHDOG_TIMER
1628             save_gpt_context(GPTIMER_11);
1629             ipu_pm_gpt_stop(GPTIMER_11);
1630             ipu_pm_gpt_disable(GPTIMER_11);
1631 #endif
1632             if (GPT4InUse == TRUE)
1633                 save_gpt_context(GPTIMER_4);
1635             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
1636                                  Omap4430DucatiProc_CtrlCmd_Suspend, NULL);
1637             if (retval < 0) {
1638                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx",
1639                                     retval, "Error while suspending CORE1");
1640                 goto error;
1641             }
1642             GT_0trace(curTrace, GT_4CLASS, "Sleep CORE1");
1643         }
1645 #ifdef DUCATI_WATCHDOG_TIMER
1646         save_gpt_context(GPTIMER_9);
1647         ipu_pm_gpt_stop(GPTIMER_9);
1648         ipu_pm_gpt_disable(GPTIMER_9);
1649 #endif
1650         if (GPT3InUse == TRUE)
1651             save_gpt_context(GPTIMER_3);
1653         ipu_pm_state.proc_state |= CORE1_PROC_DOWN;
1654         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
1655                                  Omap4430DucatiProc_CtrlCmd_Suspend, NULL);
1656         if (retval < 0) {
1657             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
1658                                 "Error while suspending CORE0");
1659             goto error;
1660         }
1661         GT_0trace(curTrace, GT_4CLASS, "Sleep CORE0");
1662         ipu_pm_state.proc_state |= CORE0_PROC_DOWN;
1664         ipu_pm_ivahd_off();
1666         // Advise that Ducati is hibernating
1667         pthread_mutex_lock(&syslink_hib_mutex);
1668         syslink_hib_hibernating = TRUE;
1669         pthread_mutex_unlock(&syslink_hib_mutex);
1670     }
1671     else if (proc_id == dsp_id) {
1672         //TODO: Add support for DSP.
1673     }
1674     else
1675         goto error;
1677 #ifdef QNX_PM_ENABLE
1678     if (oswr_prevent == 1) {
1679         tell_powman_auth_oswr(0); // Passing 1 prevents OSWR and 0 allows OSWR
1680         oswr_prevent = 0;
1681     }
1682 #endif
1683        /* If there is a message in the mbox restore
1684      * immediately after save.
1685      */
1686     if (PENDING_MBOX_MSG)
1687         goto restore;
1689 exit:
1690     pthread_mutex_unlock(&ipu_pm_state.mtx);
1691     return 0;
1692 error:
1693     GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_save_ctx", retval,
1694                         "Aborting hibernation process");
1695     ipu_pm_timer_state(PM_HIB_TIMER_ON);
1696     pthread_mutex_unlock(&ipu_pm_state.mtx);
1697     return retval;
1698 restore:
1699     GT_0trace(curTrace, GT_4CLASS,
1700               "Starting restore_ctx since messages pending in mbox");
1701     pthread_mutex_unlock(&ipu_pm_state.mtx);
1702     ipu_pm_restore_ctx(proc_id);
1704     return retval;
1708 /* Function to check if a processor is shutdown
1709  * if shutdown then restore context else return.
1710  */
1711 int ipu_pm_restore_ctx(int proc_id)
1713     int retval = 0;
1714     int core0_loaded;
1715     int core1_loaded;
1716     unsigned short core0_id = MultiProc_getId("CORE0");
1717     unsigned short core1_id = MultiProc_getId("CORE1");
1718     unsigned short dsp_id = MultiProc_getId("DSP");
1720     /*If feature not supported by proc, return*/
1721     if (proc_id == dsp_id)
1722         return 0;
1724     /* Check if the M3 was loaded */
1725     core0_loaded = (ipu_pm_state.loaded_procs & CORE0_LOADED);
1726     core1_loaded = (ipu_pm_state.loaded_procs & CORE1_LOADED);
1728     /* Because of the current scheme, we need to check
1729      * if CORE1 is enable and we need to enable it too
1730      * In both cases we should check if for both cores
1731      * and enable them if they were loaded.
1732      */
1733     pthread_mutex_lock(&ipu_pm_state.mtx);
1735     /* Restart the hib timer */
1736     if (syslink_hib_enable) {
1737         ipu_pm_timer_state(PM_HIB_TIMER_ON);
1738     }
1739 #ifdef QNX_PM_ENABLE
1740     if(oswr_prevent == 0) {
1741         tell_powman_auth_oswr(1); // Passing 1 prevents OSWR and 0 allows OSWR
1742         oswr_prevent = 1;
1743     }
1744 #endif
1745     if (proc_id == core0_id || proc_id == core1_id) {
1746         if (!(ipu_pm_state.proc_state & CORE0_PROC_DOWN) || !core0_loaded) {
1747             goto exit;
1748         }
1750         if (ProcMgr_getState(ipu_pm_state.proc_handles[core0_id]) != ProcMgr_State_Suspended) {
1751             goto exit;
1752         }
1754         retval = Omap4430IpcInt_mboxRestoreCtxt(core0_id);
1755         if(retval != OMAP4430IPCINT_SUCCESS){
1756             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
1757                                 retval,
1758                                 "Not able to restore Mail Box context");
1759             goto error;
1760         }
1762 #ifdef DUCATI_WATCHDOG_TIMER
1763         ipu_pm_gpt_enable(GPTIMER_9);
1764         restore_gpt_context(GPTIMER_9);
1765         ipu_pm_gpt_start(GPTIMER_9);
1766 #endif
1767         if (GPT3InUse == TRUE) {
1768             ipu_pm_gpt_enable(GPTIMER_3);
1769             restore_gpt_context(GPTIMER_3);
1770         }
1772         GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE0");
1773         ipu_pm_state.proc_state &= ~CORE0_PROC_DOWN;
1774         retval = ProcMgr_control(ipu_pm_state.proc_handles[core0_id],
1775                                  Omap4430DucatiProc_CtrlCmd_Resume, NULL);
1776         if (retval < 0){
1777             GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
1778                                 retval, "Not able to resume CORE0");
1779             goto error;
1780         }
1782         if (core1_loaded) {
1783 #ifdef DUCATI_WATCHDOG_TIMER
1784             ipu_pm_gpt_enable(GPTIMER_11);
1785             restore_gpt_context(GPTIMER_11);
1786             ipu_pm_gpt_start(GPTIMER_11);
1787 #endif
1788             if (GPT4InUse == TRUE) {
1789                 ipu_pm_gpt_enable(GPTIMER_4);
1790                 restore_gpt_context(GPTIMER_4);
1791             }
1793             GT_0trace(curTrace, GT_4CLASS, "Wakeup CORE1");
1794             ipu_pm_state.proc_state &= ~CORE1_PROC_DOWN;
1795             retval = ProcMgr_control(ipu_pm_state.proc_handles[core1_id],
1796                                      Omap4430DucatiProc_CtrlCmd_Resume, NULL);
1797             if (retval < 0){
1798                 GT_setFailureReason(curTrace, GT_4CLASS, "ipu_pm_restore_ctx",
1799                                     retval, "Not able to resume CORE1");
1800                 goto error;
1801             }
1802         }
1803         pthread_mutex_lock(&syslink_hib_mutex);
1804         // Once we are active, signal any thread waiting for end of hibernation
1805         syslink_hib_hibernating = FALSE;
1806         pthread_cond_broadcast(&syslink_hib_cond);
1807         pthread_mutex_unlock(&syslink_hib_mutex);
1808     }
1809     else
1810         goto error;
1811 exit:
1812     /* turn on ducati hibernation timer */
1813     if (ipu_pm_state.hib_timer_state == PM_HIB_TIMER_OFF ||
1814         ipu_pm_state.hib_timer_state == PM_HIB_TIMER_RESET) {
1815             ipu_pm_timer_state(PM_HIB_TIMER_ON);
1816     }
1817     pthread_mutex_unlock(&ipu_pm_state.mtx);
1818     return retval;
1819 error:
1820     pthread_mutex_unlock(&ipu_pm_state.mtx);
1821     return -EINVAL;
1824 /* ISR for Timer*/
1825 static void ipu_pm_timer_interrupt (union sigval val)
1827     ipu_pm_save_ctx(MultiProc_getId("CORE0"));
1828     return;
1830 #else // DUCATI_SELF_HIBERNATION
1832 int ipu_pm_restore_ctx(int proc_id)
1834     return 0;
1836 #endif //DUCATI_SELF_HIBERNATION
1838 int ipu_pm_attach(int proc_id)
1840     int retval = EOK;
1841 #ifdef DUCATI_WATCHDOG_TIMER
1842     OsalIsr_Params isrParams;
1843 #endif
1845     if (proc_id > MultiProc_MAXPROCESSORS) {
1846         return -EINVAL;
1847     }
1849     if (proc_id == MultiProc_getId("CORE0")) {
1850         ipu_pm_state.loaded_procs |= CORE0_LOADED;
1851 #ifdef DUCATI_WATCHDOG_TIMER
1852         ipu_pm_gpt_enable(GPTIMER_9);
1853         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
1854         isrParams.fxnArgs = (Ptr)GPTIMER_9;
1855         isrParams.intId = OMAP44XX_IRQ_GPT9;
1856         isrParams.sharedInt = FALSE;
1857         ipu_pm_state.gpt9IsrObject =
1858             OsalIsr_create(&ipu_pm_gptimer_interrupt,
1859                            isrParams.fxnArgs, &isrParams);
1860         if(ipu_pm_state.gpt9IsrObject != NULL) {
1861             if (OsalIsr_install(ipu_pm_state.gpt9IsrObject) < 0) {
1862                 retval = -ENOMEM;
1863             }
1864         }
1865         else {
1866             retval = -ENOMEM;
1867         }
1868 #endif
1869     }
1870     else if (proc_id == MultiProc_getId("CORE1")) {
1871         ipu_pm_state.loaded_procs |= CORE1_LOADED;
1872 #ifdef DUCATI_WATCHDOG_TIMER
1873         ipu_pm_gpt_enable(GPTIMER_11);
1874         isrParams.checkAndClearFxn = ipu_pm_clr_gptimer_interrupt;
1875         isrParams.fxnArgs = (Ptr)GPTIMER_11;
1876         isrParams.intId = OMAP44XX_IRQ_GPT11;
1877         isrParams.sharedInt = FALSE;
1878         ipu_pm_state.gpt11IsrObject =
1879             OsalIsr_create(&ipu_pm_gptimer_interrupt,
1880                            isrParams.fxnArgs, &isrParams);
1881         if(ipu_pm_state.gpt11IsrObject != NULL) {
1882             if (OsalIsr_install(ipu_pm_state.gpt11IsrObject) < 0) {
1883                 retval = -ENOMEM;
1884             }
1885         }
1886         else {
1887             retval = -ENOMEM;
1888         }
1889 #endif
1890     }
1892     if (retval >= 0)
1893         retval = ProcMgr_open(&ipu_pm_state.proc_handles[proc_id], proc_id);
1895     if (retval < 0) {
1896 #ifdef DUCATI_WATCHDOG_TIMER
1897         if (proc_id == MultiProc_getId("CORE0")) {
1898             if (ipu_pm_state.gpt9IsrObject) {
1899                 OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
1900                 OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
1901                 ipu_pm_state.gpt9IsrObject = NULL;
1902             }
1903             ipu_pm_gpt_stop(GPTIMER_9);
1904             ipu_pm_gpt_disable(GPTIMER_9);
1905         }
1906         else if (proc_id == MultiProc_getId("CORE1")) {
1907             if (ipu_pm_state.gpt11IsrObject) {
1908                 OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
1909                 ipu_pm_state.gpt11IsrObject = NULL;
1910             }
1911             ipu_pm_gpt_stop(GPTIMER_11);
1912             ipu_pm_gpt_disable(GPTIMER_11);
1913         }
1914 #endif
1915     }
1916     else {
1917         ipu_pm_state.attached[proc_id] = TRUE;
1918     }
1920     return retval;
1923 int ipu_pm_detach(int proc_id)
1925     int retval = EOK;
1927     if (proc_id > MultiProc_MAXPROCESSORS) {
1928         return -EINVAL;
1929     }
1931     ipu_pm_state.attached[proc_id] = FALSE;
1933 #ifdef DUCATI_SELF_HIBERNATION
1934     if (core0Idle != NULL) {
1935         munmap_device_io(ROUND_DOWN((uint32_t)core0Idle, 0x1000),
1936                          0x1000);
1937         core0Idle = NULL;
1938         core1Idle = NULL;
1939     }
1940 #endif
1942     if (proc_id == MultiProc_getId("CORE0")) {
1943 #ifdef DUCATI_WATCHDOG_TIMER
1944         OsalIsr_uninstall(ipu_pm_state.gpt9IsrObject);
1945         OsalIsr_delete(&ipu_pm_state.gpt9IsrObject);
1946         ipu_pm_state.gpt9IsrObject = NULL;
1947         ipu_pm_gpt_stop(GPTIMER_9);
1948         ipu_pm_gpt_disable(GPTIMER_9);
1949 #endif
1950         ipu_pm_state.loaded_procs &= ~CORE0_LOADED;
1951     }
1952     else if (proc_id == MultiProc_getId("CORE1")) {
1953 #ifdef DUCATI_WATCHDOG_TIMER
1954         OsalIsr_uninstall(ipu_pm_state.gpt11IsrObject);
1955         OsalIsr_delete(&ipu_pm_state.gpt11IsrObject);
1956         ipu_pm_state.gpt11IsrObject = NULL;
1957         ipu_pm_gpt_stop(GPTIMER_11);
1958         ipu_pm_gpt_disable(GPTIMER_11);
1959 #endif
1960         ipu_pm_state.loaded_procs &= ~CORE1_LOADED;
1961     }
1963     if (ipu_pm_state.proc_handles[proc_id]) {
1964         ProcMgr_close(&ipu_pm_state.proc_handles[proc_id]);
1965         ipu_pm_state.proc_handles[proc_id] = NULL;
1966     }
1968     return retval;
1971 int ipu_pm_setup(ipu_pm_config *cfg)
1973     int retval = EOK;
1974     int i = 0;
1975 #ifdef DUCATI_SELF_HIBERNATION
1976     struct sigevent signal_event;
1977 #endif
1979     if (ipu_pm_state.is_setup == false) {
1980         pthread_mutex_init(&ipu_pm_state.mtx, NULL);
1982         if (cfg == NULL) {
1983             retval = -EINVAL;
1984             goto exit;
1985         }
1986         if (cfg->num_procs > MultiProc_MAXPROCESSORS) {
1987             retval = -EINVAL;
1988             goto exit;
1989         }
1991         memcpy(&ipu_pm_state.cfg, cfg, sizeof(ipu_pm_config));
1993 #ifdef DUCATI_SELF_HIBERNATION
1994         /* MBOX flag to check if there are pending messages */
1995         a9_m3_mbox = (void *)mmap_device_io(0x1000, A9_M3_MBOX);
1996         if ((uintptr_t)a9_m3_mbox == MAP_DEVICE_FAILED) {
1997             a9_m3_mbox = NULL;
1998             retval = -ENOMEM;
1999             goto exit;
2000         }
2002         if (syslink_hib_enable) {
2003             SIGEV_THREAD_INIT (&signal_event, ipu_pm_timer_interrupt, NULL,
2004                                NULL);
2005             retval = timer_create(CLOCK_REALTIME, &signal_event,
2006                                   &ipu_pm_state.hibernation_timer);
2007             if (retval < 0) {
2008                 retval = -errno;
2009                 goto exit;
2010             }
2011         }
2012 #endif
2014         cm2_base_va = (void *)mmap_device_io(CM2_SIZE, CM2_BASE);
2015         if ((uintptr_t)cm2_base_va == MAP_DEVICE_FAILED) {
2016             cm2_base_va = NULL;
2017             retval = -errno;
2018             goto exit;
2019         }
2020 #ifdef DUCATI_SELF_HIBERNATION
2021         m3_clkstctrl = cm2_base_va + CM_MPU_M3_CLKCTRL_OFFSET;
2022 #endif
2024         prm_base_va = (void *)mmap_device_io(PRM_SIZE, PRM_BASE);
2025         if ((uintptr_t)prm_base_va == MAP_DEVICE_FAILED) {
2026             prm_base_va = NULL;
2027             retval = -errno;
2028             goto exit;
2029         }
2031         map_gpt_regs();
2032 #ifdef QNX_PM_ENABLE
2033         ipu_pm_powman_init();
2034         ipu_pm_power_init();
2035 #endif
2036         for (i = 0; i < NUM_CAM_MODES; i++)
2037             last_camera_req[i] = 0;
2038         last_led_req = 0;
2040         ipu_pm_state.is_setup = true;
2041     }
2043 exit:
2044     if (retval != EOK) {
2045         unmap_gpt_regs();
2046         if (prm_base_va) {
2047             munmap(prm_base_va, PRM_SIZE);
2048             prm_base_va = NULL;
2049         }
2050         if (cm2_base_va) {
2051             munmap(cm2_base_va, CM2_SIZE);
2052             cm2_base_va = NULL;
2053         }
2054 #ifdef DUCATI_SELF_HIBERNATION
2055         m3_clkstctrl = NULL;
2057         if (a9_m3_mbox) {
2058             munmap(a9_m3_mbox, 0x1000);
2059             a9_m3_mbox = NULL;
2060         }
2061 #endif
2062         ipu_pm_state.loaded_procs = 0;
2063         pthread_mutex_destroy(&ipu_pm_state.mtx);
2064     }
2065     return retval;
2068 int ipu_pm_destroy()
2070     int i = 0;
2072     if (ipu_pm_state.is_setup) {
2073         for (i = 0; i < NUM_CAM_MODES; i++) {
2074             if (last_camera_req[i])
2075                 ipu_pm_camera_enable(i, 0);
2076         }
2077         if (last_led_req)
2078             ipu_pm_led_enable(0, 0);
2080 #ifdef QNX_PM_ENABLE
2081         ipu_pm_power_deinit();
2082         ipu_pm_powman_deinit();
2083 #endif
2085         unmap_gpt_regs();
2086 #ifdef DUCATI_SELF_HIBERNATION
2087         if (syslink_hib_enable) {
2088             /*Stop the Timer*/
2089             configure_timer(0, 0);
2090             /* Delete the timer */
2091             timer_delete(ipu_pm_state.hibernation_timer);
2092         }
2093         if (a9_m3_mbox) {
2094             munmap(a9_m3_mbox, 0x1000);
2095             a9_m3_mbox = NULL;
2096         }
2097         m3_clkstctrl = NULL;
2098 #endif
2099         if (cm2_base_va) {
2100             munmap(cm2_base_va, CM2_SIZE);
2101             cm2_base_va = NULL;
2102         }
2103         if (prm_base_va) {
2104             munmap(prm_base_va, PRM_SIZE);
2105             prm_base_va = NULL;
2106         }
2107         pthread_mutex_destroy(&ipu_pm_state.mtx);
2108         ipu_pm_state.proc_state = 0;
2109         ipu_pm_state.loaded_procs = 0;
2110         ipu_pm_state.ivahd_use_cnt = 0;
2111         ipu_pm_state.is_setup = false;
2112     }
2113     return EOK;