]> Pileus Git - ~andy/linux/blob - drivers/staging/tidspbridge/core/tiomap_io.c
staging: ti dspbridge: make variables in prototypes match within functions definitions
[~andy/linux] / drivers / staging / tidspbridge / core / tiomap_io.c
1 /*
2  * tiomap_io.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Implementation for the io read/write routines.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
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.
13  *
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.
17  */
18
19 /*  ----------------------------------- DSP/BIOS Bridge */
20 #include <dspbridge/dbdefs.h>
21
22 /*  ----------------------------------- Trace & Debug */
23 #include <dspbridge/dbc.h>
24
25 /*  ----------------------------------- Platform Manager */
26 #include <dspbridge/dev.h>
27 #include <dspbridge/drv.h>
28
29 /*  ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/wdt.h>
32
33 /*  ----------------------------------- specific to this file */
34 #include "_tiomap.h"
35 #include "_tiomap_pwr.h"
36 #include "tiomap_io.h"
37
38 static u32 ul_ext_base;
39 static u32 ul_ext_end;
40
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;
46
47 bool symbols_reloaded = true;
48
49 /*
50  *  ======== read_ext_dsp_data ========
51  *      Copies DSP external memory buffers to the host side buffers.
52  */
53 int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
54                              OUT u8 *host_buff, u32 dsp_addr,
55                              u32 ul_num_bytes, u32 mem_type)
56 {
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;
65
66         if (!ul_shm_base_virt) {
67                 status = dev_get_symbol(dev_context->hdev_obj,
68                                         SHMBASENAME, &ul_shm_base_virt);
69         }
70         DBC_ASSERT(ul_shm_base_virt != 0);
71
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);
76         }
77         DBC_ASSERT(ul_trace_sec_beg != 0);
78
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);
82         }
83         DBC_ASSERT(ul_trace_sec_end != 0);
84
85         if (DSP_SUCCEEDED(status)) {
86                 if ((dsp_addr <= ul_trace_sec_end) &&
87                     (dsp_addr >= ul_trace_sec_beg))
88                         trace_read = true;
89         }
90
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;
95         }
96
97         if (!dw_base_addr) {
98                 /* Initialize ul_ext_base and ul_ext_end */
99                 ul_ext_base = 0;
100                 ul_ext_end = 0;
101
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);
106                 }
107                 DBC_ASSERT(ul_dyn_ext_base != 0);
108
109                 if (DSP_SUCCEEDED(status)) {
110                         status = dev_get_symbol(dev_context->hdev_obj,
111                                                 EXTBASE, &ul_ext_base);
112                 }
113                 DBC_ASSERT(ul_ext_base != 0);
114
115                 if (DSP_SUCCEEDED(status)) {
116                         status = dev_get_symbol(dev_context->hdev_obj,
117                                                 EXTEND, &ul_ext_end);
118                 }
119                 DBC_ASSERT(ul_ext_end != 0);
120
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;
126                 }
127
128                 DBC_ASSERT(ul_ext_end != 0);
129                 DBC_ASSERT(ul_ext_end > ul_ext_base);
130
131                 if (ul_ext_end < ul_ext_base)
132                         status = -EPERM;
133
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;
140
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;
152
153                                 /*
154                                  * This dw_dsp_ext_base_addr will get cleared
155                                  * only when the board is stopped.
156                                 */
157                                 if (!dev_context->dw_dsp_ext_base_addr)
158                                         status = -EPERM;
159                         }
160
161                         dw_base_addr = dw_ext_prog_virt_mem;
162                 }
163         }
164
165         if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
166                 status = -EPERM;
167
168         offset = dsp_addr - ul_ext_base;
169
170         if (DSP_SUCCEEDED(status))
171                 memcpy(host_buff, (u8 *) dw_base_addr + offset, ul_num_bytes);
172
173         return status;
174 }
175
176 /*
177  *  ======== write_dsp_data ========
178  *  purpose:
179  *      Copies buffers to the DSP internal/external memory.
180  */
181 int write_dsp_data(struct bridge_dev_context *dev_context,
182                           IN u8 *host_buff, u32 dsp_addr, u32 ul_num_bytes,
183                           u32 mem_type)
184 {
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;
193
194         if (!resources)
195                 return -EPERM;
196
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;
212         }
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;
217
218         return status;
219 }
220
221 /*
222  *  ======== write_ext_dsp_data ========
223  *  purpose:
224  *      Copies buffers to the external memory.
225  *
226  */
227 int write_ext_dsp_data(struct bridge_dev_context *dev_context,
228                               IN u8 *host_buff, u32 dsp_addr,
229                               u32 ul_num_bytes, u32 mem_type,
230                               bool dynamic_load)
231 {
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;
245
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);
254         }
255         if (DSP_SUCCEEDED(ret)) {
256                 if ((dsp_addr <= ul_trace_sec_end) &&
257                     (dsp_addr >= ul_trace_sec_beg))
258                         trace_load = true;
259         }
260
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;
267         }
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 (DSP_SUCCEEDED(ret)) {
276                                 if (symbols_reloaded)
277                                         ret =
278                                             dev_get_symbol
279                                             (dev_context->hdev_obj, DYNEXTBASE,
280                                              &ul_ext_base);
281                         }
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);
293                         }
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);
307                         }
308                 }
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;
313
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;
318
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);
323
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);
330                                 }
331                                 if (DSP_SUCCEEDED(ret)) {
332                                         ret =
333                                             dev_get_symbol
334                                             (dev_context->hdev_obj, DYNEXTBASE,
335                                              &ul_dyn_ext_base);
336                                 }
337                         }
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);
347                         }
348
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;
358                 }
359         }
360         if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
361                 ret = -EPERM;
362
363         if (DSP_SUCCEEDED(ret)) {
364                 for (i = 0; i < 4; i++)
365                         remain_byte[i] = 0x0;
366
367                 dw_offset = dsp_addr - ul_ext_base;
368                 /* Also make sure the dsp_addr is < ul_ext_end */
369                 if (dsp_addr > ul_ext_end || dw_offset > dsp_addr)
370                         ret = -EPERM;
371         }
372         if (DSP_SUCCEEDED(ret)) {
373                 if (ul_num_bytes)
374                         memcpy((u8 *) dw_base_addr + dw_offset, host_buff,
375                                ul_num_bytes);
376                 else
377                         *((u32 *) host_buff) = dw_base_addr + dw_offset;
378         }
379         /* Unmap here to force remap for other Ext loads */
380         if ((dynamic_load || 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;
384         }
385         symbols_reloaded = false;
386         return ret;
387 }
388
389 int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
390 {
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;
399
400         if (!dev_context->mbox)
401                 return 0;
402
403         if (!resources)
404                 return -EPERM;
405
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);
414                 }
415 #endif
416                 /* Restart the peripheral clocks */
417                 dsp_clock_enable_all(dev_context->dsp_per_clks);
418                 dsp_wdt_enable(true);
419
420                 /*
421                  * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control
422                  *     in CM_AUTOIDLE_PLL_IVA2 register
423                  */
424                 (*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
425                                 OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL);
426
427                 /*
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
431                  */
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);
437
438                 /* Restore mailbox settings */
439                 omap_mbox_restore_ctx(dev_context->mbox);
440
441                 /* Access MMU SYS CONFIG register to generate a short wakeup */
442                 temp = *(reg_uword32 *) (resources->dw_dmmu_base + 0x10);
443
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);
448         }
449
450         status = omap_mbox_msg_send(dev_context->mbox, mb_val);
451
452         if (status) {
453                 pr_err("omap_mbox_msg_send Fail and status = %d\n", status);
454                 status = -EPERM;
455         }
456
457         return 0;
458 }