4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Implementation for the io read/write routines.
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 /* ----------------------------------- DSP/BIOS Bridge */
20 #include <dspbridge/dbdefs.h>
22 /* ----------------------------------- Trace & Debug */
23 #include <dspbridge/dbc.h>
25 /* ----------------------------------- Platform Manager */
26 #include <dspbridge/dev.h>
27 #include <dspbridge/drv.h>
29 /* ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/wdt.h>
33 /* ----------------------------------- specific to this file */
35 #include "_tiomap_pwr.h"
36 #include "tiomap_io.h"
38 static u32 ul_ext_base
;
39 static u32 ul_ext_end
;
42 static u32 ul_dyn_ext_base
;
43 static u32 ul_trace_sec_beg
;
44 static u32 ul_trace_sec_end
;
45 static u32 ul_shm_base_virt
;
47 bool symbols_reloaded
= true;
50 * ======== read_ext_dsp_data ========
51 * Copies DSP external memory buffers to the host side buffers.
53 int read_ext_dsp_data(struct bridge_dev_context
*hDevContext
,
54 OUT u8
*pbHostBuf
, u32 dwDSPAddr
,
55 u32 ul_num_bytes
, u32 ulMemType
)
58 struct bridge_dev_context
*dev_context
= hDevContext
;
60 u32 ul_tlb_base_virt
= 0;
61 u32 ul_shm_offset_virt
= 0;
62 u32 dw_ext_prog_virt_mem
;
63 u32 dw_base_addr
= dev_context
->dw_dsp_ext_base_addr
;
64 bool trace_read
= false;
66 if (!ul_shm_base_virt
) {
67 status
= dev_get_symbol(dev_context
->hdev_obj
,
68 SHMBASENAME
, &ul_shm_base_virt
);
70 DBC_ASSERT(ul_shm_base_virt
!= 0);
72 /* Check if it is a read of Trace section */
73 if (DSP_SUCCEEDED(status
) && !ul_trace_sec_beg
) {
74 status
= dev_get_symbol(dev_context
->hdev_obj
,
75 DSP_TRACESEC_BEG
, &ul_trace_sec_beg
);
77 DBC_ASSERT(ul_trace_sec_beg
!= 0);
79 if (DSP_SUCCEEDED(status
) && !ul_trace_sec_end
) {
80 status
= dev_get_symbol(dev_context
->hdev_obj
,
81 DSP_TRACESEC_END
, &ul_trace_sec_end
);
83 DBC_ASSERT(ul_trace_sec_end
!= 0);
85 if (DSP_SUCCEEDED(status
)) {
86 if ((dwDSPAddr
<= ul_trace_sec_end
) &&
87 (dwDSPAddr
>= ul_trace_sec_beg
))
91 /* If reading from TRACE, force remap/unmap */
92 if (trace_read
&& dw_base_addr
) {
94 dev_context
->dw_dsp_ext_base_addr
= 0;
98 /* Initialize ul_ext_base and ul_ext_end */
102 /* Get DYNEXT_BEG, EXT_BEG and EXT_END. */
103 if (DSP_SUCCEEDED(status
) && !ul_dyn_ext_base
) {
104 status
= dev_get_symbol(dev_context
->hdev_obj
,
105 DYNEXTBASE
, &ul_dyn_ext_base
);
107 DBC_ASSERT(ul_dyn_ext_base
!= 0);
109 if (DSP_SUCCEEDED(status
)) {
110 status
= dev_get_symbol(dev_context
->hdev_obj
,
111 EXTBASE
, &ul_ext_base
);
113 DBC_ASSERT(ul_ext_base
!= 0);
115 if (DSP_SUCCEEDED(status
)) {
116 status
= dev_get_symbol(dev_context
->hdev_obj
,
117 EXTEND
, &ul_ext_end
);
119 DBC_ASSERT(ul_ext_end
!= 0);
121 /* Trace buffer is right after the shm SEG0,
122 * so set the base address to SHMBASE */
124 ul_ext_base
= ul_shm_base_virt
;
125 ul_ext_end
= ul_trace_sec_end
;
128 DBC_ASSERT(ul_ext_end
!= 0);
129 DBC_ASSERT(ul_ext_end
> ul_ext_base
);
131 if (ul_ext_end
< ul_ext_base
)
134 if (DSP_SUCCEEDED(status
)) {
136 dev_context
->atlb_entry
[0].ul_dsp_va
* DSPWORDSIZE
;
137 DBC_ASSERT(ul_tlb_base_virt
<= ul_shm_base_virt
);
138 dw_ext_prog_virt_mem
=
139 dev_context
->atlb_entry
[0].ul_gpp_va
;
143 ul_shm_base_virt
- ul_tlb_base_virt
;
144 ul_shm_offset_virt
+=
145 PG_ALIGN_HIGH(ul_ext_end
- ul_dyn_ext_base
+
146 1, HW_PAGE_SIZE64KB
);
147 dw_ext_prog_virt_mem
-= ul_shm_offset_virt
;
148 dw_ext_prog_virt_mem
+=
149 (ul_ext_base
- ul_dyn_ext_base
);
150 dev_context
->dw_dsp_ext_base_addr
=
151 dw_ext_prog_virt_mem
;
154 * This dw_dsp_ext_base_addr will get cleared
155 * only when the board is stopped.
157 if (!dev_context
->dw_dsp_ext_base_addr
)
161 dw_base_addr
= dw_ext_prog_virt_mem
;
165 if (!dw_base_addr
|| !ul_ext_base
|| !ul_ext_end
)
168 offset
= dwDSPAddr
- ul_ext_base
;
170 if (DSP_SUCCEEDED(status
))
171 memcpy(pbHostBuf
, (u8
*) dw_base_addr
+ offset
, ul_num_bytes
);
177 * ======== write_dsp_data ========
179 * Copies buffers to the DSP internal/external memory.
181 int write_dsp_data(struct bridge_dev_context
*hDevContext
,
182 IN u8
*pbHostBuf
, u32 dwDSPAddr
, u32 ul_num_bytes
,
186 u32 dw_base_addr
= hDevContext
->dw_dsp_base_addr
;
187 struct cfg_hostres
*resources
= hDevContext
->resources
;
189 u32 base1
, base2
, base3
;
190 base1
= OMAP_DSP_MEM1_SIZE
;
191 base2
= OMAP_DSP_MEM2_BASE
- OMAP_DSP_MEM1_BASE
;
192 base3
= OMAP_DSP_MEM3_BASE
- OMAP_DSP_MEM1_BASE
;
197 offset
= dwDSPAddr
- hDevContext
->dw_dsp_start_add
;
198 if (offset
< base1
) {
199 dw_base_addr
= MEM_LINEAR_ADDRESS(resources
->dw_mem_base
[2],
200 resources
->dw_mem_length
[2]);
201 } else if (offset
> base1
&& offset
< base2
+ OMAP_DSP_MEM2_SIZE
) {
202 dw_base_addr
= MEM_LINEAR_ADDRESS(resources
->dw_mem_base
[3],
203 resources
->dw_mem_length
[3]);
204 offset
= offset
- base2
;
205 } else if (offset
>= base2
+ OMAP_DSP_MEM2_SIZE
&&
206 offset
< base3
+ OMAP_DSP_MEM3_SIZE
) {
207 dw_base_addr
= MEM_LINEAR_ADDRESS(resources
->dw_mem_base
[4],
208 resources
->dw_mem_length
[4]);
209 offset
= offset
- base3
;
214 memcpy((u8
*) (dw_base_addr
+ offset
), pbHostBuf
, ul_num_bytes
);
216 *((u32
*) pbHostBuf
) = dw_base_addr
+ offset
;
222 * ======== write_ext_dsp_data ========
224 * Copies buffers to the external memory.
227 int write_ext_dsp_data(struct bridge_dev_context
*dev_context
,
228 IN u8
*pbHostBuf
, u32 dwDSPAddr
,
229 u32 ul_num_bytes
, u32 ulMemType
,
232 u32 dw_base_addr
= dev_context
->dw_dsp_ext_base_addr
;
234 u8 temp_byte1
, temp_byte2
;
238 u32 dw_ext_prog_virt_mem
;
239 u32 ul_tlb_base_virt
= 0;
240 u32 ul_shm_offset_virt
= 0;
241 struct cfg_hostres
*host_res
= dev_context
->resources
;
242 bool trace_load
= false;
246 if (symbols_reloaded
) {
247 /* Check if it is a load to Trace section */
248 ret
= dev_get_symbol(dev_context
->hdev_obj
,
249 DSP_TRACESEC_BEG
, &ul_trace_sec_beg
);
250 if (DSP_SUCCEEDED(ret
))
251 ret
= dev_get_symbol(dev_context
->hdev_obj
,
255 if (DSP_SUCCEEDED(ret
)) {
256 if ((dwDSPAddr
<= ul_trace_sec_end
) &&
257 (dwDSPAddr
>= ul_trace_sec_beg
))
261 /* If dynamic, force remap/unmap */
262 if ((bDynamicLoad
|| trace_load
) && dw_base_addr
) {
264 MEM_UNMAP_LINEAR_ADDRESS((void *)
265 dev_context
->dw_dsp_ext_base_addr
);
266 dev_context
->dw_dsp_ext_base_addr
= 0x0;
269 if (symbols_reloaded
)
270 /* Get SHM_BEG EXT_BEG and EXT_END. */
271 ret
= dev_get_symbol(dev_context
->hdev_obj
,
272 SHMBASENAME
, &ul_shm_base_virt
);
273 DBC_ASSERT(ul_shm_base_virt
!= 0);
275 if (DSP_SUCCEEDED(ret
)) {
276 if (symbols_reloaded
)
279 (dev_context
->hdev_obj
, DYNEXTBASE
,
282 DBC_ASSERT(ul_ext_base
!= 0);
283 if (DSP_SUCCEEDED(ret
)) {
284 /* DR OMAPS00013235 : DLModules array may be
285 * in EXTMEM. It is expected that DYNEXTMEM and
286 * EXTMEM are contiguous, so checking for the
287 * upper bound at EXTEND should be Ok. */
288 if (symbols_reloaded
)
291 (dev_context
->hdev_obj
, EXTEND
,
295 if (symbols_reloaded
) {
296 if (DSP_SUCCEEDED(ret
))
299 (dev_context
->hdev_obj
, EXTBASE
,
301 DBC_ASSERT(ul_ext_base
!= 0);
302 if (DSP_SUCCEEDED(ret
))
305 (dev_context
->hdev_obj
, EXTEND
,
309 /* Trace buffer it right after the shm SEG0, so set the
310 * base address to SHMBASE */
312 ul_ext_base
= ul_shm_base_virt
;
314 DBC_ASSERT(ul_ext_end
!= 0);
315 DBC_ASSERT(ul_ext_end
> ul_ext_base
);
316 if (ul_ext_end
< ul_ext_base
)
319 if (DSP_SUCCEEDED(ret
)) {
321 dev_context
->atlb_entry
[0].ul_dsp_va
* DSPWORDSIZE
;
322 DBC_ASSERT(ul_tlb_base_virt
<= ul_shm_base_virt
);
324 if (symbols_reloaded
) {
325 if (DSP_SUCCEEDED(ret
)) {
328 (dev_context
->hdev_obj
,
329 DSP_TRACESEC_END
, &shm0_end
);
331 if (DSP_SUCCEEDED(ret
)) {
334 (dev_context
->hdev_obj
, DYNEXTBASE
,
339 ul_shm_base_virt
- ul_tlb_base_virt
;
341 dw_ext_prog_virt_mem
=
342 dev_context
->atlb_entry
[0].ul_gpp_va
;
344 dw_ext_prog_virt_mem
= host_res
->dw_mem_base
[1];
345 dw_ext_prog_virt_mem
+=
346 (ul_ext_base
- ul_dyn_ext_base
);
349 dev_context
->dw_dsp_ext_base_addr
=
350 (u32
) MEM_LINEAR_ADDRESS((void *)
351 dw_ext_prog_virt_mem
,
352 ul_ext_end
- ul_ext_base
);
353 dw_base_addr
+= dev_context
->dw_dsp_ext_base_addr
;
354 /* This dw_dsp_ext_base_addr will get cleared only when
355 * the board is stopped. */
356 if (!dev_context
->dw_dsp_ext_base_addr
)
360 if (!dw_base_addr
|| !ul_ext_base
|| !ul_ext_end
)
363 if (DSP_SUCCEEDED(ret
)) {
364 for (i
= 0; i
< 4; i
++)
365 remain_byte
[i
] = 0x0;
367 dw_offset
= dwDSPAddr
- ul_ext_base
;
368 /* Also make sure the dwDSPAddr is < ul_ext_end */
369 if (dwDSPAddr
> ul_ext_end
|| dw_offset
> dwDSPAddr
)
372 if (DSP_SUCCEEDED(ret
)) {
374 memcpy((u8
*) dw_base_addr
+ dw_offset
, pbHostBuf
,
377 *((u32
*) pbHostBuf
) = dw_base_addr
+ dw_offset
;
379 /* Unmap here to force remap for other Ext loads */
380 if ((bDynamicLoad
|| trace_load
) && dev_context
->dw_dsp_ext_base_addr
) {
381 MEM_UNMAP_LINEAR_ADDRESS((void *)
382 dev_context
->dw_dsp_ext_base_addr
);
383 dev_context
->dw_dsp_ext_base_addr
= 0x0;
385 symbols_reloaded
= false;
389 int sm_interrupt_dsp(struct bridge_dev_context
*dev_context
, u16 mb_val
)
391 #ifdef CONFIG_TIDSPBRIDGE_DVFS
394 struct dspbridge_platform_data
*pdata
=
395 omap_dspbridge_dev
->dev
.platform_data
;
396 struct cfg_hostres
*resources
= dev_context
->resources
;
400 if (!dev_context
->mbox
)
406 if (dev_context
->dw_brd_state
== BRD_DSP_HIBERNATION
||
407 dev_context
->dw_brd_state
== BRD_HIBERNATION
) {
408 #ifdef CONFIG_TIDSPBRIDGE_DVFS
409 if (pdata
->dsp_get_opp
)
410 opplevel
= (*pdata
->dsp_get_opp
) ();
411 if (opplevel
== VDD1_OPP1
) {
412 if (pdata
->dsp_set_min_opp
)
413 (*pdata
->dsp_set_min_opp
) (VDD1_OPP2
);
416 /* Restart the peripheral clocks */
417 dsp_clock_enable_all(dev_context
->dsp_per_clks
);
418 dsp_wdt_enable(true);
421 * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control
422 * in CM_AUTOIDLE_PLL_IVA2 register
424 (*pdata
->dsp_cm_write
)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT
,
425 OMAP3430_IVA2_MOD
, OMAP3430_CM_AUTOIDLE_PLL
);
428 * 7:4 IVA2_DPLL_FREQSEL - IVA2 internal frq set to
430 * 2:0 EN_IVA2_DPLL - Enable IVA2 DPLL in lock mode
432 (*pdata
->dsp_cm_rmw_bits
)(OMAP3430_IVA2_DPLL_FREQSEL_MASK
|
433 OMAP3430_EN_IVA2_DPLL_MASK
,
434 0x3 << OMAP3430_IVA2_DPLL_FREQSEL_SHIFT
|
435 0x7 << OMAP3430_EN_IVA2_DPLL_SHIFT
,
436 OMAP3430_IVA2_MOD
, OMAP3430_CM_CLKEN_PLL
);
438 /* Restore mailbox settings */
439 omap_mbox_restore_ctx(dev_context
->mbox
);
441 /* Access MMU SYS CONFIG register to generate a short wakeup */
442 temp
= *(reg_uword32
*) (resources
->dw_dmmu_base
+ 0x10);
444 dev_context
->dw_brd_state
= BRD_RUNNING
;
445 } else if (dev_context
->dw_brd_state
== BRD_RETENTION
) {
446 /* Restart the peripheral clocks */
447 dsp_clock_enable_all(dev_context
->dsp_per_clks
);
450 status
= omap_mbox_msg_send(dev_context
->mbox
, mb_val
);
453 pr_err("omap_mbox_msg_send Fail and status = %d\n", status
);