staging: ti dspbridge: prefix configs with TIDSPBRIDGE
[linux-2.6.git] / drivers / staging / tidspbridge / core / tiomap_io.c
blobe7cfbee570738e18a033baaa942b63d57eed68b2
1 /*
2 * tiomap_io.c
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 */
34 #include "_tiomap.h"
35 #include "_tiomap_pwr.h"
36 #include "tiomap_io.h"
38 static u32 ul_ext_base;
39 static u32 ul_ext_end;
41 static u32 shm0_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)
57 int status = 0;
58 struct bridge_dev_context *dev_context = hDevContext;
59 u32 offset;
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))
88 trace_read = true;
91 /* If reading from TRACE, force remap/unmap */
92 if (trace_read && dw_base_addr) {
93 dw_base_addr = 0;
94 dev_context->dw_dsp_ext_base_addr = 0;
97 if (!dw_base_addr) {
98 /* Initialize ul_ext_base and ul_ext_end */
99 ul_ext_base = 0;
100 ul_ext_end = 0;
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 */
123 if (trace_read) {
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)
132 status = -EPERM;
134 if (DSP_SUCCEEDED(status)) {
135 ul_tlb_base_virt =
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;
141 if (!trace_read) {
142 ul_shm_offset_virt =
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)
158 status = -EPERM;
161 dw_base_addr = dw_ext_prog_virt_mem;
165 if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
166 status = -EPERM;
168 offset = dwDSPAddr - ul_ext_base;
170 if (DSP_SUCCEEDED(status))
171 memcpy(pbHostBuf, (u8 *) dw_base_addr + offset, ul_num_bytes);
173 return status;
177 * ======== write_dsp_data ========
178 * purpose:
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,
183 u32 ulMemType)
185 u32 offset;
186 u32 dw_base_addr = hDevContext->dw_dsp_base_addr;
187 struct cfg_hostres *resources = hDevContext->resources;
188 int status = 0;
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;
194 if (!resources)
195 return -EPERM;
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;
210 } else {
211 return -EPERM;
213 if (ul_num_bytes)
214 memcpy((u8 *) (dw_base_addr + offset), pbHostBuf, ul_num_bytes);
215 else
216 *((u32 *) pbHostBuf) = dw_base_addr + offset;
218 return status;
222 * ======== write_ext_dsp_data ========
223 * purpose:
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,
230 bool bDynamicLoad)
232 u32 dw_base_addr = dev_context->dw_dsp_ext_base_addr;
233 u32 dw_offset = 0;
234 u8 temp_byte1, temp_byte2;
235 u8 remain_byte[4];
236 s32 i;
237 int ret = 0;
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;
243 temp_byte1 = 0x0;
244 temp_byte2 = 0x0;
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,
252 DSP_TRACESEC_END,
253 &ul_trace_sec_end);
255 if (DSP_SUCCEEDED(ret)) {
256 if ((dwDSPAddr <= ul_trace_sec_end) &&
257 (dwDSPAddr >= ul_trace_sec_beg))
258 trace_load = true;
261 /* If dynamic, force remap/unmap */
262 if ((bDynamicLoad || trace_load) && dw_base_addr) {
263 dw_base_addr = 0;
264 MEM_UNMAP_LINEAR_ADDRESS((void *)
265 dev_context->dw_dsp_ext_base_addr);
266 dev_context->dw_dsp_ext_base_addr = 0x0;
268 if (!dw_base_addr) {
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);
274 if (bDynamicLoad) {
275 if (DSP_SUCCEEDED(ret)) {
276 if (symbols_reloaded)
277 ret =
278 dev_get_symbol
279 (dev_context->hdev_obj, DYNEXTBASE,
280 &ul_ext_base);
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)
289 ret =
290 dev_get_symbol
291 (dev_context->hdev_obj, EXTEND,
292 &ul_ext_end);
294 } else {
295 if (symbols_reloaded) {
296 if (DSP_SUCCEEDED(ret))
297 ret =
298 dev_get_symbol
299 (dev_context->hdev_obj, EXTBASE,
300 &ul_ext_base);
301 DBC_ASSERT(ul_ext_base != 0);
302 if (DSP_SUCCEEDED(ret))
303 ret =
304 dev_get_symbol
305 (dev_context->hdev_obj, EXTEND,
306 &ul_ext_end);
309 /* Trace buffer it right after the shm SEG0, so set the
310 * base address to SHMBASE */
311 if (trace_load)
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)
317 ret = -EPERM;
319 if (DSP_SUCCEEDED(ret)) {
320 ul_tlb_base_virt =
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)) {
326 ret =
327 dev_get_symbol
328 (dev_context->hdev_obj,
329 DSP_TRACESEC_END, &shm0_end);
331 if (DSP_SUCCEEDED(ret)) {
332 ret =
333 dev_get_symbol
334 (dev_context->hdev_obj, DYNEXTBASE,
335 &ul_dyn_ext_base);
338 ul_shm_offset_virt =
339 ul_shm_base_virt - ul_tlb_base_virt;
340 if (trace_load) {
341 dw_ext_prog_virt_mem =
342 dev_context->atlb_entry[0].ul_gpp_va;
343 } else {
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)
357 ret = -EPERM;
360 if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
361 ret = -EPERM;
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)
370 ret = -EPERM;
372 if (DSP_SUCCEEDED(ret)) {
373 if (ul_num_bytes)
374 memcpy((u8 *) dw_base_addr + dw_offset, pbHostBuf,
375 ul_num_bytes);
376 else
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;
386 return ret;
389 int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
391 #ifdef CONFIG_TIDSPBRIDGE_DVFS
392 u32 opplevel = 0;
393 #endif
394 struct dspbridge_platform_data *pdata =
395 omap_dspbridge_dev->dev.platform_data;
396 struct cfg_hostres *resources = dev_context->resources;
397 int status = 0;
398 u32 temp;
400 if (!dev_context->mbox)
401 return 0;
403 if (!resources)
404 return -EPERM;
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);
415 #endif
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
429 * 0.75 MHz - 1.0 MHz
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);
452 if (status) {
453 pr_err("omap_mbox_msg_send Fail and status = %d\n", status);
454 status = -EPERM;
457 return 0;