ducati: implement VirtToPhys using new sysbios-rpmsg API
[gstreamer-omap:ndecs-libdce.git] / ducati / ti / dce / ivahd.c
1 /*
2  * Copyright (c) 2010, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33
34 #include <xdc/std.h>
35 #include <xdc/runtime/System.h>
36 #include <xdc/runtime/Memory.h>
37 #include <xdc/runtime/IHeap.h>
38 #include <xdc/runtime/Error.h>
39 #include <ti/sysbios/knl/Clock.h>
40 #include <ti/sysbios/knl/Task.h>
41 #include <ti/sysbios/hal/Hwi.h>
42 #include <ti/pm/IpcPower.h>
43 #include <ti/pm/_IpcPower.h>
44 #include <ti/sdo/ce/Engine.h>
45 #include <ti/sdo/ce/CERuntime.h>
46 #include <ti/sdo/utils/trace/gt.h>
47 #include <xdc/cfg/global.h>
48
49 #include "dce_priv.h"
50
51 #include <ti/xdais/ires.h>
52 #include <ti/sdo/fc/ires/hdvicp/iresman_hdvicp.h>
53 #include <ti/sdo/fc/ires/hdvicp/ires_hdvicp2.h>
54 #include <ti/sdo/fc/ires/tiledmemory/iresman_tiledmemory.h>
55 #include <ti/sdo/fc/rman/rman.h>
56 #include <ti/resources/IpcMemory.h>
57
58 #define MEMORYSTATS_DEBUG 1
59
60 static uint32_t ivahd_base = 0;
61 static uint32_t ivahd_m5div = 0x1f;
62
63 static uint32_t get_ivahd_base(void)
64 {
65     if (!ivahd_base) {
66         ERROR("Chipset ID not set!");
67         while (TRUE) {
68             asm(" wfi");
69         }
70     }
71     return ivahd_base;
72 }
73
74 #define IVAHD_REG(off)            (*(volatile unsigned int *)(get_ivahd_base() + (off)))
75
76 #define PM_IVAHD_PWRSTCTRL        IVAHD_REG(0xF00)
77 #define RM_IVAHD_RSTCTRL          IVAHD_REG(0xF10)
78 #define RM_IVAHD_RSTST            IVAHD_REG(0xF14)
79
80 #define CM_IVAHD_CLKSTCTRL        (*(volatile unsigned int *)0xAA008F00)
81 #define CM_IVAHD_CLKCTRL          (*(volatile unsigned int *)0xAA008F20)
82 #define CM_IVAHD_SL2_CLKCTRL      (*(volatile unsigned int *)0xAA008F28)
83
84 #define CM_DIV_M5_DPLL_IVA        (*(volatile unsigned int *)0xAA0041BC)
85
86 #define IVAHD_CONFIG_REG_BASE     (0xBA000000)
87 #define ICONT1_ITCM_BASE          (IVAHD_CONFIG_REG_BASE + 0x08000)
88 #define ICONT2_ITCM_BASE          (IVAHD_CONFIG_REG_BASE + 0x18000)
89
90
91 /*******************************************************************************
92  *   Hex code to set for Stack setting, Interrupt vector setting
93  *   and instruction to put ICONT in WFI mode.
94  *   This shall be placed at TCM_BASE_ADDRESS of given IVAHD, which is
95  *   0x0000 locally after reset.
96  *******************************************************************************/
97
98 const unsigned int icont_boot[] = {
99         0xEA000006,
100         0xEAFFFFFE,
101         0xEAFFFFFE,
102         0xEAFFFFFE,
103         0xEAFFFFFE,
104         0xEAFFFFFE,
105         0xEAFFFFFE,
106         0xEAFFFFFE,
107         0xE3A00000,
108         0xEE070F9A,
109         0xEE070F90,
110         0xE3A00000,
111         0xEAFFFFFE,
112         0xEAFFFFF1
113 };
114
115
116 static inline void sleepms(int ms)
117 {
118     Task_sleep(((ms * 1000 + (Clock_tickPeriod - 1)) / Clock_tickPeriod));
119 }
120
121 static void ivahd_boot(void)
122 {
123     int i;
124     volatile unsigned int *icont1_itcm_base_addr =
125             (unsigned int *)ICONT1_ITCM_BASE;
126     volatile unsigned int *icont2_itcm_base_addr =
127             (unsigned int *)ICONT2_ITCM_BASE;
128
129     /*
130      * Reset IVA HD, SL2 and ICONTs
131      */
132
133     DEBUG("Booting IVAHD...");
134
135     /* Reset IVAHD sequencers and SL2 */
136     RM_IVAHD_RSTCTRL = 0x00000007;
137     sleepms(10);
138
139     /* Turn IVA power state to on */
140     PM_IVAHD_PWRSTCTRL = 0x00000003;
141     sleepms(10);
142
143     /* First put IVA into SW_WKUP mode */
144     CM_IVAHD_CLKSTCTRL = 0x00000002;
145     sleepms(10);
146
147     /* Set IVA clock to 'auto' */
148     CM_IVAHD_CLKCTRL = 0x00000001;
149     sleepms(10);
150
151     /* Set SL2 clock to 'auto' */
152     CM_IVAHD_SL2_CLKCTRL = 0x00000001;
153     sleepms(10);
154
155     /* put ICONT1 & ICONT2 in reset and remove SL2 reset */
156     RM_IVAHD_RSTCTRL = 0x00000003;
157     sleepms(10);
158
159     /* Copy boot code to ICONT1 & ICONT2 memory */
160     for (i = 0; i < DIM(icont_boot); i++) {
161         *icont1_itcm_base_addr++ = icont_boot[i];
162         *icont2_itcm_base_addr++ = icont_boot[i];
163     }
164 }
165
166 int ivahd_reset(void * handle, void * iresHandle)
167 {
168     /*
169      * Reset IVA HD, SL2 and ICONTs
170      */
171
172     DEBUG("Resetting IVAHD...");
173
174     /* First put IVA into HW Auto mode */
175     CM_IVAHD_CLKSTCTRL |= 0x00000003;
176
177     /* Wait for IVA HD to standby */
178     while (!((CM_IVAHD_CLKCTRL) & 0x00040000));
179
180     /* Disable IVAHD and SL2 modules */
181     CM_IVAHD_CLKCTRL = 0x00000000;
182     CM_IVAHD_SL2_CLKCTRL = 0x00000000;
183
184     /* Ensure that IVAHD and SL2 are disabled */
185     while (!(CM_IVAHD_CLKCTRL & 0x00030000));
186     while (!(CM_IVAHD_SL2_CLKCTRL & 0x00030000));
187
188     /* Reset IVAHD sequencers and SL2 */
189     RM_IVAHD_RSTCTRL |= 0x00000007;
190
191     /*
192      * Check if modules are reset
193      */
194
195     /* First clear the status bits */
196     RM_IVAHD_RSTST |= 0x00000007;
197
198     /* Wait for confirmation that the systems have been reset */
199     /* THIS CHECK MAY NOT BE NECESSARY, AND MOST OF ALL GIVEN OUR STATE,
200      * MAY NOT BE POSSIBLE
201      */
202
203     /* Ensure that the wake up mode is set to SW_WAKEUP */
204     CM_IVAHD_CLKSTCTRL &= 0x00000002;
205
206     /* Enable IVAHD and SL2 modules */
207     CM_IVAHD_CLKCTRL = 0x00000001;
208     CM_IVAHD_SL2_CLKCTRL = 0x00000001;
209
210     /* Deassert the SL2 reset */
211     RM_IVAHD_RSTCTRL &= 0xFFFFFFFB;
212
213     /* Ensure that IVAHD and SL2 are enabled */
214     while (CM_IVAHD_CLKCTRL & 0x00030000);
215     while (CM_IVAHD_SL2_CLKCTRL & 0x00030000);
216
217     return TRUE;
218 }
219
220 static int ivahd_use_cnt = 0;
221
222 static inline void set_ivahd_opp(int opp)
223 {
224     unsigned int val;
225
226     switch (opp) {
227     case 0:    val = 0x010e;       break;
228     case 50:   val = 0x000e;       break;
229     case 100:  val = ivahd_m5div;  break;
230     default: ERROR("invalid opp"); return;
231     }
232
233     DEBUG("CM_DIV_M5_DPLL_IVA=%08x", CM_DIV_M5_DPLL_IVA);
234     /* set HSDIVDER_CLKOUT2_DIV */
235     CM_DIV_M5_DPLL_IVA = (CM_DIV_M5_DPLL_IVA & ~0x0000011f) | val;
236     DEBUG("CM_DIV_M5_DPLL_IVA=%08x", CM_DIV_M5_DPLL_IVA);
237 }
238
239 void ivahd_acquire(void)
240 {
241     UInt hwiKey = Hwi_disable();
242     if (++ivahd_use_cnt == 1) {
243         DEBUG("ivahd acquire");
244         set_ivahd_opp(100);
245     } else {
246         DEBUG("ivahd already acquired");
247     }
248     Hwi_restore(hwiKey);
249 }
250
251 void ivahd_release(void)
252 {
253     UInt hwiKey = Hwi_disable();
254     if (ivahd_use_cnt-- == 1) {
255         DEBUG("ivahd release");
256         set_ivahd_opp(0);
257     } else {
258         DEBUG("ivahd still in use");
259     }
260     Hwi_restore(hwiKey);
261 }
262
263 static unsigned int SyslinkMemUtils_VirtToPhys(Ptr Addr)
264 {
265     unsigned int    pa;
266
267     if( !Addr || IpcMemory_virtToPhys((unsigned int) Addr, &pa)) {
268         return (0);
269     }
270     return (pa);
271 }
272
273 void *MEMUTILS_getPhysicalAddr(Ptr vaddr)
274 {
275     unsigned int paddr = SyslinkMemUtils_VirtToPhys(vaddr);
276     DEBUG("virtual addr:%x\tphysical addr:%x", vaddr, paddr);
277     return (void *)paddr;
278 }
279
280 static Bool allocFxn(IALG_MemRec *memTab, Int numRecs);
281 static void freeFxn(IALG_MemRec *memTab, Int numRecs);
282
283
284 void ivahd_init(uint32_t chipset_id)
285 {
286     IRES_Status ret;
287     IRESMAN_Params rman_params = {
288             .size = sizeof(IRESMAN_Params),
289             .allocFxn = allocFxn,
290             .freeFxn = freeFxn,
291     };
292
293     sleepms(10);
294
295     switch (chipset_id) {
296     case 0x4430:
297         ivahd_base = 0xAA306000;
298         ivahd_m5div = 0x07;
299         break;
300     case 0x4460:
301     case 0x4470:
302         ivahd_base = 0xAA306000;
303         ivahd_m5div = 0x05;
304         break;
305     case 0x5430:
306     case 0x5432:
307         ivahd_base = 0xAAE06000;
308         ivahd_m5div = 0x04;
309         break;
310     default:
311         ERROR("Invalid chipset-id: %x", chipset_id);
312         break;
313     }
314
315     CERuntime_init();
316
317     ret = RMAN_init();
318     if (ret != IRES_OK) {
319         goto end;
320     }
321
322     /* Register HDVICP with RMAN if not already registered */
323     ret = RMAN_register(&IRESMAN_HDVICP, &rman_params);
324     if ((ret != IRES_OK) && (ret != IRES_EEXISTS)) {
325         DEBUG("could not register IRESMAN_HDVICP: %d", ret);
326         goto end;
327     }
328
329     /* NOTE: this might try MemMgr allocations over RCM remote
330      * call back to host side.  Which will fail if we don't
331      * have memsrv.  But will eventually fall back to allocFxn
332      * which will allocate from the local heap.
333      */
334     ret = RMAN_register(&IRESMAN_TILEDMEMORY, &rman_params);
335     if ((ret != IRES_OK) && (ret != IRES_EEXISTS)) {
336         DEBUG("could not register IRESMAN_TILEDMEMORY: %d", ret);
337         goto end;
338     }
339
340     sleepms(10);
341
342     ivahd_boot();
343
344     /* clear HSDIVDER_CLKOUT2_DIV */
345     set_ivahd_opp(0);
346
347     DEBUG("RMAN_register() for HDVICP is successful");
348
349 end:
350     return;
351 }
352
353 static Bool allocFxn(IALG_MemRec memTab[], Int n)
354 {
355     Int i;
356 #ifdef MEMORYSTATS_DEBUG
357     Memory_Stats stats;
358 #endif
359
360     for (i = 0; i < n; i++) {
361         Error_Block eb;
362         Uns pad, size;
363         void *blk;
364         MemHeader *hdr;
365
366         if (memTab[i].alignment > sizeof(MemHeader)) {
367             pad = memTab[i].alignment;
368         } else {
369             pad = sizeof(MemHeader);
370         }
371
372         size = memTab[i].size + pad;
373
374 #ifdef MEMORYSTATS_DEBUG
375         Memory_getStats(NULL, &stats);
376         INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,
377                 stats.totalFreeSize, stats.largestFreeSize);
378 #endif
379
380         blk = Memory_alloc(NULL, size, memTab[i].alignment, &eb);
381
382         if (!blk) {
383             ERROR("MemTab Allocation failed at %d", i);
384             freeFxn(memTab, i);
385             return FALSE;
386         } else {
387             memTab[i].base = (void *)((char *)blk + pad);
388             hdr = P2H(memTab[i].base);
389             hdr->size = size;
390             hdr->ptr  = blk;
391             DEBUG("%d: alloc: %p/%p (%d)", i, hdr->ptr,
392                     memTab[i].base, hdr->size);
393         }
394     }
395     DEBUG("MemTab Allocation is Successful");
396     return TRUE;
397 }
398
399 static void freeFxn(IALG_MemRec memTab[], Int n)
400 {
401     Int i;
402 #ifdef MEMORYSTATS_DEBUG
403     Memory_Stats stats;
404 #endif
405
406     for (i = 0; i < n; i++) {
407         if (memTab[i].base != NULL) {
408             MemHeader *hdr = P2H(memTab[i].base);
409
410 #ifdef MEMORYSTATS_DEBUG
411             DEBUG("%d: free: %p/%p (%d)", n, hdr->ptr,
412                     memTab[i].base, hdr->size);
413 #endif
414             Memory_free(NULL, hdr->ptr, hdr->size);
415         }
416 #ifdef MEMORYSTATS_DEBUG
417         Memory_getStats(NULL, &stats);
418         INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,
419                 stats.totalFreeSize, stats.largestFreeSize);
420 #endif
421     }
422 }