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
*dev_ctxt
,
54 u8
*host_buff
, u32 dsp_addr
,
55 u32 ul_num_bytes
, u32 mem_type
)
58 struct bridge_dev_context
*dev_context
= dev_ctxt
;
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 (!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 (!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);
86 if ((dsp_addr
<= ul_trace_sec_end
) &&
87 (dsp_addr
>= 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 (!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);
110 status
= dev_get_symbol(dev_context
->hdev_obj
,
111 EXTBASE
, &ul_ext_base
);
113 DBC_ASSERT(ul_ext_base
!= 0);
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
)
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
= dsp_addr
- ul_ext_base
;
171 memcpy(host_buff
, (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
*dev_context
,
182 u8
*host_buff
, u32 dsp_addr
, u32 ul_num_bytes
,
186 u32 dw_base_addr
= dev_context
->dw_dsp_base_addr
;
187 struct cfg_hostres
*resources
= dev_context
->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
= dsp_addr
- dev_context
->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
), host_buff
, ul_num_bytes
);
216 *((u32
*) host_buff
) = 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 u8
*host_buff
, u32 dsp_addr
,
229 u32 ul_num_bytes
, u32 mem_type
,
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
);
251 ret
= dev_get_symbol(dev_context
->hdev_obj
,
256 if ((dsp_addr
<= ul_trace_sec_end
) &&
257 (dsp_addr
>= ul_trace_sec_beg
))
261 /* If dynamic, force remap/unmap */
262 if ((dynamic_load
|| 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);
276 if (symbols_reloaded
)
279 (dev_context
->hdev_obj
, DYNEXTBASE
,
282 DBC_ASSERT(ul_ext_base
!= 0);
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
) {
299 (dev_context
->hdev_obj
, EXTBASE
,
301 DBC_ASSERT(ul_ext_base
!= 0);
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
)
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
) {
326 (dev_context
->hdev_obj
,
327 DSP_TRACESEC_END
, &shm0_end
);
331 (dev_context
->hdev_obj
, DYNEXTBASE
,
336 ul_shm_base_virt
- ul_tlb_base_virt
;
338 dw_ext_prog_virt_mem
=
339 dev_context
->atlb_entry
[0].ul_gpp_va
;
341 dw_ext_prog_virt_mem
= host_res
->dw_mem_base
[1];
342 dw_ext_prog_virt_mem
+=
343 (ul_ext_base
- ul_dyn_ext_base
);
346 dev_context
->dw_dsp_ext_base_addr
=
347 (u32
) MEM_LINEAR_ADDRESS((void *)
348 dw_ext_prog_virt_mem
,
349 ul_ext_end
- ul_ext_base
);
350 dw_base_addr
+= dev_context
->dw_dsp_ext_base_addr
;
351 /* This dw_dsp_ext_base_addr will get cleared only when
352 * the board is stopped. */
353 if (!dev_context
->dw_dsp_ext_base_addr
)
357 if (!dw_base_addr
|| !ul_ext_base
|| !ul_ext_end
)
361 for (i
= 0; i
< 4; i
++)
362 remain_byte
[i
] = 0x0;
364 dw_offset
= dsp_addr
- ul_ext_base
;
365 /* Also make sure the dsp_addr is < ul_ext_end */
366 if (dsp_addr
> ul_ext_end
|| dw_offset
> dsp_addr
)
371 memcpy((u8
*) dw_base_addr
+ dw_offset
, host_buff
,
374 *((u32
*) host_buff
) = dw_base_addr
+ dw_offset
;
376 /* Unmap here to force remap for other Ext loads */
377 if ((dynamic_load
|| trace_load
) && dev_context
->dw_dsp_ext_base_addr
) {
378 MEM_UNMAP_LINEAR_ADDRESS((void *)
379 dev_context
->dw_dsp_ext_base_addr
);
380 dev_context
->dw_dsp_ext_base_addr
= 0x0;
382 symbols_reloaded
= false;
386 int sm_interrupt_dsp(struct bridge_dev_context
*dev_context
, u16 mb_val
)
388 #ifdef CONFIG_TIDSPBRIDGE_DVFS
391 struct dspbridge_platform_data
*pdata
=
392 omap_dspbridge_dev
->dev
.platform_data
;
393 struct cfg_hostres
*resources
= dev_context
->resources
;
397 if (!dev_context
->mbox
)
403 if (dev_context
->dw_brd_state
== BRD_DSP_HIBERNATION
||
404 dev_context
->dw_brd_state
== BRD_HIBERNATION
) {
405 #ifdef CONFIG_TIDSPBRIDGE_DVFS
406 if (pdata
->dsp_get_opp
)
407 opplevel
= (*pdata
->dsp_get_opp
) ();
408 if (opplevel
== VDD1_OPP1
) {
409 if (pdata
->dsp_set_min_opp
)
410 (*pdata
->dsp_set_min_opp
) (VDD1_OPP2
);
413 /* Restart the peripheral clocks */
414 dsp_clock_enable_all(dev_context
->dsp_per_clks
);
415 dsp_wdt_enable(true);
418 * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control
419 * in CM_AUTOIDLE_PLL_IVA2 register
421 (*pdata
->dsp_cm_write
)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT
,
422 OMAP3430_IVA2_MOD
, OMAP3430_CM_AUTOIDLE_PLL
);
425 * 7:4 IVA2_DPLL_FREQSEL - IVA2 internal frq set to
427 * 2:0 EN_IVA2_DPLL - Enable IVA2 DPLL in lock mode
429 (*pdata
->dsp_cm_rmw_bits
)(OMAP3430_IVA2_DPLL_FREQSEL_MASK
|
430 OMAP3430_EN_IVA2_DPLL_MASK
,
431 0x3 << OMAP3430_IVA2_DPLL_FREQSEL_SHIFT
|
432 0x7 << OMAP3430_EN_IVA2_DPLL_SHIFT
,
433 OMAP3430_IVA2_MOD
, OMAP3430_CM_CLKEN_PLL
);
435 /* Restore mailbox settings */
436 omap_mbox_restore_ctx(dev_context
->mbox
);
438 /* Access MMU SYS CONFIG register to generate a short wakeup */
439 temp
= readl(resources
->dw_dmmu_base
+ 0x10);
441 dev_context
->dw_brd_state
= BRD_RUNNING
;
442 } else if (dev_context
->dw_brd_state
== BRD_RETENTION
) {
443 /* Restart the peripheral clocks */
444 dsp_clock_enable_all(dev_context
->dsp_per_clks
);
447 status
= omap_mbox_msg_send(dev_context
->mbox
, mb_val
);
450 pr_err("omap_mbox_msg_send Fail and status = %d\n", status
);