blob: b740edc29b1c904fc0af5b2a4d7e55d862733923 [file] [log] [blame]
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Hardware Programming Interface (HPI) for AudioScience
20 ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters.
21 These PCI and PCIe bus adapters are based on a
22 TMS320C6205 PCI bus mastering DSP,
23 and (except ASI50xx) TI TMS320C6xxx floating point DSP
24
25 Exported function:
26 void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
27
28(C) Copyright AudioScience Inc. 1998-2010
29*******************************************************************************/
30#define SOURCEFILE_NAME "hpi6205.c"
31
32#include "hpi_internal.h"
33#include "hpimsginit.h"
34#include "hpidebug.h"
35#include "hpi6205.h"
36#include "hpidspcd.h"
37#include "hpicmn.h"
38
39/*****************************************************************************/
40/* HPI6205 specific error codes */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130041#define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */
42
43/* operational/messaging errors */
44#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015
45#define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016
46
47/* initialization/bootload errors */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020048#define HPI6205_ERROR_6205_NO_IRQ 1002
49#define HPI6205_ERROR_6205_INIT_FAILED 1003
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020050#define HPI6205_ERROR_6205_REG 1006
51#define HPI6205_ERROR_6205_DSPPAGE 1007
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020052#define HPI6205_ERROR_C6713_HPIC 1009
53#define HPI6205_ERROR_C6713_HPIA 1010
54#define HPI6205_ERROR_C6713_PLL 1011
55#define HPI6205_ERROR_DSP_INTMEM 1012
56#define HPI6205_ERROR_DSP_EXTMEM 1013
57#define HPI6205_ERROR_DSP_PLD 1014
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020058#define HPI6205_ERROR_6205_EEPROM 1017
59#define HPI6205_ERROR_DSP_EMIF 1018
60
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020061/*****************************************************************************/
62/* for C6205 PCI i/f */
63/* Host Status Register (HSR) bitfields */
64#define C6205_HSR_INTSRC 0x01
65#define C6205_HSR_INTAVAL 0x02
66#define C6205_HSR_INTAM 0x04
67#define C6205_HSR_CFGERR 0x08
68#define C6205_HSR_EEREAD 0x10
69/* Host-to-DSP Control Register (HDCR) bitfields */
70#define C6205_HDCR_WARMRESET 0x01
71#define C6205_HDCR_DSPINT 0x02
72#define C6205_HDCR_PCIBOOT 0x04
73/* DSP Page Register (DSPP) bitfields, */
74/* defines 4 Mbyte page that BAR0 points to */
75#define C6205_DSPP_MAP1 0x400
76
77/* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP.
78 * BAR1 maps to non-prefetchable 8 Mbyte memory block
79 * of DSP memory mapped registers (starting at 0x01800000).
80 * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this
81 * needs to be added to the BAR1 base address set in the PCI config reg
82 */
83#define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L)
84#define C6205_BAR1_HSR (C6205_BAR1_PCI_IO_OFFSET)
85#define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4)
86#define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8)
87
88/* used to control LED (revA) and reset C6713 (revB) */
89#define C6205_BAR0_TIMER1_CTL (0x01980000L)
90
91/* For first 6713 in CE1 space, using DA17,16,2 */
92#define HPICL_ADDR 0x01400000L
93#define HPICH_ADDR 0x01400004L
94#define HPIAL_ADDR 0x01410000L
95#define HPIAH_ADDR 0x01410004L
96#define HPIDIL_ADDR 0x01420000L
97#define HPIDIH_ADDR 0x01420004L
98#define HPIDL_ADDR 0x01430000L
99#define HPIDH_ADDR 0x01430004L
100
101#define C6713_EMIF_GCTL 0x01800000
102#define C6713_EMIF_CE1 0x01800004
103#define C6713_EMIF_CE0 0x01800008
104#define C6713_EMIF_CE2 0x01800010
105#define C6713_EMIF_CE3 0x01800014
106#define C6713_EMIF_SDRAMCTL 0x01800018
107#define C6713_EMIF_SDRAMTIMING 0x0180001C
108#define C6713_EMIF_SDRAMEXT 0x01800020
109
110struct hpi_hw_obj {
111 /* PCI registers */
112 __iomem u32 *prHSR;
113 __iomem u32 *prHDCR;
114 __iomem u32 *prDSPP;
115
116 u32 dsp_page;
117
118 struct consistent_dma_area h_locked_mem;
119 struct bus_master_interface *p_interface_buffer;
120
121 u16 flag_outstream_just_reset[HPI_MAX_STREAMS];
122 /* a non-NULL handle means there is an HPI allocated buffer */
123 struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS];
124 struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS];
125 /* non-zero size means a buffer exists, may be external */
126 u32 instream_host_buffer_size[HPI_MAX_STREAMS];
127 u32 outstream_host_buffer_size[HPI_MAX_STREAMS];
128
129 struct consistent_dma_area h_control_cache;
130 struct consistent_dma_area h_async_event_buffer;
131/* struct hpi_control_cache_single *pControlCache; */
132 struct hpi_async_event *p_async_event_buffer;
133 struct hpi_control_cache *p_cache;
134};
135
136/*****************************************************************************/
137/* local prototypes */
138
139#define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write)
140
141static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us);
142
143static void send_dsp_command(struct hpi_hw_obj *phw, int cmd);
144
145static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
146 u32 *pos_error_code);
147
148static u16 message_response_sequence(struct hpi_adapter_obj *pao,
149 struct hpi_message *phm, struct hpi_response *phr);
150
151static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
152 struct hpi_response *phr);
153
154#define HPI6205_TIMEOUT 1000000
155
156static void subsys_create_adapter(struct hpi_message *phm,
157 struct hpi_response *phr);
158static void subsys_delete_adapter(struct hpi_message *phm,
159 struct hpi_response *phr);
160
161static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
162 u32 *pos_error_code);
163
164static void delete_adapter_obj(struct hpi_adapter_obj *pao);
165
166static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
167 struct hpi_message *phm, struct hpi_response *phr);
168
169static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
170 struct hpi_message *phm, struct hpi_response *phr);
171
172static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
173 struct hpi_message *phm, struct hpi_response *phr);
174static void outstream_write(struct hpi_adapter_obj *pao,
175 struct hpi_message *phm, struct hpi_response *phr);
176
177static void outstream_get_info(struct hpi_adapter_obj *pao,
178 struct hpi_message *phm, struct hpi_response *phr);
179
180static void outstream_start(struct hpi_adapter_obj *pao,
181 struct hpi_message *phm, struct hpi_response *phr);
182
183static void outstream_open(struct hpi_adapter_obj *pao,
184 struct hpi_message *phm, struct hpi_response *phr);
185
186static void outstream_reset(struct hpi_adapter_obj *pao,
187 struct hpi_message *phm, struct hpi_response *phr);
188
189static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
190 struct hpi_message *phm, struct hpi_response *phr);
191
192static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
193 struct hpi_message *phm, struct hpi_response *phr);
194
195static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
196 struct hpi_message *phm, struct hpi_response *phr);
197
198static void instream_read(struct hpi_adapter_obj *pao,
199 struct hpi_message *phm, struct hpi_response *phr);
200
201static void instream_get_info(struct hpi_adapter_obj *pao,
202 struct hpi_message *phm, struct hpi_response *phr);
203
204static void instream_start(struct hpi_adapter_obj *pao,
205 struct hpi_message *phm, struct hpi_response *phr);
206
207static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
208 u32 address);
209
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300210static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
211 int dsp_index, u32 address, u32 data);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200212
213static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao,
214 int dsp_index);
215
216static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
217 u32 address, u32 length);
218
219static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
220 int dsp_index);
221
222static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
223 int dsp_index);
224
225static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
226
227/*****************************************************************************/
228
229static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
230{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200231 switch (phm->function) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200232 case HPI_SUBSYS_CREATE_ADAPTER:
233 subsys_create_adapter(phm, phr);
234 break;
235 case HPI_SUBSYS_DELETE_ADAPTER:
236 subsys_delete_adapter(phm, phr);
237 break;
238 default:
239 phr->error = HPI_ERROR_INVALID_FUNC;
240 break;
241 }
242}
243
244static void control_message(struct hpi_adapter_obj *pao,
245 struct hpi_message *phm, struct hpi_response *phr)
246{
247
248 struct hpi_hw_obj *phw = pao->priv;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300249 u16 pending_cache_error = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200250
251 switch (phm->function) {
252 case HPI_CONTROL_GET_STATE:
253 if (pao->has_control_cache) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300254 rmb(); /* make sure we see updates DMAed from DSP */
255 if (hpi_check_control_cache(phw->p_cache, phm, phr)) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200256 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300257 } else if (phm->u.c.attribute == HPI_METER_PEAK) {
258 pending_cache_error =
259 HPI_ERROR_CONTROL_CACHING;
260 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200261 }
262 hw_message(pao, phm, phr);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300263 if (pending_cache_error && !phr->error)
264 phr->error = pending_cache_error;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200265 break;
266 case HPI_CONTROL_GET_INFO:
267 hw_message(pao, phm, phr);
268 break;
269 case HPI_CONTROL_SET_STATE:
270 hw_message(pao, phm, phr);
271 if (pao->has_control_cache)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300272 hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm,
273 phr);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200274 break;
275 default:
276 phr->error = HPI_ERROR_INVALID_FUNC;
277 break;
278 }
279}
280
281static void adapter_message(struct hpi_adapter_obj *pao,
282 struct hpi_message *phm, struct hpi_response *phr)
283{
284 switch (phm->function) {
285 default:
286 hw_message(pao, phm, phr);
287 break;
288 }
289}
290
291static void outstream_message(struct hpi_adapter_obj *pao,
292 struct hpi_message *phm, struct hpi_response *phr)
293{
294
295 if (phm->obj_index >= HPI_MAX_STREAMS) {
296 phr->error = HPI_ERROR_INVALID_STREAM;
297 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300298 "Message referencing invalid stream %d "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200299 "on adapter index %d\n", phm->obj_index,
300 phm->adapter_index);
301 return;
302 }
303
304 switch (phm->function) {
305 case HPI_OSTREAM_WRITE:
306 outstream_write(pao, phm, phr);
307 break;
308 case HPI_OSTREAM_GET_INFO:
309 outstream_get_info(pao, phm, phr);
310 break;
311 case HPI_OSTREAM_HOSTBUFFER_ALLOC:
312 outstream_host_buffer_allocate(pao, phm, phr);
313 break;
314 case HPI_OSTREAM_HOSTBUFFER_GET_INFO:
315 outstream_host_buffer_get_info(pao, phm, phr);
316 break;
317 case HPI_OSTREAM_HOSTBUFFER_FREE:
318 outstream_host_buffer_free(pao, phm, phr);
319 break;
320 case HPI_OSTREAM_START:
321 outstream_start(pao, phm, phr);
322 break;
323 case HPI_OSTREAM_OPEN:
324 outstream_open(pao, phm, phr);
325 break;
326 case HPI_OSTREAM_RESET:
327 outstream_reset(pao, phm, phr);
328 break;
329 default:
330 hw_message(pao, phm, phr);
331 break;
332 }
333}
334
335static void instream_message(struct hpi_adapter_obj *pao,
336 struct hpi_message *phm, struct hpi_response *phr)
337{
338
339 if (phm->obj_index >= HPI_MAX_STREAMS) {
340 phr->error = HPI_ERROR_INVALID_STREAM;
341 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300342 "Message referencing invalid stream %d "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200343 "on adapter index %d\n", phm->obj_index,
344 phm->adapter_index);
345 return;
346 }
347
348 switch (phm->function) {
349 case HPI_ISTREAM_READ:
350 instream_read(pao, phm, phr);
351 break;
352 case HPI_ISTREAM_GET_INFO:
353 instream_get_info(pao, phm, phr);
354 break;
355 case HPI_ISTREAM_HOSTBUFFER_ALLOC:
356 instream_host_buffer_allocate(pao, phm, phr);
357 break;
358 case HPI_ISTREAM_HOSTBUFFER_GET_INFO:
359 instream_host_buffer_get_info(pao, phm, phr);
360 break;
361 case HPI_ISTREAM_HOSTBUFFER_FREE:
362 instream_host_buffer_free(pao, phm, phr);
363 break;
364 case HPI_ISTREAM_START:
365 instream_start(pao, phm, phr);
366 break;
367 default:
368 hw_message(pao, phm, phr);
369 break;
370 }
371}
372
373/*****************************************************************************/
374/** Entry point to this HPI backend
375 * All calls to the HPI start here
376 */
377void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
378{
379 struct hpi_adapter_obj *pao = NULL;
380
381 /* subsytem messages are processed by every HPI.
382 * All other messages are ignored unless the adapter index matches
383 * an adapter in the HPI
384 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300385 /* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject,
386 phm->wFunction); */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200387
388 /* if Dsp has crashed then do not communicate with it any more */
389 if (phm->object != HPI_OBJ_SUBSYSTEM) {
390 pao = hpi_find_adapter(phm->adapter_index);
391 if (!pao) {
392 HPI_DEBUG_LOG(DEBUG,
393 " %d,%d refused, for another HPI?\n",
394 phm->object, phm->function);
395 return;
396 }
397
398 if ((pao->dsp_crashed >= 10)
399 && (phm->function != HPI_ADAPTER_DEBUG_READ)) {
400 /* allow last resort debug read even after crash */
401 hpi_init_response(phr, phm->object, phm->function,
402 HPI_ERROR_DSP_HARDWARE);
403 HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n",
404 phm->object, phm->function);
405 return;
406 }
407 }
408
409 /* Init default response */
410 if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300411 phr->error = HPI_ERROR_PROCESSING_MESSAGE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200412
413 HPI_DEBUG_LOG(VERBOSE, "start of switch\n");
414 switch (phm->type) {
415 case HPI_TYPE_MESSAGE:
416 switch (phm->object) {
417 case HPI_OBJ_SUBSYSTEM:
418 subsys_message(phm, phr);
419 break;
420
421 case HPI_OBJ_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200422 adapter_message(pao, phm, phr);
423 break;
424
425 case HPI_OBJ_CONTROLEX:
426 case HPI_OBJ_CONTROL:
427 control_message(pao, phm, phr);
428 break;
429
430 case HPI_OBJ_OSTREAM:
431 outstream_message(pao, phm, phr);
432 break;
433
434 case HPI_OBJ_ISTREAM:
435 instream_message(pao, phm, phr);
436 break;
437
438 default:
439 hw_message(pao, phm, phr);
440 break;
441 }
442 break;
443
444 default:
445 phr->error = HPI_ERROR_INVALID_TYPE;
446 break;
447 }
448}
449
450/*****************************************************************************/
451/* SUBSYSTEM */
452
453/** Create an adapter object and initialise it based on resource information
454 * passed in in the message
455 * *** NOTE - you cannot use this function AND the FindAdapters function at the
456 * same time, the application must use only one of them to get the adapters ***
457 */
458static void subsys_create_adapter(struct hpi_message *phm,
459 struct hpi_response *phr)
460{
461 /* create temp adapter obj, because we don't know what index yet */
462 struct hpi_adapter_obj ao;
463 u32 os_error_code;
464 u16 err;
465
466 HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n");
467
468 memset(&ao, 0, sizeof(ao));
469
Julia Lawall550a8b62010-05-13 21:58:37 +0200470 ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200471 if (!ao.priv) {
472 HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
473 phr->error = HPI_ERROR_MEMORY_ALLOC;
474 return;
475 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200476
477 ao.pci = *phm->u.s.resource.r.pci;
478 err = create_adapter_obj(&ao, &os_error_code);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200479 if (err) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200480 delete_adapter_obj(&ao);
481 phr->error = err;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300482 phr->u.s.data = os_error_code;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200483 return;
484 }
485
486 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
487 phr->u.s.adapter_index = ao.index;
488 phr->u.s.num_adapters++;
489 phr->error = 0;
490}
491
492/** delete an adapter - required by WDM driver */
493static void subsys_delete_adapter(struct hpi_message *phm,
494 struct hpi_response *phr)
495{
496 struct hpi_adapter_obj *pao;
497 struct hpi_hw_obj *phw;
498
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300499 pao = hpi_find_adapter(phm->obj_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200500 if (!pao) {
501 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
502 return;
503 }
504 phw = (struct hpi_hw_obj *)pao->priv;
505 /* reset adapter h/w */
506 /* Reset C6713 #1 */
507 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
508 /* reset C6205 */
509 iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
510
511 delete_adapter_obj(pao);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300512 hpi_delete_adapter(pao);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200513 phr->error = 0;
514}
515
516/** Create adapter object
517 allocate buffers, bootload DSPs, initialise control cache
518*/
519static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
520 u32 *pos_error_code)
521{
522 struct hpi_hw_obj *phw = pao->priv;
523 struct bus_master_interface *interface;
524 u32 phys_addr;
525#ifndef HPI6205_NO_HSR_POLL
526 u32 time_out = HPI6205_TIMEOUT;
527 u32 temp1;
528#endif
529 int i;
530 u16 err;
531
532 /* init error reporting */
533 pao->dsp_crashed = 0;
534
535 for (i = 0; i < HPI_MAX_STREAMS; i++)
536 phw->flag_outstream_just_reset[i] = 1;
537
538 /* The C6205 memory area 1 is 8Mbyte window into DSP registers */
539 phw->prHSR =
540 pao->pci.ap_mem_base[1] +
541 C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);
542 phw->prHDCR =
543 pao->pci.ap_mem_base[1] +
544 C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);
545 phw->prDSPP =
546 pao->pci.ap_mem_base[1] +
547 C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);
548
549 pao->has_control_cache = 0;
550
551 if (hpios_locked_mem_alloc(&phw->h_locked_mem,
552 sizeof(struct bus_master_interface),
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300553 pao->pci.pci_dev))
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200554 phw->p_interface_buffer = NULL;
555 else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
556 (void *)&phw->p_interface_buffer))
557 phw->p_interface_buffer = NULL;
558
559 HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",
560 phw->p_interface_buffer);
561
562 if (phw->p_interface_buffer) {
563 memset((void *)phw->p_interface_buffer, 0,
564 sizeof(struct bus_master_interface));
565 phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;
566 }
567
568 err = adapter_boot_load_dsp(pao, pos_error_code);
569 if (err)
570 /* no need to clean up as SubSysCreateAdapter */
571 /* calls DeleteAdapter on error. */
572 return err;
573
574 HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
575
576 /* allow boot load even if mem alloc wont work */
577 if (!phw->p_interface_buffer)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300578 return HPI_ERROR_MEMORY_ALLOC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200579
580 interface = phw->p_interface_buffer;
581
582#ifndef HPI6205_NO_HSR_POLL
583 /* wait for first interrupt indicating the DSP init is done */
584 time_out = HPI6205_TIMEOUT * 10;
585 temp1 = 0;
586 while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out)
587 temp1 = ioread32(phw->prHSR);
588
589 if (temp1 & C6205_HSR_INTSRC)
590 HPI_DEBUG_LOG(INFO,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300591 "Interrupt confirming DSP code running OK\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200592 else {
593 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300594 "Timed out waiting for interrupt "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200595 "confirming DSP code running\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300596 return HPI6205_ERROR_6205_NO_IRQ;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200597 }
598
599 /* reset the interrupt */
600 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
601#endif
602
603 /* make sure the DSP has started ok */
604 if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
605 HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300606 return HPI6205_ERROR_6205_INIT_FAILED;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200607 }
608 /* Note that *pao, *phw are zeroed after allocation,
609 * so pointers and flags are NULL by default.
610 * Allocate bus mastering control cache buffer and tell the DSP about it
611 */
612 if (interface->control_cache.number_of_controls) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300613 u8 *p_control_cache_virtual;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200614
615 err = hpios_locked_mem_alloc(&phw->h_control_cache,
616 interface->control_cache.size_in_bytes,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300617 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200618 if (!err)
619 err = hpios_locked_mem_get_virt_addr(&phw->
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300620 h_control_cache,
621 (void *)&p_control_cache_virtual);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200622 if (!err) {
623 memset(p_control_cache_virtual, 0,
624 interface->control_cache.size_in_bytes);
625
626 phw->p_cache =
627 hpi_alloc_control_cache(interface->
628 control_cache.number_of_controls,
629 interface->control_cache.size_in_bytes,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200630 p_control_cache_virtual);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200631 if (!phw->p_cache)
632 err = HPI_ERROR_MEMORY_ALLOC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200633 }
634 if (!err) {
635 err = hpios_locked_mem_get_phys_addr(&phw->
636 h_control_cache, &phys_addr);
637 interface->control_cache.physical_address32 =
638 phys_addr;
639 }
640
641 if (!err)
642 pao->has_control_cache = 1;
643 else {
644 if (hpios_locked_mem_valid(&phw->h_control_cache))
645 hpios_locked_mem_free(&phw->h_control_cache);
646 pao->has_control_cache = 0;
647 }
648 }
649 /* allocate bus mastering async buffer and tell the DSP about it */
650 if (interface->async_buffer.b.size) {
651 err = hpios_locked_mem_alloc(&phw->h_async_event_buffer,
652 interface->async_buffer.b.size *
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300653 sizeof(struct hpi_async_event), pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200654 if (!err)
655 err = hpios_locked_mem_get_virt_addr
656 (&phw->h_async_event_buffer, (void *)
657 &phw->p_async_event_buffer);
658 if (!err)
659 memset((void *)phw->p_async_event_buffer, 0,
660 interface->async_buffer.b.size *
661 sizeof(struct hpi_async_event));
662 if (!err) {
663 err = hpios_locked_mem_get_phys_addr
664 (&phw->h_async_event_buffer, &phys_addr);
665 interface->async_buffer.physical_address32 =
666 phys_addr;
667 }
668 if (err) {
669 if (hpios_locked_mem_valid(&phw->
670 h_async_event_buffer)) {
671 hpios_locked_mem_free
672 (&phw->h_async_event_buffer);
673 phw->p_async_event_buffer = NULL;
674 }
675 }
676 }
677 send_dsp_command(phw, H620_HIF_IDLE);
678
679 {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300680 struct hpi_message hm;
681 struct hpi_response hr;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200682 u32 max_streams;
683
684 HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300685 memset(&hm, 0, sizeof(hm));
686 hm.type = HPI_TYPE_MESSAGE;
687 hm.size = sizeof(hm);
688 hm.object = HPI_OBJ_ADAPTER;
689 hm.function = HPI_ADAPTER_GET_INFO;
690 hm.adapter_index = 0;
691 memset(&hr, 0, sizeof(hr));
692 hr.size = sizeof(hr);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200693
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300694 err = message_response_sequence(pao, &hm, &hr);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200695 if (err) {
696 HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
697 err);
698 return err;
699 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300700 if (hr.error)
701 return hr.error;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200702
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300703 pao->adapter_type = hr.u.ax.info.adapter_type;
704 pao->index = hr.u.ax.info.adapter_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200705
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300706 max_streams =
707 hr.u.ax.info.num_outstreams +
708 hr.u.ax.info.num_instreams;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200709
710 hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300711 65536, pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200712
713 HPI_DEBUG_LOG(VERBOSE,
714 "got adapter info type %x index %d serial %d\n",
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300715 hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,
716 hr.u.ax.info.serial_number);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200717 }
718
719 pao->open = 0; /* upon creation the adapter is closed */
720
721 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300722
723 return hpi_add_adapter(pao);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200724}
725
726/** Free memory areas allocated by adapter
727 * this routine is called from SubSysDeleteAdapter,
728 * and SubSysCreateAdapter if duplicate index
729*/
730static void delete_adapter_obj(struct hpi_adapter_obj *pao)
731{
732 struct hpi_hw_obj *phw;
733 int i;
734
735 phw = pao->priv;
736
737 if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) {
738 hpios_locked_mem_free(&phw->h_async_event_buffer);
739 phw->p_async_event_buffer = NULL;
740 }
741
742 if (hpios_locked_mem_valid(&phw->h_control_cache)) {
743 hpios_locked_mem_free(&phw->h_control_cache);
744 hpi_free_control_cache(phw->p_cache);
745 }
746
747 if (hpios_locked_mem_valid(&phw->h_locked_mem)) {
748 hpios_locked_mem_free(&phw->h_locked_mem);
749 phw->p_interface_buffer = NULL;
750 }
751
752 for (i = 0; i < HPI_MAX_STREAMS; i++)
753 if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {
754 hpios_locked_mem_free(&phw->instream_host_buffers[i]);
755 /*?phw->InStreamHostBuffers[i] = NULL; */
756 phw->instream_host_buffer_size[i] = 0;
757 }
758
759 for (i = 0; i < HPI_MAX_STREAMS; i++)
760 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {
761 hpios_locked_mem_free(&phw->outstream_host_buffers
762 [i]);
763 phw->outstream_host_buffer_size[i] = 0;
764 }
765
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300766 hpios_locked_mem_unprepare(pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200767
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200768 kfree(phw);
769}
770
771/*****************************************************************************/
772/* OutStream Host buffer functions */
773
774/** Allocate or attach buffer for busmastering
775*/
776static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
777 struct hpi_message *phm, struct hpi_response *phr)
778{
779 u16 err = 0;
780 u32 command = phm->u.d.u.buffer.command;
781 struct hpi_hw_obj *phw = pao->priv;
782 struct bus_master_interface *interface = phw->p_interface_buffer;
783
784 hpi_init_response(phr, phm->object, phm->function, 0);
785
786 if (command == HPI_BUFFER_CMD_EXTERNAL
787 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
788 /* ALLOC phase, allocate a buffer with power of 2 size,
789 get its bus address for PCI bus mastering
790 */
791 phm->u.d.u.buffer.buffer_size =
792 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
793 /* return old size and allocated size,
794 so caller can detect change */
795 phr->u.d.u.stream_info.data_available =
796 phw->outstream_host_buffer_size[phm->obj_index];
797 phr->u.d.u.stream_info.buffer_size =
798 phm->u.d.u.buffer.buffer_size;
799
800 if (phw->outstream_host_buffer_size[phm->obj_index] ==
801 phm->u.d.u.buffer.buffer_size) {
802 /* Same size, no action required */
803 return;
804 }
805
806 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
807 obj_index]))
808 hpios_locked_mem_free(&phw->outstream_host_buffers
809 [phm->obj_index]);
810
811 err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
812 [phm->obj_index], phm->u.d.u.buffer.buffer_size,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300813 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200814
815 if (err) {
816 phr->error = HPI_ERROR_INVALID_DATASIZE;
817 phw->outstream_host_buffer_size[phm->obj_index] = 0;
818 return;
819 }
820
821 err = hpios_locked_mem_get_phys_addr
822 (&phw->outstream_host_buffers[phm->obj_index],
823 &phm->u.d.u.buffer.pci_address);
824 /* get the phys addr into msg for single call alloc caller
825 * needs to do this for split alloc (or use the same message)
826 * return the phy address for split alloc in the respose too
827 */
828 phr->u.d.u.stream_info.auxiliary_data_available =
829 phm->u.d.u.buffer.pci_address;
830
831 if (err) {
832 hpios_locked_mem_free(&phw->outstream_host_buffers
833 [phm->obj_index]);
834 phw->outstream_host_buffer_size[phm->obj_index] = 0;
835 phr->error = HPI_ERROR_MEMORY_ALLOC;
836 return;
837 }
838 }
839
840 if (command == HPI_BUFFER_CMD_EXTERNAL
841 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
842 /* GRANT phase. Set up the BBM status, tell the DSP about
843 the buffer so it can start using BBM.
844 */
845 struct hpi_hostbuffer_status *status;
846
847 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
848 buffer_size - 1)) {
849 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300850 "Buffer size must be 2^N not %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200851 phm->u.d.u.buffer.buffer_size);
852 phr->error = HPI_ERROR_INVALID_DATASIZE;
853 return;
854 }
855 phw->outstream_host_buffer_size[phm->obj_index] =
856 phm->u.d.u.buffer.buffer_size;
857 status = &interface->outstream_host_buffer_status[phm->
858 obj_index];
859 status->samples_processed = 0;
860 status->stream_state = HPI_STATE_STOPPED;
861 status->dSP_index = 0;
862 status->host_index = status->dSP_index;
863 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
864
865 hw_message(pao, phm, phr);
866
867 if (phr->error
868 && hpios_locked_mem_valid(&phw->
869 outstream_host_buffers[phm->obj_index])) {
870 hpios_locked_mem_free(&phw->outstream_host_buffers
871 [phm->obj_index]);
872 phw->outstream_host_buffer_size[phm->obj_index] = 0;
873 }
874 }
875}
876
877static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
878 struct hpi_message *phm, struct hpi_response *phr)
879{
880 struct hpi_hw_obj *phw = pao->priv;
881 struct bus_master_interface *interface = phw->p_interface_buffer;
882 struct hpi_hostbuffer_status *status;
883 u8 *p_bbm_data;
884
885 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
886 obj_index])) {
887 if (hpios_locked_mem_get_virt_addr(&phw->
888 outstream_host_buffers[phm->obj_index],
889 (void *)&p_bbm_data)) {
890 phr->error = HPI_ERROR_INVALID_OPERATION;
891 return;
892 }
893 status = &interface->outstream_host_buffer_status[phm->
894 obj_index];
895 hpi_init_response(phr, HPI_OBJ_OSTREAM,
896 HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);
897 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
898 phr->u.d.u.hostbuffer_info.p_status = status;
899 } else {
900 hpi_init_response(phr, HPI_OBJ_OSTREAM,
901 HPI_OSTREAM_HOSTBUFFER_GET_INFO,
902 HPI_ERROR_INVALID_OPERATION);
903 }
904}
905
906static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
907 struct hpi_message *phm, struct hpi_response *phr)
908{
909 struct hpi_hw_obj *phw = pao->priv;
910 u32 command = phm->u.d.u.buffer.command;
911
912 if (phw->outstream_host_buffer_size[phm->obj_index]) {
913 if (command == HPI_BUFFER_CMD_EXTERNAL
914 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
915 phw->outstream_host_buffer_size[phm->obj_index] = 0;
916 hw_message(pao, phm, phr);
917 /* Tell adapter to stop using the host buffer. */
918 }
919 if (command == HPI_BUFFER_CMD_EXTERNAL
920 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
921 hpios_locked_mem_free(&phw->outstream_host_buffers
922 [phm->obj_index]);
923 }
924 /* Should HPI_ERROR_INVALID_OPERATION be returned
925 if no host buffer is allocated? */
926 else
927 hpi_init_response(phr, HPI_OBJ_OSTREAM,
928 HPI_OSTREAM_HOSTBUFFER_FREE, 0);
929
930}
931
Eliot Blennerhassett60f1deb2010-08-28 19:52:24 +1200932static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200933{
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200934 return status->size_in_bytes - (status->host_index -
935 status->dSP_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200936}
937
938static void outstream_write(struct hpi_adapter_obj *pao,
939 struct hpi_message *phm, struct hpi_response *phr)
940{
941 struct hpi_hw_obj *phw = pao->priv;
942 struct bus_master_interface *interface = phw->p_interface_buffer;
943 struct hpi_hostbuffer_status *status;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200944 u32 space_available;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200945
946 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
947 /* there is no BBM buffer, write via message */
948 hw_message(pao, phm, phr);
949 return;
950 }
951
952 hpi_init_response(phr, phm->object, phm->function, 0);
953 status = &interface->outstream_host_buffer_status[phm->obj_index];
954
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200955 space_available = outstream_get_space_available(status);
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200956 if (space_available < phm->u.d.u.data.data_size) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200957 phr->error = HPI_ERROR_INVALID_DATASIZE;
958 return;
959 }
960
961 /* HostBuffers is used to indicate host buffer is internally allocated.
962 otherwise, assumed external, data written externally */
963 if (phm->u.d.u.data.pb_data
964 && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
965 obj_index])) {
966 u8 *p_bbm_data;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200967 u32 l_first_write;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200968 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
969
970 if (hpios_locked_mem_get_virt_addr(&phw->
971 outstream_host_buffers[phm->obj_index],
972 (void *)&p_bbm_data)) {
973 phr->error = HPI_ERROR_INVALID_OPERATION;
974 return;
975 }
976
977 /* either all data,
978 or enough to fit from current to end of BBM buffer */
979 l_first_write =
980 min(phm->u.d.u.data.data_size,
981 status->size_in_bytes -
982 (status->host_index & (status->size_in_bytes - 1)));
983
984 memcpy(p_bbm_data +
985 (status->host_index & (status->size_in_bytes - 1)),
986 p_app_data, l_first_write);
987 /* remaining data if any */
988 memcpy(p_bbm_data, p_app_data + l_first_write,
989 phm->u.d.u.data.data_size - l_first_write);
990 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300991
992 /*
993 * This version relies on the DSP code triggering an OStream buffer
994 * update immediately following a SET_FORMAT call. The host has
995 * already written data into the BBM buffer, but the DSP won't know about
996 * it until dwHostIndex is adjusted.
997 */
998 if (phw->flag_outstream_just_reset[phm->obj_index]) {
999 /* Format can only change after reset. Must tell DSP. */
1000 u16 function = phm->function;
1001 phw->flag_outstream_just_reset[phm->obj_index] = 0;
1002 phm->function = HPI_OSTREAM_SET_FORMAT;
1003 hw_message(pao, phm, phr); /* send the format to the DSP */
1004 phm->function = function;
1005 if (phr->error)
1006 return;
1007 }
1008
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001009 status->host_index += phm->u.d.u.data.data_size;
1010}
1011
1012static void outstream_get_info(struct hpi_adapter_obj *pao,
1013 struct hpi_message *phm, struct hpi_response *phr)
1014{
1015 struct hpi_hw_obj *phw = pao->priv;
1016 struct bus_master_interface *interface = phw->p_interface_buffer;
1017 struct hpi_hostbuffer_status *status;
1018
1019 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
1020 hw_message(pao, phm, phr);
1021 return;
1022 }
1023
1024 hpi_init_response(phr, phm->object, phm->function, 0);
1025
1026 status = &interface->outstream_host_buffer_status[phm->obj_index];
1027
1028 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1029 phr->u.d.u.stream_info.samples_transferred =
1030 status->samples_processed;
1031 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1032 phr->u.d.u.stream_info.data_available =
1033 status->size_in_bytes - outstream_get_space_available(status);
1034 phr->u.d.u.stream_info.auxiliary_data_available =
1035 status->auxiliary_data_available;
1036}
1037
1038static void outstream_start(struct hpi_adapter_obj *pao,
1039 struct hpi_message *phm, struct hpi_response *phr)
1040{
1041 hw_message(pao, phm, phr);
1042}
1043
1044static void outstream_reset(struct hpi_adapter_obj *pao,
1045 struct hpi_message *phm, struct hpi_response *phr)
1046{
1047 struct hpi_hw_obj *phw = pao->priv;
1048 phw->flag_outstream_just_reset[phm->obj_index] = 1;
1049 hw_message(pao, phm, phr);
1050}
1051
1052static void outstream_open(struct hpi_adapter_obj *pao,
1053 struct hpi_message *phm, struct hpi_response *phr)
1054{
1055 outstream_reset(pao, phm, phr);
1056}
1057
1058/*****************************************************************************/
1059/* InStream Host buffer functions */
1060
1061static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1062 struct hpi_message *phm, struct hpi_response *phr)
1063{
1064 u16 err = 0;
1065 u32 command = phm->u.d.u.buffer.command;
1066 struct hpi_hw_obj *phw = pao->priv;
1067 struct bus_master_interface *interface = phw->p_interface_buffer;
1068
1069 hpi_init_response(phr, phm->object, phm->function, 0);
1070
1071 if (command == HPI_BUFFER_CMD_EXTERNAL
1072 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
1073
1074 phm->u.d.u.buffer.buffer_size =
1075 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
1076 phr->u.d.u.stream_info.data_available =
1077 phw->instream_host_buffer_size[phm->obj_index];
1078 phr->u.d.u.stream_info.buffer_size =
1079 phm->u.d.u.buffer.buffer_size;
1080
1081 if (phw->instream_host_buffer_size[phm->obj_index] ==
1082 phm->u.d.u.buffer.buffer_size) {
1083 /* Same size, no action required */
1084 return;
1085 }
1086
1087 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1088 obj_index]))
1089 hpios_locked_mem_free(&phw->instream_host_buffers
1090 [phm->obj_index]);
1091
1092 err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
1093 obj_index], phm->u.d.u.buffer.buffer_size,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001094 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001095
1096 if (err) {
1097 phr->error = HPI_ERROR_INVALID_DATASIZE;
1098 phw->instream_host_buffer_size[phm->obj_index] = 0;
1099 return;
1100 }
1101
1102 err = hpios_locked_mem_get_phys_addr
1103 (&phw->instream_host_buffers[phm->obj_index],
1104 &phm->u.d.u.buffer.pci_address);
1105 /* get the phys addr into msg for single call alloc. Caller
1106 needs to do this for split alloc so return the phy address */
1107 phr->u.d.u.stream_info.auxiliary_data_available =
1108 phm->u.d.u.buffer.pci_address;
1109 if (err) {
1110 hpios_locked_mem_free(&phw->instream_host_buffers
1111 [phm->obj_index]);
1112 phw->instream_host_buffer_size[phm->obj_index] = 0;
1113 phr->error = HPI_ERROR_MEMORY_ALLOC;
1114 return;
1115 }
1116 }
1117
1118 if (command == HPI_BUFFER_CMD_EXTERNAL
1119 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
1120 struct hpi_hostbuffer_status *status;
1121
1122 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
1123 buffer_size - 1)) {
1124 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001125 "Buffer size must be 2^N not %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001126 phm->u.d.u.buffer.buffer_size);
1127 phr->error = HPI_ERROR_INVALID_DATASIZE;
1128 return;
1129 }
1130
1131 phw->instream_host_buffer_size[phm->obj_index] =
1132 phm->u.d.u.buffer.buffer_size;
1133 status = &interface->instream_host_buffer_status[phm->
1134 obj_index];
1135 status->samples_processed = 0;
1136 status->stream_state = HPI_STATE_STOPPED;
1137 status->dSP_index = 0;
1138 status->host_index = status->dSP_index;
1139 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
1140
1141 hw_message(pao, phm, phr);
1142 if (phr->error
1143 && hpios_locked_mem_valid(&phw->
1144 instream_host_buffers[phm->obj_index])) {
1145 hpios_locked_mem_free(&phw->instream_host_buffers
1146 [phm->obj_index]);
1147 phw->instream_host_buffer_size[phm->obj_index] = 0;
1148 }
1149 }
1150}
1151
1152static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1153 struct hpi_message *phm, struct hpi_response *phr)
1154{
1155 struct hpi_hw_obj *phw = pao->priv;
1156 struct bus_master_interface *interface = phw->p_interface_buffer;
1157 struct hpi_hostbuffer_status *status;
1158 u8 *p_bbm_data;
1159
1160 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1161 obj_index])) {
1162 if (hpios_locked_mem_get_virt_addr(&phw->
1163 instream_host_buffers[phm->obj_index],
1164 (void *)&p_bbm_data)) {
1165 phr->error = HPI_ERROR_INVALID_OPERATION;
1166 return;
1167 }
1168 status = &interface->instream_host_buffer_status[phm->
1169 obj_index];
1170 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1171 HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);
1172 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
1173 phr->u.d.u.hostbuffer_info.p_status = status;
1174 } else {
1175 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1176 HPI_ISTREAM_HOSTBUFFER_GET_INFO,
1177 HPI_ERROR_INVALID_OPERATION);
1178 }
1179}
1180
1181static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
1182 struct hpi_message *phm, struct hpi_response *phr)
1183{
1184 struct hpi_hw_obj *phw = pao->priv;
1185 u32 command = phm->u.d.u.buffer.command;
1186
1187 if (phw->instream_host_buffer_size[phm->obj_index]) {
1188 if (command == HPI_BUFFER_CMD_EXTERNAL
1189 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
1190 phw->instream_host_buffer_size[phm->obj_index] = 0;
1191 hw_message(pao, phm, phr);
1192 }
1193
1194 if (command == HPI_BUFFER_CMD_EXTERNAL
1195 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
1196 hpios_locked_mem_free(&phw->instream_host_buffers
1197 [phm->obj_index]);
1198
1199 } else {
1200 /* Should HPI_ERROR_INVALID_OPERATION be returned
1201 if no host buffer is allocated? */
1202 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1203 HPI_ISTREAM_HOSTBUFFER_FREE, 0);
1204
1205 }
1206
1207}
1208
1209static void instream_start(struct hpi_adapter_obj *pao,
1210 struct hpi_message *phm, struct hpi_response *phr)
1211{
1212 hw_message(pao, phm, phr);
1213}
1214
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001215static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001216{
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001217 return status->dSP_index - status->host_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001218}
1219
1220static void instream_read(struct hpi_adapter_obj *pao,
1221 struct hpi_message *phm, struct hpi_response *phr)
1222{
1223 struct hpi_hw_obj *phw = pao->priv;
1224 struct bus_master_interface *interface = phw->p_interface_buffer;
1225 struct hpi_hostbuffer_status *status;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001226 u32 data_available;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001227 u8 *p_bbm_data;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001228 u32 l_first_read;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001229 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1230
1231 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1232 hw_message(pao, phm, phr);
1233 return;
1234 }
1235 hpi_init_response(phr, phm->object, phm->function, 0);
1236
1237 status = &interface->instream_host_buffer_status[phm->obj_index];
1238 data_available = instream_get_bytes_available(status);
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001239 if (data_available < phm->u.d.u.data.data_size) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001240 phr->error = HPI_ERROR_INVALID_DATASIZE;
1241 return;
1242 }
1243
1244 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1245 obj_index])) {
1246 if (hpios_locked_mem_get_virt_addr(&phw->
1247 instream_host_buffers[phm->obj_index],
1248 (void *)&p_bbm_data)) {
1249 phr->error = HPI_ERROR_INVALID_OPERATION;
1250 return;
1251 }
1252
1253 /* either all data,
1254 or enough to fit from current to end of BBM buffer */
1255 l_first_read =
1256 min(phm->u.d.u.data.data_size,
1257 status->size_in_bytes -
1258 (status->host_index & (status->size_in_bytes - 1)));
1259
1260 memcpy(p_app_data,
1261 p_bbm_data +
1262 (status->host_index & (status->size_in_bytes - 1)),
1263 l_first_read);
1264 /* remaining data if any */
1265 memcpy(p_app_data + l_first_read, p_bbm_data,
1266 phm->u.d.u.data.data_size - l_first_read);
1267 }
1268 status->host_index += phm->u.d.u.data.data_size;
1269}
1270
1271static void instream_get_info(struct hpi_adapter_obj *pao,
1272 struct hpi_message *phm, struct hpi_response *phr)
1273{
1274 struct hpi_hw_obj *phw = pao->priv;
1275 struct bus_master_interface *interface = phw->p_interface_buffer;
1276 struct hpi_hostbuffer_status *status;
1277 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1278 hw_message(pao, phm, phr);
1279 return;
1280 }
1281
1282 status = &interface->instream_host_buffer_status[phm->obj_index];
1283
1284 hpi_init_response(phr, phm->object, phm->function, 0);
1285
1286 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1287 phr->u.d.u.stream_info.samples_transferred =
1288 status->samples_processed;
1289 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1290 phr->u.d.u.stream_info.data_available =
1291 instream_get_bytes_available(status);
1292 phr->u.d.u.stream_info.auxiliary_data_available =
1293 status->auxiliary_data_available;
1294}
1295
1296/*****************************************************************************/
1297/* LOW-LEVEL */
1298#define HPI6205_MAX_FILES_TO_LOAD 2
1299
1300static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1301 u32 *pos_error_code)
1302{
1303 struct hpi_hw_obj *phw = pao->priv;
1304 struct dsp_code dsp_code;
1305 u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001306 u16 firmware_id = pao->pci.pci_dev->subsystem_device;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001307 u32 temp;
1308 int dsp = 0, i = 0;
1309 u16 err = 0;
1310
1311 boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
1312
1313 /* special cases where firmware_id != subsys ID */
1314 switch (firmware_id) {
1315 case HPI_ADAPTER_FAMILY_ASI(0x5000):
1316 boot_code_id[0] = firmware_id;
1317 firmware_id = 0;
1318 break;
1319 case HPI_ADAPTER_FAMILY_ASI(0x5300):
1320 case HPI_ADAPTER_FAMILY_ASI(0x5400):
1321 case HPI_ADAPTER_FAMILY_ASI(0x6300):
1322 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400);
1323 break;
1324 case HPI_ADAPTER_FAMILY_ASI(0x5600):
1325 case HPI_ADAPTER_FAMILY_ASI(0x6500):
1326 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
1327 break;
Eliot Blennerhassettcadae422010-05-27 17:53:54 +12001328 case HPI_ADAPTER_FAMILY_ASI(0x8800):
1329 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900);
1330 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001331 }
1332 boot_code_id[1] = firmware_id;
1333
1334 /* reset DSP by writing a 1 to the WARMRESET bit */
1335 temp = C6205_HDCR_WARMRESET;
1336 iowrite32(temp, phw->prHDCR);
1337 hpios_delay_micro_seconds(1000);
1338
1339 /* check that PCI i/f was configured by EEPROM */
1340 temp = ioread32(phw->prHSR);
1341 if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
1342 C6205_HSR_EEREAD)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001343 return HPI6205_ERROR_6205_EEPROM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001344 temp |= 0x04;
1345 /* disable PINTA interrupt */
1346 iowrite32(temp, phw->prHSR);
1347
1348 /* check control register reports PCI boot mode */
1349 temp = ioread32(phw->prHDCR);
1350 if (!(temp & C6205_HDCR_PCIBOOT))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001351 return HPI6205_ERROR_6205_REG;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001352
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001353 /* try writing a few numbers to the DSP page register */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001354 /* and reading them back. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001355 temp = 3;
1356 iowrite32(temp, phw->prDSPP);
1357 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001358 return HPI6205_ERROR_6205_DSPPAGE;
1359 temp = 2;
1360 iowrite32(temp, phw->prDSPP);
1361 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1362 return HPI6205_ERROR_6205_DSPPAGE;
1363 temp = 1;
1364 iowrite32(temp, phw->prDSPP);
1365 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1366 return HPI6205_ERROR_6205_DSPPAGE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001367 /* reset DSP page to the correct number */
1368 temp = 0;
1369 iowrite32(temp, phw->prDSPP);
1370 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001371 return HPI6205_ERROR_6205_DSPPAGE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001372 phw->dsp_page = 0;
1373
1374 /* release 6713 from reset before 6205 is bootloaded.
1375 This ensures that the EMIF is inactive,
1376 and the 6713 HPI gets the correct bootmode etc
1377 */
1378 if (boot_code_id[1] != 0) {
1379 /* DSP 1 is a C6713 */
1380 /* CLKX0 <- '1' release the C6205 bootmode pulldowns */
1381 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002202);
1382 hpios_delay_micro_seconds(100);
1383 /* Reset the 6713 #1 - revB */
1384 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
1385
1386 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1387 boot_loader_read_mem32(pao, 0, 0);
1388
1389 hpios_delay_micro_seconds(100);
1390 /* Release C6713 from reset - revB */
1391 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);
1392 hpios_delay_micro_seconds(100);
1393 }
1394
1395 for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {
1396 /* is there a DSP to load? */
1397 if (boot_code_id[dsp] == 0)
1398 continue;
1399
1400 err = boot_loader_config_emif(pao, dsp);
1401 if (err)
1402 return err;
1403
1404 err = boot_loader_test_internal_memory(pao, dsp);
1405 if (err)
1406 return err;
1407
1408 err = boot_loader_test_external_memory(pao, dsp);
1409 if (err)
1410 return err;
1411
1412 err = boot_loader_test_pld(pao, dsp);
1413 if (err)
1414 return err;
1415
1416 /* write the DSP code down into the DSPs memory */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001417 dsp_code.ps_dev = pao->pci.pci_dev;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001418 err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
1419 pos_error_code);
1420 if (err)
1421 return err;
1422
1423 while (1) {
1424 u32 length;
1425 u32 address;
1426 u32 type;
1427 u32 *pcode;
1428
1429 err = hpi_dsp_code_read_word(&dsp_code, &length);
1430 if (err)
1431 break;
1432 if (length == 0xFFFFFFFF)
1433 break; /* end of code */
1434
1435 err = hpi_dsp_code_read_word(&dsp_code, &address);
1436 if (err)
1437 break;
1438 err = hpi_dsp_code_read_word(&dsp_code, &type);
1439 if (err)
1440 break;
1441 err = hpi_dsp_code_read_block(length, &dsp_code,
1442 &pcode);
1443 if (err)
1444 break;
1445 for (i = 0; i < (int)length; i++) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001446 boot_loader_write_mem32(pao, dsp, address,
1447 *pcode);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001448 /* dummy read every 4 words */
1449 /* for 6205 advisory 1.4.4 */
1450 if (i % 4 == 0)
1451 boot_loader_read_mem32(pao, dsp,
1452 address);
1453 pcode++;
1454 address += 4;
1455 }
1456
1457 }
1458 if (err) {
1459 hpi_dsp_code_close(&dsp_code);
1460 return err;
1461 }
1462
1463 /* verify code */
1464 hpi_dsp_code_rewind(&dsp_code);
1465 while (1) {
1466 u32 length = 0;
1467 u32 address = 0;
1468 u32 type = 0;
1469 u32 *pcode = NULL;
1470 u32 data = 0;
1471
1472 hpi_dsp_code_read_word(&dsp_code, &length);
1473 if (length == 0xFFFFFFFF)
1474 break; /* end of code */
1475
1476 hpi_dsp_code_read_word(&dsp_code, &address);
1477 hpi_dsp_code_read_word(&dsp_code, &type);
1478 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1479
1480 for (i = 0; i < (int)length; i++) {
1481 data = boot_loader_read_mem32(pao, dsp,
1482 address);
1483 if (data != *pcode) {
1484 err = 0;
1485 break;
1486 }
1487 pcode++;
1488 address += 4;
1489 }
1490 if (err)
1491 break;
1492 }
1493 hpi_dsp_code_close(&dsp_code);
1494 if (err)
1495 return err;
1496 }
1497
1498 /* After bootloading all DSPs, start DSP0 running
1499 * The DSP0 code will handle starting and synchronizing with its slaves
1500 */
1501 if (phw->p_interface_buffer) {
1502 /* we need to tell the card the physical PCI address */
1503 u32 physicalPC_iaddress;
1504 struct bus_master_interface *interface =
1505 phw->p_interface_buffer;
1506 u32 host_mailbox_address_on_dsp;
1507 u32 physicalPC_iaddress_verify = 0;
1508 int time_out = 10;
1509 /* set ack so we know when DSP is ready to go */
1510 /* (dwDspAck will be changed to HIF_RESET) */
1511 interface->dsp_ack = H620_HIF_UNKNOWN;
1512 wmb(); /* ensure ack is written before dsp writes back */
1513
1514 err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,
1515 &physicalPC_iaddress);
1516
1517 /* locate the host mailbox on the DSP. */
1518 host_mailbox_address_on_dsp = 0x80000000;
1519 while ((physicalPC_iaddress != physicalPC_iaddress_verify)
1520 && time_out--) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001521 boot_loader_write_mem32(pao, 0,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001522 host_mailbox_address_on_dsp,
1523 physicalPC_iaddress);
1524 physicalPC_iaddress_verify =
1525 boot_loader_read_mem32(pao, 0,
1526 host_mailbox_address_on_dsp);
1527 }
1528 }
1529 HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");
1530 /* enable interrupts */
1531 temp = ioread32(phw->prHSR);
1532 temp &= ~(u32)C6205_HSR_INTAM;
1533 iowrite32(temp, phw->prHSR);
1534
1535 /* start code running... */
1536 temp = ioread32(phw->prHDCR);
1537 temp |= (u32)C6205_HDCR_DSPINT;
1538 iowrite32(temp, phw->prHDCR);
1539
1540 /* give the DSP 10ms to start up */
1541 hpios_delay_micro_seconds(10000);
1542 return err;
1543
1544}
1545
1546/*****************************************************************************/
1547/* Bootloader utility functions */
1548
1549static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1550 u32 address)
1551{
1552 struct hpi_hw_obj *phw = pao->priv;
1553 u32 data = 0;
1554 __iomem u32 *p_data;
1555
1556 if (dsp_index == 0) {
1557 /* DSP 0 is always C6205 */
1558 if ((address >= 0x01800000) & (address < 0x02000000)) {
1559 /* BAR1 register access */
1560 p_data = pao->pci.ap_mem_base[1] +
1561 (address & 0x007fffff) /
1562 sizeof(*pao->pci.ap_mem_base[1]);
1563 /* HPI_DEBUG_LOG(WARNING,
1564 "BAR1 access %08x\n", dwAddress); */
1565 } else {
1566 u32 dw4M_page = address >> 22L;
1567 if (dw4M_page != phw->dsp_page) {
1568 phw->dsp_page = dw4M_page;
1569 /* *INDENT OFF* */
1570 iowrite32(phw->dsp_page, phw->prDSPP);
1571 /* *INDENT-ON* */
1572 }
1573 address &= 0x3fffff; /* address within 4M page */
1574 /* BAR0 memory access */
1575 p_data = pao->pci.ap_mem_base[0] +
1576 address / sizeof(u32);
1577 }
1578 data = ioread32(p_data);
1579 } else if (dsp_index == 1) {
1580 /* DSP 1 is a C6713 */
1581 u32 lsb;
1582 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1583 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1584 lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);
1585 data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);
1586 data = (data << 16) | (lsb & 0xFFFF);
1587 }
1588 return data;
1589}
1590
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001591static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
1592 int dsp_index, u32 address, u32 data)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001593{
1594 struct hpi_hw_obj *phw = pao->priv;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001595 __iomem u32 *p_data;
1596 /* u32 dwVerifyData=0; */
1597
1598 if (dsp_index == 0) {
1599 /* DSP 0 is always C6205 */
1600 if ((address >= 0x01800000) & (address < 0x02000000)) {
1601 /* BAR1 - DSP register access using */
1602 /* Non-prefetchable PCI access */
1603 p_data = pao->pci.ap_mem_base[1] +
1604 (address & 0x007fffff) /
1605 sizeof(*pao->pci.ap_mem_base[1]);
1606 } else {
1607 /* BAR0 access - all of DSP memory using */
1608 /* pre-fetchable PCI access */
1609 u32 dw4M_page = address >> 22L;
1610 if (dw4M_page != phw->dsp_page) {
1611 phw->dsp_page = dw4M_page;
1612 /* *INDENT-OFF* */
1613 iowrite32(phw->dsp_page, phw->prDSPP);
1614 /* *INDENT-ON* */
1615 }
1616 address &= 0x3fffff; /* address within 4M page */
1617 p_data = pao->pci.ap_mem_base[0] +
1618 address / sizeof(u32);
1619 }
1620 iowrite32(data, p_data);
1621 } else if (dsp_index == 1) {
1622 /* DSP 1 is a C6713 */
1623 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1624 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1625
1626 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1627 boot_loader_read_mem32(pao, 0, 0);
1628
1629 boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);
1630 boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);
1631
1632 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1633 boot_loader_read_mem32(pao, 0, 0);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001634 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001635}
1636
1637static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
1638{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001639 if (dsp_index == 0) {
1640 u32 setting;
1641
1642 /* DSP 0 is always C6205 */
1643
1644 /* Set the EMIF */
1645 /* memory map of C6205 */
1646 /* 00000000-0000FFFF 16Kx32 internal program */
1647 /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */
1648
1649 /* EMIF config */
1650 /*------------ */
1651 /* Global EMIF control */
1652 boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);
1653#define WS_OFS 28
1654#define WST_OFS 22
1655#define WH_OFS 20
1656#define RS_OFS 16
1657#define RST_OFS 8
1658#define MTYPE_OFS 4
1659#define RH_OFS 0
1660
1661 /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */
1662 setting = 0x00000030;
1663 boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
1664 if (setting != boot_loader_read_mem32(pao, dsp_index,
1665 0x01800008))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001666 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001667
1668 /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
1669 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1670 /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */
1671 /* WST should be 71, but 63 is max possible */
1672 setting =
1673 (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |
1674 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1675 (2L << MTYPE_OFS);
1676 boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
1677 if (setting != boot_loader_read_mem32(pao, dsp_index,
1678 0x01800004))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001679 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001680
1681 /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
1682 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1683 /* plenty of wait states */
1684 setting =
1685 (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |
1686 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1687 (2L << MTYPE_OFS);
1688 boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
1689 if (setting != boot_loader_read_mem32(pao, dsp_index,
1690 0x01800010))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001691 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001692
1693 /* EMIF CE3 setup - 32 bit async. */
1694 /* This is the PLD on the ASI5000 cards only */
1695 setting =
1696 (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |
1697 (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |
1698 (2L << MTYPE_OFS);
1699 boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
1700 if (setting != boot_loader_read_mem32(pao, dsp_index,
1701 0x01800014))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001702 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001703
1704 /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
1705 /* need to use this else DSP code crashes? */
1706 boot_loader_write_mem32(pao, dsp_index, 0x01800018,
1707 0x07117000);
1708
1709 /* EMIF SDRAM Refresh Timing */
1710 /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */
1711 boot_loader_write_mem32(pao, dsp_index, 0x0180001C,
1712 0x00000410);
1713
1714 } else if (dsp_index == 1) {
1715 /* test access to the C6713s HPI registers */
1716 u32 write_data = 0, read_data = 0, i = 0;
1717
1718 /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */
1719 write_data = 1;
1720 boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);
1721 boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);
1722 /* C67 HPI is on lower 16bits of 32bit EMIF */
1723 read_data =
1724 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
1725 if (write_data != read_data) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001726 HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
1727 read_data);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001728 return HPI6205_ERROR_C6713_HPIC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001729 }
1730 /* HPIA - walking ones test */
1731 write_data = 1;
1732 for (i = 0; i < 32; i++) {
1733 boot_loader_write_mem32(pao, 0, HPIAL_ADDR,
1734 write_data);
1735 boot_loader_write_mem32(pao, 0, HPIAH_ADDR,
1736 (write_data >> 16));
1737 read_data =
1738 0xFFFF & boot_loader_read_mem32(pao, 0,
1739 HPIAL_ADDR);
1740 read_data =
1741 read_data | ((0xFFFF &
1742 boot_loader_read_mem32(pao, 0,
1743 HPIAH_ADDR))
1744 << 16);
1745 if (read_data != write_data) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001746 HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
1747 write_data, read_data);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001748 return HPI6205_ERROR_C6713_HPIA;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001749 }
1750 write_data = write_data << 1;
1751 }
1752
1753 /* setup C67x PLL
1754 * ** C6713 datasheet says we cannot program PLL from HPI,
1755 * and indeed if we try to set the PLL multiply from the HPI,
1756 * the PLL does not seem to lock, so we enable the PLL and
1757 * use the default multiply of x 7, which for a 27MHz clock
1758 * gives a DSP speed of 189MHz
1759 */
1760 /* bypass PLL */
1761 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);
1762 hpios_delay_micro_seconds(1000);
1763 /* EMIF = 189/3=63MHz */
1764 boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);
1765 /* peri = 189/2 */
1766 boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);
1767 /* cpu = 189/1 */
1768 boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);
1769 hpios_delay_micro_seconds(1000);
1770 /* ** SGT test to take GPO3 high when we start the PLL */
1771 /* and low when the delay is completed */
1772 /* FSX0 <- '1' (GPO3) */
1773 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);
1774 /* PLL not bypassed */
1775 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);
1776 hpios_delay_micro_seconds(1000);
1777 /* FSX0 <- '0' (GPO3) */
1778 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);
1779
1780 /* 6205 EMIF CE1 resetup - 32 bit async. */
1781 /* Now 6713 #1 is running at 189MHz can reduce waitstates */
1782 boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */
1783 (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |
1784 (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |
1785 (2L << MTYPE_OFS));
1786
1787 hpios_delay_micro_seconds(1000);
1788
1789 /* check that we can read one of the PLL registers */
1790 /* PLL should not be bypassed! */
1791 if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
1792 != 0x0001) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001793 return HPI6205_ERROR_C6713_PLL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001794 }
1795 /* setup C67x EMIF (note this is the only use of
1796 BAR1 via BootLoader_WriteMem32) */
1797 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
1798 0x000034A8);
1799 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
1800 0x00000030);
1801 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
1802 0x001BDF29);
1803 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
1804 0x47117000);
1805 boot_loader_write_mem32(pao, dsp_index,
1806 C6713_EMIF_SDRAMTIMING, 0x00000410);
1807
1808 hpios_delay_micro_seconds(1000);
1809 } else if (dsp_index == 2) {
1810 /* DSP 2 is a C6713 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001811 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001812
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001813 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001814}
1815
1816static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
1817 u32 start_address, u32 length)
1818{
1819 u32 i = 0, j = 0;
1820 u32 test_addr = 0;
1821 u32 test_data = 0, data = 0;
1822
1823 length = 1000;
1824
1825 /* for 1st word, test each bit in the 32bit word, */
1826 /* dwLength specifies number of 32bit words to test */
1827 /*for(i=0; i<dwLength; i++) */
1828 i = 0;
1829 {
1830 test_addr = start_address + i * 4;
1831 test_data = 0x00000001;
1832 for (j = 0; j < 32; j++) {
1833 boot_loader_write_mem32(pao, dsp_index, test_addr,
1834 test_data);
1835 data = boot_loader_read_mem32(pao, dsp_index,
1836 test_addr);
1837 if (data != test_data) {
1838 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001839 "Memtest error details "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001840 "%08x %08x %08x %i\n", test_addr,
1841 test_data, data, dsp_index);
1842 return 1; /* error */
1843 }
1844 test_data = test_data << 1;
1845 } /* for(j) */
1846 } /* for(i) */
1847
1848 /* for the next 100 locations test each location, leaving it as zero */
1849 /* write a zero to the next word in memory before we read */
1850 /* the previous write to make sure every memory location is unique */
1851 for (i = 0; i < 100; i++) {
1852 test_addr = start_address + i * 4;
1853 test_data = 0xA5A55A5A;
1854 boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);
1855 boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);
1856 data = boot_loader_read_mem32(pao, dsp_index, test_addr);
1857 if (data != test_data) {
1858 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001859 "Memtest error details "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001860 "%08x %08x %08x %i\n", test_addr, test_data,
1861 data, dsp_index);
1862 return 1; /* error */
1863 }
1864 /* leave location as zero */
1865 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1866 }
1867
1868 /* zero out entire memory block */
1869 for (i = 0; i < length; i++) {
1870 test_addr = start_address + i * 4;
1871 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1872 }
1873 return 0;
1874}
1875
1876static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
1877 int dsp_index)
1878{
1879 int err = 0;
1880 if (dsp_index == 0) {
1881 /* DSP 0 is a C6205 */
1882 /* 64K prog mem */
1883 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1884 0x10000);
1885 if (!err)
1886 /* 64K data mem */
1887 err = boot_loader_test_memory(pao, dsp_index,
1888 0x80000000, 0x10000);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001889 } else if (dsp_index == 1) {
1890 /* DSP 1 is a C6713 */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001891 /* 192K internal mem */
1892 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1893 0x30000);
1894 if (!err)
1895 /* 64K internal mem / L2 cache */
1896 err = boot_loader_test_memory(pao, dsp_index,
1897 0x00030000, 0x10000);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001898 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001899
1900 if (err)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001901 return HPI6205_ERROR_DSP_INTMEM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001902 else
1903 return 0;
1904}
1905
1906static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
1907 int dsp_index)
1908{
1909 u32 dRAM_start_address = 0;
1910 u32 dRAM_size = 0;
1911
1912 if (dsp_index == 0) {
1913 /* only test for SDRAM if an ASI5000 card */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001914 if (pao->pci.pci_dev->subsystem_device == 0x5000) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001915 /* DSP 0 is always C6205 */
1916 dRAM_start_address = 0x00400000;
1917 dRAM_size = 0x200000;
1918 /*dwDRAMinc=1024; */
1919 } else
1920 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001921 } else if (dsp_index == 1) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001922 /* DSP 1 is a C6713 */
1923 dRAM_start_address = 0x80000000;
1924 dRAM_size = 0x200000;
1925 /*dwDRAMinc=1024; */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001926 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001927
1928 if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
1929 dRAM_size))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001930 return HPI6205_ERROR_DSP_EXTMEM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001931 return 0;
1932}
1933
1934static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
1935{
1936 u32 data = 0;
1937 if (dsp_index == 0) {
1938 /* only test for DSP0 PLD on ASI5000 card */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001939 if (pao->pci.pci_dev->subsystem_device == 0x5000) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001940 /* PLD is located at CE3=0x03000000 */
1941 data = boot_loader_read_mem32(pao, dsp_index,
1942 0x03000008);
1943 if ((data & 0xF) != 0x5)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001944 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001945 data = boot_loader_read_mem32(pao, dsp_index,
1946 0x0300000C);
1947 if ((data & 0xF) != 0xA)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001948 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001949 }
1950 } else if (dsp_index == 1) {
1951 /* DSP 1 is a C6713 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001952 if (pao->pci.pci_dev->subsystem_device == 0x8700) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001953 /* PLD is located at CE1=0x90000000 */
1954 data = boot_loader_read_mem32(pao, dsp_index,
1955 0x90000010);
1956 if ((data & 0xFF) != 0xAA)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001957 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001958 /* 8713 - LED on */
1959 boot_loader_write_mem32(pao, dsp_index, 0x90000000,
1960 0x02);
1961 }
1962 }
1963 return 0;
1964}
1965
1966/** Transfer data to or from DSP
1967 nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA
1968*/
1969static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
1970 u32 data_size, int operation)
1971{
1972 struct hpi_hw_obj *phw = pao->priv;
1973 u32 data_transferred = 0;
1974 u16 err = 0;
1975#ifndef HPI6205_NO_HSR_POLL
1976 u32 time_out;
1977#endif
1978 u32 temp2;
1979 struct bus_master_interface *interface = phw->p_interface_buffer;
1980
1981 if (!p_data)
1982 return HPI_ERROR_INVALID_DATA_TRANSFER;
1983
1984 data_size &= ~3L; /* round data_size down to nearest 4 bytes */
1985
1986 /* make sure state is IDLE */
1987 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))
1988 return HPI_ERROR_DSP_HARDWARE;
1989
1990 while (data_transferred < data_size) {
1991 u32 this_copy = data_size - data_transferred;
1992
1993 if (this_copy > HPI6205_SIZEOF_DATA)
1994 this_copy = HPI6205_SIZEOF_DATA;
1995
1996 if (operation == H620_HIF_SEND_DATA)
1997 memcpy((void *)&interface->u.b_data[0],
1998 &p_data[data_transferred], this_copy);
1999
2000 interface->transfer_size_in_bytes = this_copy;
2001
2002#ifdef HPI6205_NO_HSR_POLL
2003 /* DSP must change this back to nOperation */
2004 interface->dsp_ack = H620_HIF_IDLE;
2005#endif
2006
2007 send_dsp_command(phw, operation);
2008
2009#ifdef HPI6205_NO_HSR_POLL
2010 temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
2011 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2012 HPI6205_TIMEOUT - temp2, this_copy);
2013
2014 if (!temp2) {
2015 /* timed out */
2016 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002017 "Timed out waiting for " "state %d got %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002018 operation, interface->dsp_ack);
2019
2020 break;
2021 }
2022#else
2023 /* spin waiting on the result */
2024 time_out = HPI6205_TIMEOUT;
2025 temp2 = 0;
2026 while ((temp2 == 0) && time_out--) {
2027 /* give 16k bus mastering transfer time to happen */
2028 /*(16k / 132Mbytes/s = 122usec) */
2029 hpios_delay_micro_seconds(20);
2030 temp2 = ioread32(phw->prHSR);
2031 temp2 &= C6205_HSR_INTSRC;
2032 }
2033 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2034 HPI6205_TIMEOUT - time_out, this_copy);
2035 if (temp2 == C6205_HSR_INTSRC) {
2036 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002037 "Interrupt from HIF <data> OK\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002038 /*
2039 if(interface->dwDspAck != nOperation) {
2040 HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d,
2041 expected %d \n",
2042 interface->dwDspAck,nOperation);
2043 }
2044 */
2045 }
2046/* need to handle this differently... */
2047 else {
2048 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002049 "Interrupt from HIF <data> BAD\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002050 err = HPI_ERROR_DSP_HARDWARE;
2051 }
2052
2053 /* reset the interrupt from the DSP */
2054 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2055#endif
2056 if (operation == H620_HIF_GET_DATA)
2057 memcpy(&p_data[data_transferred],
2058 (void *)&interface->u.b_data[0], this_copy);
2059
2060 data_transferred += this_copy;
2061 }
2062 if (interface->dsp_ack != operation)
2063 HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",
2064 interface->dsp_ack, operation);
2065 /* err=HPI_ERROR_DSP_HARDWARE; */
2066
2067 send_dsp_command(phw, H620_HIF_IDLE);
2068
2069 return err;
2070}
2071
2072/* wait for up to timeout_us microseconds for the DSP
2073 to signal state by DMA into dwDspAck
2074*/
2075static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
2076{
2077 struct bus_master_interface *interface = phw->p_interface_buffer;
2078 int t = timeout_us / 4;
2079
2080 rmb(); /* ensure interface->dsp_ack is up to date */
2081 while ((interface->dsp_ack != state) && --t) {
2082 hpios_delay_micro_seconds(4);
2083 rmb(); /* DSP changes dsp_ack by DMA */
2084 }
2085
2086 /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */
2087 return t * 4;
2088}
2089
2090/* set the busmaster interface to cmd, then interrupt the DSP */
2091static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
2092{
2093 struct bus_master_interface *interface = phw->p_interface_buffer;
2094
2095 u32 r;
2096
2097 interface->host_cmd = cmd;
2098 wmb(); /* DSP gets state by DMA, make sure it is written to memory */
2099 /* before we interrupt the DSP */
2100 r = ioread32(phw->prHDCR);
2101 r |= (u32)C6205_HDCR_DSPINT;
2102 iowrite32(r, phw->prHDCR);
2103 r &= ~(u32)C6205_HDCR_DSPINT;
2104 iowrite32(r, phw->prHDCR);
2105}
2106
2107static unsigned int message_count;
2108
2109static u16 message_response_sequence(struct hpi_adapter_obj *pao,
2110 struct hpi_message *phm, struct hpi_response *phr)
2111{
2112#ifndef HPI6205_NO_HSR_POLL
2113 u32 temp2;
2114#endif
2115 u32 time_out, time_out2;
2116 struct hpi_hw_obj *phw = pao->priv;
2117 struct bus_master_interface *interface = phw->p_interface_buffer;
2118 u16 err = 0;
2119
2120 message_count++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002121 if (phm->size > sizeof(interface->u)) {
2122 /* really MESSAGE buffer too small */
2123 phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
2124 phr->specific_error = sizeof(interface->u);
2125 phr->size = sizeof(struct hpi_response_header);
2126 HPI_DEBUG_LOG(ERROR,
2127 "message len %d too big for buffer %ld \n", phm->size,
2128 sizeof(interface->u));
2129 return 0;
2130 }
2131
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002132 /* Assume buffer of type struct bus_master_interface
2133 is allocated "noncacheable" */
2134
2135 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2136 HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002137 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002138 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002139
2140 memcpy(&interface->u.message_buffer, phm, phm->size);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002141 /* signal we want a response */
2142 send_dsp_command(phw, H620_HIF_GET_RESP);
2143
2144 time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
2145
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002146 if (!time_out2) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002147 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002148 "(%u) Timed out waiting for " "GET_RESP state [%x]\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002149 message_count, interface->dsp_ack);
2150 } else {
2151 HPI_DEBUG_LOG(VERBOSE,
2152 "(%u) transition to GET_RESP after %u\n",
2153 message_count, HPI6205_TIMEOUT - time_out2);
2154 }
2155 /* spin waiting on HIF interrupt flag (end of msg process) */
2156 time_out = HPI6205_TIMEOUT;
2157
2158#ifndef HPI6205_NO_HSR_POLL
2159 temp2 = 0;
2160 while ((temp2 == 0) && --time_out) {
2161 temp2 = ioread32(phw->prHSR);
2162 temp2 &= C6205_HSR_INTSRC;
2163 hpios_delay_micro_seconds(1);
2164 }
2165 if (temp2 == C6205_HSR_INTSRC) {
2166 rmb(); /* ensure we see latest value for dsp_ack */
2167 if ((interface->dsp_ack != H620_HIF_GET_RESP)) {
2168 HPI_DEBUG_LOG(DEBUG,
2169 "(%u)interface->dsp_ack(0x%x) != "
2170 "H620_HIF_GET_RESP, t=%u\n", message_count,
2171 interface->dsp_ack,
2172 HPI6205_TIMEOUT - time_out);
2173 } else {
2174 HPI_DEBUG_LOG(VERBOSE,
2175 "(%u)int with GET_RESP after %u\n",
2176 message_count, HPI6205_TIMEOUT - time_out);
2177 }
2178
2179 } else {
2180 /* can we do anything else in response to the error ? */
2181 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002182 "Interrupt from HIF module BAD (function %x)\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002183 phm->function);
2184 }
2185
2186 /* reset the interrupt from the DSP */
2187 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2188#endif
2189
2190 /* read the result */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002191 if (time_out) {
2192 if (interface->u.response_buffer.size <= phr->size)
2193 memcpy(phr, &interface->u.response_buffer,
2194 interface->u.response_buffer.size);
2195 else {
2196 HPI_DEBUG_LOG(ERROR,
2197 "response len %d too big for buffer %d\n",
2198 interface->u.response_buffer.size, phr->size);
2199 memcpy(phr, &interface->u.response_buffer,
2200 sizeof(struct hpi_response_header));
2201 phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
2202 phr->specific_error =
2203 interface->u.response_buffer.size;
2204 phr->size = sizeof(struct hpi_response_header);
2205 }
2206 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002207 /* set interface back to idle */
2208 send_dsp_command(phw, H620_HIF_IDLE);
2209
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002210 if (!time_out || !time_out2) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002211 HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002212 return HPI6205_ERROR_MSG_RESP_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002213 }
2214 /* special case for adapter close - */
2215 /* wait for the DSP to indicate it is idle */
2216 if (phm->function == HPI_ADAPTER_CLOSE) {
2217 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2218 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002219 "Timeout waiting for idle "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002220 "(on adapter_close)\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002221 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002222 }
2223 }
2224 err = hpi_validate_response(phm, phr);
2225 return err;
2226}
2227
2228static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
2229 struct hpi_response *phr)
2230{
2231
2232 u16 err = 0;
2233
2234 hpios_dsplock_lock(pao);
2235
2236 err = message_response_sequence(pao, phm, phr);
2237
2238 /* maybe an error response */
2239 if (err) {
2240 /* something failed in the HPI/DSP interface */
2241 phr->error = err;
2242 pao->dsp_crashed++;
2243
2244 /* just the header of the response is valid */
2245 phr->size = sizeof(struct hpi_response_header);
2246 goto err;
2247 } else
2248 pao->dsp_crashed = 0;
2249
2250 if (phr->error != 0) /* something failed in the DSP */
2251 goto err;
2252
2253 switch (phm->function) {
2254 case HPI_OSTREAM_WRITE:
2255 case HPI_ISTREAM_ANC_WRITE:
2256 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2257 phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);
2258 break;
2259
2260 case HPI_ISTREAM_READ:
2261 case HPI_OSTREAM_ANC_READ:
2262 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2263 phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
2264 break;
2265
2266 case HPI_CONTROL_SET_STATE:
2267 if (phm->object == HPI_OBJ_CONTROLEX
2268 && phm->u.cx.attribute == HPI_COBRANET_SET_DATA)
2269 err = hpi6205_transfer_data(pao,
2270 phm->u.cx.u.cobranet_bigdata.pb_data,
2271 phm->u.cx.u.cobranet_bigdata.byte_count,
2272 H620_HIF_SEND_DATA);
2273 break;
2274
2275 case HPI_CONTROL_GET_STATE:
2276 if (phm->object == HPI_OBJ_CONTROLEX
2277 && phm->u.cx.attribute == HPI_COBRANET_GET_DATA)
2278 err = hpi6205_transfer_data(pao,
2279 phm->u.cx.u.cobranet_bigdata.pb_data,
2280 phr->u.cx.u.cobranet_data.byte_count,
2281 H620_HIF_GET_DATA);
2282 break;
2283 }
2284 phr->error = err;
2285
2286err:
2287 hpios_dsplock_unlock(pao);
2288
2289 return;
2290}