GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / tidspbridge / core / tiomap_io.c
blob190c028afe9b5c2801912383a0d8765d40ea1974
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 *dev_ctxt,
54 u8 *host_buff, u32 dsp_addr,
55 u32 ul_num_bytes, u32 mem_type)
57 int status = 0;
58 struct bridge_dev_context *dev_context = dev_ctxt;
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 (!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);
85 if (!status) {
86 if ((dsp_addr <= ul_trace_sec_end) &&
87 (dsp_addr >= 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 (!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 (!status) {
110 status = dev_get_symbol(dev_context->hdev_obj,
111 EXTBASE, &ul_ext_base);
113 DBC_ASSERT(ul_ext_base != 0);
115 if (!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 (!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 = dsp_addr - ul_ext_base;
170 if (!status)
171 memcpy(host_buff, (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 *dev_context,
182 u8 *host_buff, u32 dsp_addr, u32 ul_num_bytes,
183 u32 mem_type)
185 u32 offset;
186 u32 dw_base_addr = dev_context->dw_dsp_base_addr;
187 struct cfg_hostres *resources = dev_context->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 = 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;
210 } else {
211 return -EPERM;
213 if (ul_num_bytes)
214 memcpy((u8 *) (dw_base_addr + offset), host_buff, ul_num_bytes);
215 else
216 *((u32 *) host_buff) = 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 u8 *host_buff, u32 dsp_addr,
229 u32 ul_num_bytes, u32 mem_type,
230 bool dynamic_load)
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 (!ret)
251 ret = dev_get_symbol(dev_context->hdev_obj,
252 DSP_TRACESEC_END,
253 &ul_trace_sec_end);
255 if (!ret) {
256 if ((dsp_addr <= ul_trace_sec_end) &&
257 (dsp_addr >= ul_trace_sec_beg))
258 trace_load = true;
261 /* If dynamic, force remap/unmap */
262 if ((dynamic_load || 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 (dynamic_load) {
275 if (!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 (!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 (!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 (!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 (!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 ret = dev_get_symbol
326 (dev_context->hdev_obj,
327 DSP_TRACESEC_END, &shm0_end);
328 if (!ret) {
329 ret =
330 dev_get_symbol
331 (dev_context->hdev_obj, DYNEXTBASE,
332 &ul_dyn_ext_base);
335 ul_shm_offset_virt =
336 ul_shm_base_virt - ul_tlb_base_virt;
337 if (trace_load) {
338 dw_ext_prog_virt_mem =
339 dev_context->atlb_entry[0].ul_gpp_va;
340 } else {
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)
354 ret = -EPERM;
357 if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
358 ret = -EPERM;
360 if (!ret) {
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)
367 ret = -EPERM;
369 if (!ret) {
370 if (ul_num_bytes)
371 memcpy((u8 *) dw_base_addr + dw_offset, host_buff,
372 ul_num_bytes);
373 else
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;
383 return ret;
386 int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
388 #ifdef CONFIG_TIDSPBRIDGE_DVFS
389 u32 opplevel = 0;
390 #endif
391 struct dspbridge_platform_data *pdata =
392 omap_dspbridge_dev->dev.platform_data;
393 struct cfg_hostres *resources = dev_context->resources;
394 int status = 0;
395 u32 temp;
397 if (!dev_context->mbox)
398 return 0;
400 if (!resources)
401 return -EPERM;
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);
412 #endif
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
426 * 0.75 MHz - 1.0 MHz
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);
449 if (status) {
450 pr_err("omap_mbox_msg_send Fail and status = %d\n", status);
451 status = -EPERM;
454 return 0;