blob: 5fe535b1b096ec00a58f5b08c47fbe7a382f5d91 [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 Blennerhassettdeb21a22011-02-10 17:26:03 +130041#define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130042
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) {
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +1300296 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200297 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) {
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +1300340 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200341 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);
Eliot Blennerhassett0a000442011-02-10 17:26:05 +1300481 if (err >= HPI_ERROR_BACKEND_BASE) {
482 phr->error = HPI_ERROR_DSP_BOOTLOAD;
483 phr->specific_error = err;
484 } else {
485 phr->error = err;
486 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300487 phr->u.s.data = os_error_code;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200488 return;
489 }
490
491 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
492 phr->u.s.adapter_index = ao.index;
493 phr->u.s.num_adapters++;
494 phr->error = 0;
495}
496
497/** delete an adapter - required by WDM driver */
498static void subsys_delete_adapter(struct hpi_message *phm,
499 struct hpi_response *phr)
500{
501 struct hpi_adapter_obj *pao;
502 struct hpi_hw_obj *phw;
503
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300504 pao = hpi_find_adapter(phm->obj_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200505 if (!pao) {
506 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
507 return;
508 }
509 phw = (struct hpi_hw_obj *)pao->priv;
510 /* reset adapter h/w */
511 /* Reset C6713 #1 */
512 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
513 /* reset C6205 */
514 iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
515
516 delete_adapter_obj(pao);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300517 hpi_delete_adapter(pao);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200518 phr->error = 0;
519}
520
521/** Create adapter object
522 allocate buffers, bootload DSPs, initialise control cache
523*/
524static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
525 u32 *pos_error_code)
526{
527 struct hpi_hw_obj *phw = pao->priv;
528 struct bus_master_interface *interface;
529 u32 phys_addr;
530#ifndef HPI6205_NO_HSR_POLL
531 u32 time_out = HPI6205_TIMEOUT;
532 u32 temp1;
533#endif
534 int i;
535 u16 err;
536
537 /* init error reporting */
538 pao->dsp_crashed = 0;
539
540 for (i = 0; i < HPI_MAX_STREAMS; i++)
541 phw->flag_outstream_just_reset[i] = 1;
542
543 /* The C6205 memory area 1 is 8Mbyte window into DSP registers */
544 phw->prHSR =
545 pao->pci.ap_mem_base[1] +
546 C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);
547 phw->prHDCR =
548 pao->pci.ap_mem_base[1] +
549 C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);
550 phw->prDSPP =
551 pao->pci.ap_mem_base[1] +
552 C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);
553
554 pao->has_control_cache = 0;
555
556 if (hpios_locked_mem_alloc(&phw->h_locked_mem,
557 sizeof(struct bus_master_interface),
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300558 pao->pci.pci_dev))
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200559 phw->p_interface_buffer = NULL;
560 else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
561 (void *)&phw->p_interface_buffer))
562 phw->p_interface_buffer = NULL;
563
564 HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",
565 phw->p_interface_buffer);
566
567 if (phw->p_interface_buffer) {
568 memset((void *)phw->p_interface_buffer, 0,
569 sizeof(struct bus_master_interface));
570 phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;
571 }
572
573 err = adapter_boot_load_dsp(pao, pos_error_code);
574 if (err)
575 /* no need to clean up as SubSysCreateAdapter */
576 /* calls DeleteAdapter on error. */
577 return err;
578
579 HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
580
581 /* allow boot load even if mem alloc wont work */
582 if (!phw->p_interface_buffer)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300583 return HPI_ERROR_MEMORY_ALLOC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200584
585 interface = phw->p_interface_buffer;
586
587#ifndef HPI6205_NO_HSR_POLL
588 /* wait for first interrupt indicating the DSP init is done */
589 time_out = HPI6205_TIMEOUT * 10;
590 temp1 = 0;
591 while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out)
592 temp1 = ioread32(phw->prHSR);
593
594 if (temp1 & C6205_HSR_INTSRC)
595 HPI_DEBUG_LOG(INFO,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300596 "Interrupt confirming DSP code running OK\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200597 else {
598 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300599 "Timed out waiting for interrupt "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200600 "confirming DSP code running\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300601 return HPI6205_ERROR_6205_NO_IRQ;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200602 }
603
604 /* reset the interrupt */
605 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
606#endif
607
608 /* make sure the DSP has started ok */
609 if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
610 HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300611 return HPI6205_ERROR_6205_INIT_FAILED;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200612 }
613 /* Note that *pao, *phw are zeroed after allocation,
614 * so pointers and flags are NULL by default.
615 * Allocate bus mastering control cache buffer and tell the DSP about it
616 */
617 if (interface->control_cache.number_of_controls) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300618 u8 *p_control_cache_virtual;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200619
620 err = hpios_locked_mem_alloc(&phw->h_control_cache,
621 interface->control_cache.size_in_bytes,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300622 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200623 if (!err)
624 err = hpios_locked_mem_get_virt_addr(&phw->
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300625 h_control_cache,
626 (void *)&p_control_cache_virtual);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200627 if (!err) {
628 memset(p_control_cache_virtual, 0,
629 interface->control_cache.size_in_bytes);
630
631 phw->p_cache =
632 hpi_alloc_control_cache(interface->
633 control_cache.number_of_controls,
634 interface->control_cache.size_in_bytes,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200635 p_control_cache_virtual);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200636 if (!phw->p_cache)
637 err = HPI_ERROR_MEMORY_ALLOC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200638 }
639 if (!err) {
640 err = hpios_locked_mem_get_phys_addr(&phw->
641 h_control_cache, &phys_addr);
642 interface->control_cache.physical_address32 =
643 phys_addr;
644 }
645
646 if (!err)
647 pao->has_control_cache = 1;
648 else {
649 if (hpios_locked_mem_valid(&phw->h_control_cache))
650 hpios_locked_mem_free(&phw->h_control_cache);
651 pao->has_control_cache = 0;
652 }
653 }
654 /* allocate bus mastering async buffer and tell the DSP about it */
655 if (interface->async_buffer.b.size) {
656 err = hpios_locked_mem_alloc(&phw->h_async_event_buffer,
657 interface->async_buffer.b.size *
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300658 sizeof(struct hpi_async_event), pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200659 if (!err)
660 err = hpios_locked_mem_get_virt_addr
661 (&phw->h_async_event_buffer, (void *)
662 &phw->p_async_event_buffer);
663 if (!err)
664 memset((void *)phw->p_async_event_buffer, 0,
665 interface->async_buffer.b.size *
666 sizeof(struct hpi_async_event));
667 if (!err) {
668 err = hpios_locked_mem_get_phys_addr
669 (&phw->h_async_event_buffer, &phys_addr);
670 interface->async_buffer.physical_address32 =
671 phys_addr;
672 }
673 if (err) {
674 if (hpios_locked_mem_valid(&phw->
675 h_async_event_buffer)) {
676 hpios_locked_mem_free
677 (&phw->h_async_event_buffer);
678 phw->p_async_event_buffer = NULL;
679 }
680 }
681 }
682 send_dsp_command(phw, H620_HIF_IDLE);
683
684 {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300685 struct hpi_message hm;
686 struct hpi_response hr;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200687 u32 max_streams;
688
689 HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300690 memset(&hm, 0, sizeof(hm));
691 hm.type = HPI_TYPE_MESSAGE;
692 hm.size = sizeof(hm);
693 hm.object = HPI_OBJ_ADAPTER;
694 hm.function = HPI_ADAPTER_GET_INFO;
695 hm.adapter_index = 0;
696 memset(&hr, 0, sizeof(hr));
697 hr.size = sizeof(hr);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200698
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300699 err = message_response_sequence(pao, &hm, &hr);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200700 if (err) {
701 HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
702 err);
703 return err;
704 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300705 if (hr.error)
706 return hr.error;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200707
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300708 pao->adapter_type = hr.u.ax.info.adapter_type;
709 pao->index = hr.u.ax.info.adapter_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200710
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300711 max_streams =
712 hr.u.ax.info.num_outstreams +
713 hr.u.ax.info.num_instreams;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200714
715 hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300716 65536, pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200717
718 HPI_DEBUG_LOG(VERBOSE,
719 "got adapter info type %x index %d serial %d\n",
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300720 hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,
721 hr.u.ax.info.serial_number);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200722 }
723
724 pao->open = 0; /* upon creation the adapter is closed */
725
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300726 if (phw->p_cache)
727 phw->p_cache->adap_idx = pao->index;
728
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200729 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300730
731 return hpi_add_adapter(pao);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200732}
733
734/** Free memory areas allocated by adapter
735 * this routine is called from SubSysDeleteAdapter,
736 * and SubSysCreateAdapter if duplicate index
737*/
738static void delete_adapter_obj(struct hpi_adapter_obj *pao)
739{
740 struct hpi_hw_obj *phw;
741 int i;
742
743 phw = pao->priv;
744
745 if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) {
746 hpios_locked_mem_free(&phw->h_async_event_buffer);
747 phw->p_async_event_buffer = NULL;
748 }
749
750 if (hpios_locked_mem_valid(&phw->h_control_cache)) {
751 hpios_locked_mem_free(&phw->h_control_cache);
752 hpi_free_control_cache(phw->p_cache);
753 }
754
755 if (hpios_locked_mem_valid(&phw->h_locked_mem)) {
756 hpios_locked_mem_free(&phw->h_locked_mem);
757 phw->p_interface_buffer = NULL;
758 }
759
760 for (i = 0; i < HPI_MAX_STREAMS; i++)
761 if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {
762 hpios_locked_mem_free(&phw->instream_host_buffers[i]);
763 /*?phw->InStreamHostBuffers[i] = NULL; */
764 phw->instream_host_buffer_size[i] = 0;
765 }
766
767 for (i = 0; i < HPI_MAX_STREAMS; i++)
768 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {
769 hpios_locked_mem_free(&phw->outstream_host_buffers
770 [i]);
771 phw->outstream_host_buffer_size[i] = 0;
772 }
773
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300774 hpios_locked_mem_unprepare(pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200775
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200776 kfree(phw);
777}
778
779/*****************************************************************************/
780/* OutStream Host buffer functions */
781
782/** Allocate or attach buffer for busmastering
783*/
784static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
785 struct hpi_message *phm, struct hpi_response *phr)
786{
787 u16 err = 0;
788 u32 command = phm->u.d.u.buffer.command;
789 struct hpi_hw_obj *phw = pao->priv;
790 struct bus_master_interface *interface = phw->p_interface_buffer;
791
792 hpi_init_response(phr, phm->object, phm->function, 0);
793
794 if (command == HPI_BUFFER_CMD_EXTERNAL
795 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
796 /* ALLOC phase, allocate a buffer with power of 2 size,
797 get its bus address for PCI bus mastering
798 */
799 phm->u.d.u.buffer.buffer_size =
800 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
801 /* return old size and allocated size,
802 so caller can detect change */
803 phr->u.d.u.stream_info.data_available =
804 phw->outstream_host_buffer_size[phm->obj_index];
805 phr->u.d.u.stream_info.buffer_size =
806 phm->u.d.u.buffer.buffer_size;
807
808 if (phw->outstream_host_buffer_size[phm->obj_index] ==
809 phm->u.d.u.buffer.buffer_size) {
810 /* Same size, no action required */
811 return;
812 }
813
814 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
815 obj_index]))
816 hpios_locked_mem_free(&phw->outstream_host_buffers
817 [phm->obj_index]);
818
819 err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
820 [phm->obj_index], phm->u.d.u.buffer.buffer_size,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300821 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200822
823 if (err) {
824 phr->error = HPI_ERROR_INVALID_DATASIZE;
825 phw->outstream_host_buffer_size[phm->obj_index] = 0;
826 return;
827 }
828
829 err = hpios_locked_mem_get_phys_addr
830 (&phw->outstream_host_buffers[phm->obj_index],
831 &phm->u.d.u.buffer.pci_address);
832 /* get the phys addr into msg for single call alloc caller
833 * needs to do this for split alloc (or use the same message)
834 * return the phy address for split alloc in the respose too
835 */
836 phr->u.d.u.stream_info.auxiliary_data_available =
837 phm->u.d.u.buffer.pci_address;
838
839 if (err) {
840 hpios_locked_mem_free(&phw->outstream_host_buffers
841 [phm->obj_index]);
842 phw->outstream_host_buffer_size[phm->obj_index] = 0;
843 phr->error = HPI_ERROR_MEMORY_ALLOC;
844 return;
845 }
846 }
847
848 if (command == HPI_BUFFER_CMD_EXTERNAL
849 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
850 /* GRANT phase. Set up the BBM status, tell the DSP about
851 the buffer so it can start using BBM.
852 */
853 struct hpi_hostbuffer_status *status;
854
855 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
856 buffer_size - 1)) {
857 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300858 "Buffer size must be 2^N not %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200859 phm->u.d.u.buffer.buffer_size);
860 phr->error = HPI_ERROR_INVALID_DATASIZE;
861 return;
862 }
863 phw->outstream_host_buffer_size[phm->obj_index] =
864 phm->u.d.u.buffer.buffer_size;
865 status = &interface->outstream_host_buffer_status[phm->
866 obj_index];
867 status->samples_processed = 0;
868 status->stream_state = HPI_STATE_STOPPED;
869 status->dSP_index = 0;
870 status->host_index = status->dSP_index;
871 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +1300872 status->auxiliary_data_available = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200873
874 hw_message(pao, phm, phr);
875
876 if (phr->error
877 && hpios_locked_mem_valid(&phw->
878 outstream_host_buffers[phm->obj_index])) {
879 hpios_locked_mem_free(&phw->outstream_host_buffers
880 [phm->obj_index]);
881 phw->outstream_host_buffer_size[phm->obj_index] = 0;
882 }
883 }
884}
885
886static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
887 struct hpi_message *phm, struct hpi_response *phr)
888{
889 struct hpi_hw_obj *phw = pao->priv;
890 struct bus_master_interface *interface = phw->p_interface_buffer;
891 struct hpi_hostbuffer_status *status;
892 u8 *p_bbm_data;
893
894 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
895 obj_index])) {
896 if (hpios_locked_mem_get_virt_addr(&phw->
897 outstream_host_buffers[phm->obj_index],
898 (void *)&p_bbm_data)) {
899 phr->error = HPI_ERROR_INVALID_OPERATION;
900 return;
901 }
902 status = &interface->outstream_host_buffer_status[phm->
903 obj_index];
904 hpi_init_response(phr, HPI_OBJ_OSTREAM,
905 HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);
906 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
907 phr->u.d.u.hostbuffer_info.p_status = status;
908 } else {
909 hpi_init_response(phr, HPI_OBJ_OSTREAM,
910 HPI_OSTREAM_HOSTBUFFER_GET_INFO,
911 HPI_ERROR_INVALID_OPERATION);
912 }
913}
914
915static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
916 struct hpi_message *phm, struct hpi_response *phr)
917{
918 struct hpi_hw_obj *phw = pao->priv;
919 u32 command = phm->u.d.u.buffer.command;
920
921 if (phw->outstream_host_buffer_size[phm->obj_index]) {
922 if (command == HPI_BUFFER_CMD_EXTERNAL
923 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
924 phw->outstream_host_buffer_size[phm->obj_index] = 0;
925 hw_message(pao, phm, phr);
926 /* Tell adapter to stop using the host buffer. */
927 }
928 if (command == HPI_BUFFER_CMD_EXTERNAL
929 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
930 hpios_locked_mem_free(&phw->outstream_host_buffers
931 [phm->obj_index]);
932 }
933 /* Should HPI_ERROR_INVALID_OPERATION be returned
934 if no host buffer is allocated? */
935 else
936 hpi_init_response(phr, HPI_OBJ_OSTREAM,
937 HPI_OSTREAM_HOSTBUFFER_FREE, 0);
938
939}
940
Eliot Blennerhassett60f1deb2010-08-28 19:52:24 +1200941static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200942{
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200943 return status->size_in_bytes - (status->host_index -
944 status->dSP_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200945}
946
947static void outstream_write(struct hpi_adapter_obj *pao,
948 struct hpi_message *phm, struct hpi_response *phr)
949{
950 struct hpi_hw_obj *phw = pao->priv;
951 struct bus_master_interface *interface = phw->p_interface_buffer;
952 struct hpi_hostbuffer_status *status;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200953 u32 space_available;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200954
955 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
956 /* there is no BBM buffer, write via message */
957 hw_message(pao, phm, phr);
958 return;
959 }
960
961 hpi_init_response(phr, phm->object, phm->function, 0);
962 status = &interface->outstream_host_buffer_status[phm->obj_index];
963
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200964 space_available = outstream_get_space_available(status);
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200965 if (space_available < phm->u.d.u.data.data_size) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200966 phr->error = HPI_ERROR_INVALID_DATASIZE;
967 return;
968 }
969
970 /* HostBuffers is used to indicate host buffer is internally allocated.
971 otherwise, assumed external, data written externally */
972 if (phm->u.d.u.data.pb_data
973 && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
974 obj_index])) {
975 u8 *p_bbm_data;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +1200976 u32 l_first_write;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200977 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
978
979 if (hpios_locked_mem_get_virt_addr(&phw->
980 outstream_host_buffers[phm->obj_index],
981 (void *)&p_bbm_data)) {
982 phr->error = HPI_ERROR_INVALID_OPERATION;
983 return;
984 }
985
986 /* either all data,
987 or enough to fit from current to end of BBM buffer */
988 l_first_write =
989 min(phm->u.d.u.data.data_size,
990 status->size_in_bytes -
991 (status->host_index & (status->size_in_bytes - 1)));
992
993 memcpy(p_bbm_data +
994 (status->host_index & (status->size_in_bytes - 1)),
995 p_app_data, l_first_write);
996 /* remaining data if any */
997 memcpy(p_bbm_data, p_app_data + l_first_write,
998 phm->u.d.u.data.data_size - l_first_write);
999 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001000
1001 /*
1002 * This version relies on the DSP code triggering an OStream buffer
1003 * update immediately following a SET_FORMAT call. The host has
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +13001004 * already written data into the BBM buffer, but the DSP won't know
1005 * about it until dwHostIndex is adjusted.
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001006 */
1007 if (phw->flag_outstream_just_reset[phm->obj_index]) {
1008 /* Format can only change after reset. Must tell DSP. */
1009 u16 function = phm->function;
1010 phw->flag_outstream_just_reset[phm->obj_index] = 0;
1011 phm->function = HPI_OSTREAM_SET_FORMAT;
1012 hw_message(pao, phm, phr); /* send the format to the DSP */
1013 phm->function = function;
1014 if (phr->error)
1015 return;
1016 }
1017
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001018 status->host_index += phm->u.d.u.data.data_size;
1019}
1020
1021static void outstream_get_info(struct hpi_adapter_obj *pao,
1022 struct hpi_message *phm, struct hpi_response *phr)
1023{
1024 struct hpi_hw_obj *phw = pao->priv;
1025 struct bus_master_interface *interface = phw->p_interface_buffer;
1026 struct hpi_hostbuffer_status *status;
1027
1028 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
1029 hw_message(pao, phm, phr);
1030 return;
1031 }
1032
1033 hpi_init_response(phr, phm->object, phm->function, 0);
1034
1035 status = &interface->outstream_host_buffer_status[phm->obj_index];
1036
1037 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1038 phr->u.d.u.stream_info.samples_transferred =
1039 status->samples_processed;
1040 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1041 phr->u.d.u.stream_info.data_available =
1042 status->size_in_bytes - outstream_get_space_available(status);
1043 phr->u.d.u.stream_info.auxiliary_data_available =
1044 status->auxiliary_data_available;
1045}
1046
1047static void outstream_start(struct hpi_adapter_obj *pao,
1048 struct hpi_message *phm, struct hpi_response *phr)
1049{
1050 hw_message(pao, phm, phr);
1051}
1052
1053static void outstream_reset(struct hpi_adapter_obj *pao,
1054 struct hpi_message *phm, struct hpi_response *phr)
1055{
1056 struct hpi_hw_obj *phw = pao->priv;
1057 phw->flag_outstream_just_reset[phm->obj_index] = 1;
1058 hw_message(pao, phm, phr);
1059}
1060
1061static void outstream_open(struct hpi_adapter_obj *pao,
1062 struct hpi_message *phm, struct hpi_response *phr)
1063{
1064 outstream_reset(pao, phm, phr);
1065}
1066
1067/*****************************************************************************/
1068/* InStream Host buffer functions */
1069
1070static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1071 struct hpi_message *phm, struct hpi_response *phr)
1072{
1073 u16 err = 0;
1074 u32 command = phm->u.d.u.buffer.command;
1075 struct hpi_hw_obj *phw = pao->priv;
1076 struct bus_master_interface *interface = phw->p_interface_buffer;
1077
1078 hpi_init_response(phr, phm->object, phm->function, 0);
1079
1080 if (command == HPI_BUFFER_CMD_EXTERNAL
1081 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
1082
1083 phm->u.d.u.buffer.buffer_size =
1084 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
1085 phr->u.d.u.stream_info.data_available =
1086 phw->instream_host_buffer_size[phm->obj_index];
1087 phr->u.d.u.stream_info.buffer_size =
1088 phm->u.d.u.buffer.buffer_size;
1089
1090 if (phw->instream_host_buffer_size[phm->obj_index] ==
1091 phm->u.d.u.buffer.buffer_size) {
1092 /* Same size, no action required */
1093 return;
1094 }
1095
1096 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1097 obj_index]))
1098 hpios_locked_mem_free(&phw->instream_host_buffers
1099 [phm->obj_index]);
1100
1101 err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
1102 obj_index], phm->u.d.u.buffer.buffer_size,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001103 pao->pci.pci_dev);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001104
1105 if (err) {
1106 phr->error = HPI_ERROR_INVALID_DATASIZE;
1107 phw->instream_host_buffer_size[phm->obj_index] = 0;
1108 return;
1109 }
1110
1111 err = hpios_locked_mem_get_phys_addr
1112 (&phw->instream_host_buffers[phm->obj_index],
1113 &phm->u.d.u.buffer.pci_address);
1114 /* get the phys addr into msg for single call alloc. Caller
1115 needs to do this for split alloc so return the phy address */
1116 phr->u.d.u.stream_info.auxiliary_data_available =
1117 phm->u.d.u.buffer.pci_address;
1118 if (err) {
1119 hpios_locked_mem_free(&phw->instream_host_buffers
1120 [phm->obj_index]);
1121 phw->instream_host_buffer_size[phm->obj_index] = 0;
1122 phr->error = HPI_ERROR_MEMORY_ALLOC;
1123 return;
1124 }
1125 }
1126
1127 if (command == HPI_BUFFER_CMD_EXTERNAL
1128 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
1129 struct hpi_hostbuffer_status *status;
1130
1131 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
1132 buffer_size - 1)) {
1133 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001134 "Buffer size must be 2^N not %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001135 phm->u.d.u.buffer.buffer_size);
1136 phr->error = HPI_ERROR_INVALID_DATASIZE;
1137 return;
1138 }
1139
1140 phw->instream_host_buffer_size[phm->obj_index] =
1141 phm->u.d.u.buffer.buffer_size;
1142 status = &interface->instream_host_buffer_status[phm->
1143 obj_index];
1144 status->samples_processed = 0;
1145 status->stream_state = HPI_STATE_STOPPED;
1146 status->dSP_index = 0;
1147 status->host_index = status->dSP_index;
1148 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +13001149 status->auxiliary_data_available = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001150
1151 hw_message(pao, phm, phr);
1152 if (phr->error
1153 && hpios_locked_mem_valid(&phw->
1154 instream_host_buffers[phm->obj_index])) {
1155 hpios_locked_mem_free(&phw->instream_host_buffers
1156 [phm->obj_index]);
1157 phw->instream_host_buffer_size[phm->obj_index] = 0;
1158 }
1159 }
1160}
1161
1162static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1163 struct hpi_message *phm, struct hpi_response *phr)
1164{
1165 struct hpi_hw_obj *phw = pao->priv;
1166 struct bus_master_interface *interface = phw->p_interface_buffer;
1167 struct hpi_hostbuffer_status *status;
1168 u8 *p_bbm_data;
1169
1170 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1171 obj_index])) {
1172 if (hpios_locked_mem_get_virt_addr(&phw->
1173 instream_host_buffers[phm->obj_index],
1174 (void *)&p_bbm_data)) {
1175 phr->error = HPI_ERROR_INVALID_OPERATION;
1176 return;
1177 }
1178 status = &interface->instream_host_buffer_status[phm->
1179 obj_index];
1180 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1181 HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);
1182 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
1183 phr->u.d.u.hostbuffer_info.p_status = status;
1184 } else {
1185 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1186 HPI_ISTREAM_HOSTBUFFER_GET_INFO,
1187 HPI_ERROR_INVALID_OPERATION);
1188 }
1189}
1190
1191static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
1192 struct hpi_message *phm, struct hpi_response *phr)
1193{
1194 struct hpi_hw_obj *phw = pao->priv;
1195 u32 command = phm->u.d.u.buffer.command;
1196
1197 if (phw->instream_host_buffer_size[phm->obj_index]) {
1198 if (command == HPI_BUFFER_CMD_EXTERNAL
1199 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
1200 phw->instream_host_buffer_size[phm->obj_index] = 0;
1201 hw_message(pao, phm, phr);
1202 }
1203
1204 if (command == HPI_BUFFER_CMD_EXTERNAL
1205 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
1206 hpios_locked_mem_free(&phw->instream_host_buffers
1207 [phm->obj_index]);
1208
1209 } else {
1210 /* Should HPI_ERROR_INVALID_OPERATION be returned
1211 if no host buffer is allocated? */
1212 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1213 HPI_ISTREAM_HOSTBUFFER_FREE, 0);
1214
1215 }
1216
1217}
1218
1219static void instream_start(struct hpi_adapter_obj *pao,
1220 struct hpi_message *phm, struct hpi_response *phr)
1221{
1222 hw_message(pao, phm, phr);
1223}
1224
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001225static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001226{
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001227 return status->dSP_index - status->host_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001228}
1229
1230static void instream_read(struct hpi_adapter_obj *pao,
1231 struct hpi_message *phm, struct hpi_response *phr)
1232{
1233 struct hpi_hw_obj *phw = pao->priv;
1234 struct bus_master_interface *interface = phw->p_interface_buffer;
1235 struct hpi_hostbuffer_status *status;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001236 u32 data_available;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001237 u8 *p_bbm_data;
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001238 u32 l_first_read;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001239 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1240
1241 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1242 hw_message(pao, phm, phr);
1243 return;
1244 }
1245 hpi_init_response(phr, phm->object, phm->function, 0);
1246
1247 status = &interface->instream_host_buffer_status[phm->obj_index];
1248 data_available = instream_get_bytes_available(status);
Eliot Blennerhassett2a383cb2010-06-17 17:08:36 +12001249 if (data_available < phm->u.d.u.data.data_size) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001250 phr->error = HPI_ERROR_INVALID_DATASIZE;
1251 return;
1252 }
1253
1254 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1255 obj_index])) {
1256 if (hpios_locked_mem_get_virt_addr(&phw->
1257 instream_host_buffers[phm->obj_index],
1258 (void *)&p_bbm_data)) {
1259 phr->error = HPI_ERROR_INVALID_OPERATION;
1260 return;
1261 }
1262
1263 /* either all data,
1264 or enough to fit from current to end of BBM buffer */
1265 l_first_read =
1266 min(phm->u.d.u.data.data_size,
1267 status->size_in_bytes -
1268 (status->host_index & (status->size_in_bytes - 1)));
1269
1270 memcpy(p_app_data,
1271 p_bbm_data +
1272 (status->host_index & (status->size_in_bytes - 1)),
1273 l_first_read);
1274 /* remaining data if any */
1275 memcpy(p_app_data + l_first_read, p_bbm_data,
1276 phm->u.d.u.data.data_size - l_first_read);
1277 }
1278 status->host_index += phm->u.d.u.data.data_size;
1279}
1280
1281static void instream_get_info(struct hpi_adapter_obj *pao,
1282 struct hpi_message *phm, struct hpi_response *phr)
1283{
1284 struct hpi_hw_obj *phw = pao->priv;
1285 struct bus_master_interface *interface = phw->p_interface_buffer;
1286 struct hpi_hostbuffer_status *status;
1287 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1288 hw_message(pao, phm, phr);
1289 return;
1290 }
1291
1292 status = &interface->instream_host_buffer_status[phm->obj_index];
1293
1294 hpi_init_response(phr, phm->object, phm->function, 0);
1295
1296 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1297 phr->u.d.u.stream_info.samples_transferred =
1298 status->samples_processed;
1299 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1300 phr->u.d.u.stream_info.data_available =
1301 instream_get_bytes_available(status);
1302 phr->u.d.u.stream_info.auxiliary_data_available =
1303 status->auxiliary_data_available;
1304}
1305
1306/*****************************************************************************/
1307/* LOW-LEVEL */
1308#define HPI6205_MAX_FILES_TO_LOAD 2
1309
1310static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1311 u32 *pos_error_code)
1312{
1313 struct hpi_hw_obj *phw = pao->priv;
1314 struct dsp_code dsp_code;
1315 u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001316 u16 firmware_id = pao->pci.pci_dev->subsystem_device;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001317 u32 temp;
1318 int dsp = 0, i = 0;
1319 u16 err = 0;
1320
1321 boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
1322
1323 /* special cases where firmware_id != subsys ID */
1324 switch (firmware_id) {
1325 case HPI_ADAPTER_FAMILY_ASI(0x5000):
1326 boot_code_id[0] = firmware_id;
1327 firmware_id = 0;
1328 break;
1329 case HPI_ADAPTER_FAMILY_ASI(0x5300):
1330 case HPI_ADAPTER_FAMILY_ASI(0x5400):
1331 case HPI_ADAPTER_FAMILY_ASI(0x6300):
1332 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400);
1333 break;
1334 case HPI_ADAPTER_FAMILY_ASI(0x5600):
1335 case HPI_ADAPTER_FAMILY_ASI(0x6500):
1336 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
1337 break;
Eliot Blennerhassettcadae422010-05-27 17:53:54 +12001338 case HPI_ADAPTER_FAMILY_ASI(0x8800):
1339 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900);
1340 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001341 }
1342 boot_code_id[1] = firmware_id;
1343
1344 /* reset DSP by writing a 1 to the WARMRESET bit */
1345 temp = C6205_HDCR_WARMRESET;
1346 iowrite32(temp, phw->prHDCR);
1347 hpios_delay_micro_seconds(1000);
1348
1349 /* check that PCI i/f was configured by EEPROM */
1350 temp = ioread32(phw->prHSR);
1351 if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
1352 C6205_HSR_EEREAD)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001353 return HPI6205_ERROR_6205_EEPROM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001354 temp |= 0x04;
1355 /* disable PINTA interrupt */
1356 iowrite32(temp, phw->prHSR);
1357
1358 /* check control register reports PCI boot mode */
1359 temp = ioread32(phw->prHDCR);
1360 if (!(temp & C6205_HDCR_PCIBOOT))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001361 return HPI6205_ERROR_6205_REG;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001362
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001363 /* try writing a few numbers to the DSP page register */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001364 /* and reading them back. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001365 temp = 3;
1366 iowrite32(temp, phw->prDSPP);
1367 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001368 return HPI6205_ERROR_6205_DSPPAGE;
1369 temp = 2;
1370 iowrite32(temp, phw->prDSPP);
1371 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1372 return HPI6205_ERROR_6205_DSPPAGE;
1373 temp = 1;
1374 iowrite32(temp, phw->prDSPP);
1375 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1376 return HPI6205_ERROR_6205_DSPPAGE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001377 /* reset DSP page to the correct number */
1378 temp = 0;
1379 iowrite32(temp, phw->prDSPP);
1380 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001381 return HPI6205_ERROR_6205_DSPPAGE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001382 phw->dsp_page = 0;
1383
1384 /* release 6713 from reset before 6205 is bootloaded.
1385 This ensures that the EMIF is inactive,
1386 and the 6713 HPI gets the correct bootmode etc
1387 */
1388 if (boot_code_id[1] != 0) {
1389 /* DSP 1 is a C6713 */
1390 /* CLKX0 <- '1' release the C6205 bootmode pulldowns */
1391 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002202);
1392 hpios_delay_micro_seconds(100);
1393 /* Reset the 6713 #1 - revB */
1394 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
1395
1396 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1397 boot_loader_read_mem32(pao, 0, 0);
1398
1399 hpios_delay_micro_seconds(100);
1400 /* Release C6713 from reset - revB */
1401 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);
1402 hpios_delay_micro_seconds(100);
1403 }
1404
1405 for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {
1406 /* is there a DSP to load? */
1407 if (boot_code_id[dsp] == 0)
1408 continue;
1409
1410 err = boot_loader_config_emif(pao, dsp);
1411 if (err)
1412 return err;
1413
1414 err = boot_loader_test_internal_memory(pao, dsp);
1415 if (err)
1416 return err;
1417
1418 err = boot_loader_test_external_memory(pao, dsp);
1419 if (err)
1420 return err;
1421
1422 err = boot_loader_test_pld(pao, dsp);
1423 if (err)
1424 return err;
1425
1426 /* write the DSP code down into the DSPs memory */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001427 dsp_code.ps_dev = pao->pci.pci_dev;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001428 err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
1429 pos_error_code);
1430 if (err)
1431 return err;
1432
1433 while (1) {
1434 u32 length;
1435 u32 address;
1436 u32 type;
1437 u32 *pcode;
1438
1439 err = hpi_dsp_code_read_word(&dsp_code, &length);
1440 if (err)
1441 break;
1442 if (length == 0xFFFFFFFF)
1443 break; /* end of code */
1444
1445 err = hpi_dsp_code_read_word(&dsp_code, &address);
1446 if (err)
1447 break;
1448 err = hpi_dsp_code_read_word(&dsp_code, &type);
1449 if (err)
1450 break;
1451 err = hpi_dsp_code_read_block(length, &dsp_code,
1452 &pcode);
1453 if (err)
1454 break;
1455 for (i = 0; i < (int)length; i++) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001456 boot_loader_write_mem32(pao, dsp, address,
1457 *pcode);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001458 /* dummy read every 4 words */
1459 /* for 6205 advisory 1.4.4 */
1460 if (i % 4 == 0)
1461 boot_loader_read_mem32(pao, dsp,
1462 address);
1463 pcode++;
1464 address += 4;
1465 }
1466
1467 }
1468 if (err) {
1469 hpi_dsp_code_close(&dsp_code);
1470 return err;
1471 }
1472
1473 /* verify code */
1474 hpi_dsp_code_rewind(&dsp_code);
1475 while (1) {
1476 u32 length = 0;
1477 u32 address = 0;
1478 u32 type = 0;
1479 u32 *pcode = NULL;
1480 u32 data = 0;
1481
1482 hpi_dsp_code_read_word(&dsp_code, &length);
1483 if (length == 0xFFFFFFFF)
1484 break; /* end of code */
1485
1486 hpi_dsp_code_read_word(&dsp_code, &address);
1487 hpi_dsp_code_read_word(&dsp_code, &type);
1488 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1489
1490 for (i = 0; i < (int)length; i++) {
1491 data = boot_loader_read_mem32(pao, dsp,
1492 address);
1493 if (data != *pcode) {
1494 err = 0;
1495 break;
1496 }
1497 pcode++;
1498 address += 4;
1499 }
1500 if (err)
1501 break;
1502 }
1503 hpi_dsp_code_close(&dsp_code);
1504 if (err)
1505 return err;
1506 }
1507
1508 /* After bootloading all DSPs, start DSP0 running
1509 * The DSP0 code will handle starting and synchronizing with its slaves
1510 */
1511 if (phw->p_interface_buffer) {
1512 /* we need to tell the card the physical PCI address */
1513 u32 physicalPC_iaddress;
1514 struct bus_master_interface *interface =
1515 phw->p_interface_buffer;
1516 u32 host_mailbox_address_on_dsp;
1517 u32 physicalPC_iaddress_verify = 0;
1518 int time_out = 10;
1519 /* set ack so we know when DSP is ready to go */
1520 /* (dwDspAck will be changed to HIF_RESET) */
1521 interface->dsp_ack = H620_HIF_UNKNOWN;
1522 wmb(); /* ensure ack is written before dsp writes back */
1523
1524 err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,
1525 &physicalPC_iaddress);
1526
1527 /* locate the host mailbox on the DSP. */
1528 host_mailbox_address_on_dsp = 0x80000000;
1529 while ((physicalPC_iaddress != physicalPC_iaddress_verify)
1530 && time_out--) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001531 boot_loader_write_mem32(pao, 0,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001532 host_mailbox_address_on_dsp,
1533 physicalPC_iaddress);
1534 physicalPC_iaddress_verify =
1535 boot_loader_read_mem32(pao, 0,
1536 host_mailbox_address_on_dsp);
1537 }
1538 }
1539 HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");
1540 /* enable interrupts */
1541 temp = ioread32(phw->prHSR);
1542 temp &= ~(u32)C6205_HSR_INTAM;
1543 iowrite32(temp, phw->prHSR);
1544
1545 /* start code running... */
1546 temp = ioread32(phw->prHDCR);
1547 temp |= (u32)C6205_HDCR_DSPINT;
1548 iowrite32(temp, phw->prHDCR);
1549
1550 /* give the DSP 10ms to start up */
1551 hpios_delay_micro_seconds(10000);
1552 return err;
1553
1554}
1555
1556/*****************************************************************************/
1557/* Bootloader utility functions */
1558
1559static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1560 u32 address)
1561{
1562 struct hpi_hw_obj *phw = pao->priv;
1563 u32 data = 0;
1564 __iomem u32 *p_data;
1565
1566 if (dsp_index == 0) {
1567 /* DSP 0 is always C6205 */
1568 if ((address >= 0x01800000) & (address < 0x02000000)) {
1569 /* BAR1 register access */
1570 p_data = pao->pci.ap_mem_base[1] +
1571 (address & 0x007fffff) /
1572 sizeof(*pao->pci.ap_mem_base[1]);
1573 /* HPI_DEBUG_LOG(WARNING,
1574 "BAR1 access %08x\n", dwAddress); */
1575 } else {
1576 u32 dw4M_page = address >> 22L;
1577 if (dw4M_page != phw->dsp_page) {
1578 phw->dsp_page = dw4M_page;
1579 /* *INDENT OFF* */
1580 iowrite32(phw->dsp_page, phw->prDSPP);
1581 /* *INDENT-ON* */
1582 }
1583 address &= 0x3fffff; /* address within 4M page */
1584 /* BAR0 memory access */
1585 p_data = pao->pci.ap_mem_base[0] +
1586 address / sizeof(u32);
1587 }
1588 data = ioread32(p_data);
1589 } else if (dsp_index == 1) {
1590 /* DSP 1 is a C6713 */
1591 u32 lsb;
1592 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1593 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1594 lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);
1595 data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);
1596 data = (data << 16) | (lsb & 0xFFFF);
1597 }
1598 return data;
1599}
1600
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001601static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
1602 int dsp_index, u32 address, u32 data)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001603{
1604 struct hpi_hw_obj *phw = pao->priv;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001605 __iomem u32 *p_data;
1606 /* u32 dwVerifyData=0; */
1607
1608 if (dsp_index == 0) {
1609 /* DSP 0 is always C6205 */
1610 if ((address >= 0x01800000) & (address < 0x02000000)) {
1611 /* BAR1 - DSP register access using */
1612 /* Non-prefetchable PCI access */
1613 p_data = pao->pci.ap_mem_base[1] +
1614 (address & 0x007fffff) /
1615 sizeof(*pao->pci.ap_mem_base[1]);
1616 } else {
1617 /* BAR0 access - all of DSP memory using */
1618 /* pre-fetchable PCI access */
1619 u32 dw4M_page = address >> 22L;
1620 if (dw4M_page != phw->dsp_page) {
1621 phw->dsp_page = dw4M_page;
1622 /* *INDENT-OFF* */
1623 iowrite32(phw->dsp_page, phw->prDSPP);
1624 /* *INDENT-ON* */
1625 }
1626 address &= 0x3fffff; /* address within 4M page */
1627 p_data = pao->pci.ap_mem_base[0] +
1628 address / sizeof(u32);
1629 }
1630 iowrite32(data, p_data);
1631 } else if (dsp_index == 1) {
1632 /* DSP 1 is a C6713 */
1633 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1634 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1635
1636 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1637 boot_loader_read_mem32(pao, 0, 0);
1638
1639 boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);
1640 boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);
1641
1642 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1643 boot_loader_read_mem32(pao, 0, 0);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001644 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001645}
1646
1647static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
1648{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001649 if (dsp_index == 0) {
1650 u32 setting;
1651
1652 /* DSP 0 is always C6205 */
1653
1654 /* Set the EMIF */
1655 /* memory map of C6205 */
1656 /* 00000000-0000FFFF 16Kx32 internal program */
1657 /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */
1658
1659 /* EMIF config */
1660 /*------------ */
1661 /* Global EMIF control */
1662 boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);
1663#define WS_OFS 28
1664#define WST_OFS 22
1665#define WH_OFS 20
1666#define RS_OFS 16
1667#define RST_OFS 8
1668#define MTYPE_OFS 4
1669#define RH_OFS 0
1670
1671 /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */
1672 setting = 0x00000030;
1673 boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
1674 if (setting != boot_loader_read_mem32(pao, dsp_index,
1675 0x01800008))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001676 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001677
1678 /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
1679 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1680 /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */
1681 /* WST should be 71, but 63 is max possible */
1682 setting =
1683 (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |
1684 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1685 (2L << MTYPE_OFS);
1686 boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
1687 if (setting != boot_loader_read_mem32(pao, dsp_index,
1688 0x01800004))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001689 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001690
1691 /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
1692 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1693 /* plenty of wait states */
1694 setting =
1695 (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |
1696 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1697 (2L << MTYPE_OFS);
1698 boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
1699 if (setting != boot_loader_read_mem32(pao, dsp_index,
1700 0x01800010))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001701 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001702
1703 /* EMIF CE3 setup - 32 bit async. */
1704 /* This is the PLD on the ASI5000 cards only */
1705 setting =
1706 (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |
1707 (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |
1708 (2L << MTYPE_OFS);
1709 boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
1710 if (setting != boot_loader_read_mem32(pao, dsp_index,
1711 0x01800014))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001712 return HPI6205_ERROR_DSP_EMIF;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001713
1714 /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
1715 /* need to use this else DSP code crashes? */
1716 boot_loader_write_mem32(pao, dsp_index, 0x01800018,
1717 0x07117000);
1718
1719 /* EMIF SDRAM Refresh Timing */
1720 /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */
1721 boot_loader_write_mem32(pao, dsp_index, 0x0180001C,
1722 0x00000410);
1723
1724 } else if (dsp_index == 1) {
1725 /* test access to the C6713s HPI registers */
1726 u32 write_data = 0, read_data = 0, i = 0;
1727
1728 /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */
1729 write_data = 1;
1730 boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);
1731 boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);
1732 /* C67 HPI is on lower 16bits of 32bit EMIF */
1733 read_data =
1734 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
1735 if (write_data != read_data) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001736 HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
1737 read_data);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001738 return HPI6205_ERROR_C6713_HPIC;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001739 }
1740 /* HPIA - walking ones test */
1741 write_data = 1;
1742 for (i = 0; i < 32; i++) {
1743 boot_loader_write_mem32(pao, 0, HPIAL_ADDR,
1744 write_data);
1745 boot_loader_write_mem32(pao, 0, HPIAH_ADDR,
1746 (write_data >> 16));
1747 read_data =
1748 0xFFFF & boot_loader_read_mem32(pao, 0,
1749 HPIAL_ADDR);
1750 read_data =
1751 read_data | ((0xFFFF &
1752 boot_loader_read_mem32(pao, 0,
1753 HPIAH_ADDR))
1754 << 16);
1755 if (read_data != write_data) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001756 HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
1757 write_data, read_data);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001758 return HPI6205_ERROR_C6713_HPIA;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001759 }
1760 write_data = write_data << 1;
1761 }
1762
1763 /* setup C67x PLL
1764 * ** C6713 datasheet says we cannot program PLL from HPI,
1765 * and indeed if we try to set the PLL multiply from the HPI,
1766 * the PLL does not seem to lock, so we enable the PLL and
1767 * use the default multiply of x 7, which for a 27MHz clock
1768 * gives a DSP speed of 189MHz
1769 */
1770 /* bypass PLL */
1771 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);
1772 hpios_delay_micro_seconds(1000);
1773 /* EMIF = 189/3=63MHz */
1774 boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);
1775 /* peri = 189/2 */
1776 boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);
1777 /* cpu = 189/1 */
1778 boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);
1779 hpios_delay_micro_seconds(1000);
1780 /* ** SGT test to take GPO3 high when we start the PLL */
1781 /* and low when the delay is completed */
1782 /* FSX0 <- '1' (GPO3) */
1783 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);
1784 /* PLL not bypassed */
1785 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);
1786 hpios_delay_micro_seconds(1000);
1787 /* FSX0 <- '0' (GPO3) */
1788 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);
1789
1790 /* 6205 EMIF CE1 resetup - 32 bit async. */
1791 /* Now 6713 #1 is running at 189MHz can reduce waitstates */
1792 boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */
1793 (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |
1794 (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |
1795 (2L << MTYPE_OFS));
1796
1797 hpios_delay_micro_seconds(1000);
1798
1799 /* check that we can read one of the PLL registers */
1800 /* PLL should not be bypassed! */
1801 if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
1802 != 0x0001) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001803 return HPI6205_ERROR_C6713_PLL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001804 }
1805 /* setup C67x EMIF (note this is the only use of
1806 BAR1 via BootLoader_WriteMem32) */
1807 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
1808 0x000034A8);
1809 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
1810 0x00000030);
1811 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
1812 0x001BDF29);
1813 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
1814 0x47117000);
1815 boot_loader_write_mem32(pao, dsp_index,
1816 C6713_EMIF_SDRAMTIMING, 0x00000410);
1817
1818 hpios_delay_micro_seconds(1000);
1819 } else if (dsp_index == 2) {
1820 /* DSP 2 is a C6713 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001821 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001822
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001823 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001824}
1825
1826static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
1827 u32 start_address, u32 length)
1828{
1829 u32 i = 0, j = 0;
1830 u32 test_addr = 0;
1831 u32 test_data = 0, data = 0;
1832
1833 length = 1000;
1834
1835 /* for 1st word, test each bit in the 32bit word, */
1836 /* dwLength specifies number of 32bit words to test */
1837 /*for(i=0; i<dwLength; i++) */
1838 i = 0;
1839 {
1840 test_addr = start_address + i * 4;
1841 test_data = 0x00000001;
1842 for (j = 0; j < 32; j++) {
1843 boot_loader_write_mem32(pao, dsp_index, test_addr,
1844 test_data);
1845 data = boot_loader_read_mem32(pao, dsp_index,
1846 test_addr);
1847 if (data != test_data) {
1848 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001849 "Memtest error details "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001850 "%08x %08x %08x %i\n", test_addr,
1851 test_data, data, dsp_index);
1852 return 1; /* error */
1853 }
1854 test_data = test_data << 1;
1855 } /* for(j) */
1856 } /* for(i) */
1857
1858 /* for the next 100 locations test each location, leaving it as zero */
1859 /* write a zero to the next word in memory before we read */
1860 /* the previous write to make sure every memory location is unique */
1861 for (i = 0; i < 100; i++) {
1862 test_addr = start_address + i * 4;
1863 test_data = 0xA5A55A5A;
1864 boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);
1865 boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);
1866 data = boot_loader_read_mem32(pao, dsp_index, test_addr);
1867 if (data != test_data) {
1868 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001869 "Memtest error details "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001870 "%08x %08x %08x %i\n", test_addr, test_data,
1871 data, dsp_index);
1872 return 1; /* error */
1873 }
1874 /* leave location as zero */
1875 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1876 }
1877
1878 /* zero out entire memory block */
1879 for (i = 0; i < length; i++) {
1880 test_addr = start_address + i * 4;
1881 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1882 }
1883 return 0;
1884}
1885
1886static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
1887 int dsp_index)
1888{
1889 int err = 0;
1890 if (dsp_index == 0) {
1891 /* DSP 0 is a C6205 */
1892 /* 64K prog mem */
1893 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1894 0x10000);
1895 if (!err)
1896 /* 64K data mem */
1897 err = boot_loader_test_memory(pao, dsp_index,
1898 0x80000000, 0x10000);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001899 } else if (dsp_index == 1) {
1900 /* DSP 1 is a C6713 */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001901 /* 192K internal mem */
1902 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1903 0x30000);
1904 if (!err)
1905 /* 64K internal mem / L2 cache */
1906 err = boot_loader_test_memory(pao, dsp_index,
1907 0x00030000, 0x10000);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001908 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001909
1910 if (err)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001911 return HPI6205_ERROR_DSP_INTMEM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001912 else
1913 return 0;
1914}
1915
1916static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
1917 int dsp_index)
1918{
1919 u32 dRAM_start_address = 0;
1920 u32 dRAM_size = 0;
1921
1922 if (dsp_index == 0) {
1923 /* only test for SDRAM if an ASI5000 card */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001924 if (pao->pci.pci_dev->subsystem_device == 0x5000) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001925 /* DSP 0 is always C6205 */
1926 dRAM_start_address = 0x00400000;
1927 dRAM_size = 0x200000;
1928 /*dwDRAMinc=1024; */
1929 } else
1930 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001931 } else if (dsp_index == 1) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001932 /* DSP 1 is a C6713 */
1933 dRAM_start_address = 0x80000000;
1934 dRAM_size = 0x200000;
1935 /*dwDRAMinc=1024; */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001936 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001937
1938 if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
1939 dRAM_size))
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001940 return HPI6205_ERROR_DSP_EXTMEM;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001941 return 0;
1942}
1943
1944static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
1945{
1946 u32 data = 0;
1947 if (dsp_index == 0) {
1948 /* only test for DSP0 PLD on ASI5000 card */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001949 if (pao->pci.pci_dev->subsystem_device == 0x5000) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001950 /* PLD is located at CE3=0x03000000 */
1951 data = boot_loader_read_mem32(pao, dsp_index,
1952 0x03000008);
1953 if ((data & 0xF) != 0x5)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001954 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001955 data = boot_loader_read_mem32(pao, dsp_index,
1956 0x0300000C);
1957 if ((data & 0xF) != 0xA)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001958 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001959 }
1960 } else if (dsp_index == 1) {
1961 /* DSP 1 is a C6713 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001962 if (pao->pci.pci_dev->subsystem_device == 0x8700) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001963 /* PLD is located at CE1=0x90000000 */
1964 data = boot_loader_read_mem32(pao, dsp_index,
1965 0x90000010);
1966 if ((data & 0xFF) != 0xAA)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13001967 return HPI6205_ERROR_DSP_PLD;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001968 /* 8713 - LED on */
1969 boot_loader_write_mem32(pao, dsp_index, 0x90000000,
1970 0x02);
1971 }
1972 }
1973 return 0;
1974}
1975
1976/** Transfer data to or from DSP
1977 nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA
1978*/
1979static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
1980 u32 data_size, int operation)
1981{
1982 struct hpi_hw_obj *phw = pao->priv;
1983 u32 data_transferred = 0;
1984 u16 err = 0;
1985#ifndef HPI6205_NO_HSR_POLL
1986 u32 time_out;
1987#endif
1988 u32 temp2;
1989 struct bus_master_interface *interface = phw->p_interface_buffer;
1990
1991 if (!p_data)
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +13001992 return HPI_ERROR_INVALID_DATA_POINTER;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001993
1994 data_size &= ~3L; /* round data_size down to nearest 4 bytes */
1995
1996 /* make sure state is IDLE */
1997 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))
1998 return HPI_ERROR_DSP_HARDWARE;
1999
2000 while (data_transferred < data_size) {
2001 u32 this_copy = data_size - data_transferred;
2002
2003 if (this_copy > HPI6205_SIZEOF_DATA)
2004 this_copy = HPI6205_SIZEOF_DATA;
2005
2006 if (operation == H620_HIF_SEND_DATA)
2007 memcpy((void *)&interface->u.b_data[0],
2008 &p_data[data_transferred], this_copy);
2009
2010 interface->transfer_size_in_bytes = this_copy;
2011
2012#ifdef HPI6205_NO_HSR_POLL
2013 /* DSP must change this back to nOperation */
2014 interface->dsp_ack = H620_HIF_IDLE;
2015#endif
2016
2017 send_dsp_command(phw, operation);
2018
2019#ifdef HPI6205_NO_HSR_POLL
2020 temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
2021 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2022 HPI6205_TIMEOUT - temp2, this_copy);
2023
2024 if (!temp2) {
2025 /* timed out */
2026 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002027 "Timed out waiting for " "state %d got %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002028 operation, interface->dsp_ack);
2029
2030 break;
2031 }
2032#else
2033 /* spin waiting on the result */
2034 time_out = HPI6205_TIMEOUT;
2035 temp2 = 0;
2036 while ((temp2 == 0) && time_out--) {
2037 /* give 16k bus mastering transfer time to happen */
2038 /*(16k / 132Mbytes/s = 122usec) */
2039 hpios_delay_micro_seconds(20);
2040 temp2 = ioread32(phw->prHSR);
2041 temp2 &= C6205_HSR_INTSRC;
2042 }
2043 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2044 HPI6205_TIMEOUT - time_out, this_copy);
2045 if (temp2 == C6205_HSR_INTSRC) {
2046 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002047 "Interrupt from HIF <data> OK\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002048 /*
2049 if(interface->dwDspAck != nOperation) {
2050 HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d,
2051 expected %d \n",
2052 interface->dwDspAck,nOperation);
2053 }
2054 */
2055 }
2056/* need to handle this differently... */
2057 else {
2058 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002059 "Interrupt from HIF <data> BAD\n");
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002060 err = HPI_ERROR_DSP_HARDWARE;
2061 }
2062
2063 /* reset the interrupt from the DSP */
2064 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2065#endif
2066 if (operation == H620_HIF_GET_DATA)
2067 memcpy(&p_data[data_transferred],
2068 (void *)&interface->u.b_data[0], this_copy);
2069
2070 data_transferred += this_copy;
2071 }
2072 if (interface->dsp_ack != operation)
2073 HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",
2074 interface->dsp_ack, operation);
2075 /* err=HPI_ERROR_DSP_HARDWARE; */
2076
2077 send_dsp_command(phw, H620_HIF_IDLE);
2078
2079 return err;
2080}
2081
2082/* wait for up to timeout_us microseconds for the DSP
2083 to signal state by DMA into dwDspAck
2084*/
2085static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
2086{
2087 struct bus_master_interface *interface = phw->p_interface_buffer;
2088 int t = timeout_us / 4;
2089
2090 rmb(); /* ensure interface->dsp_ack is up to date */
2091 while ((interface->dsp_ack != state) && --t) {
2092 hpios_delay_micro_seconds(4);
2093 rmb(); /* DSP changes dsp_ack by DMA */
2094 }
2095
2096 /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */
2097 return t * 4;
2098}
2099
2100/* set the busmaster interface to cmd, then interrupt the DSP */
2101static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
2102{
2103 struct bus_master_interface *interface = phw->p_interface_buffer;
2104
2105 u32 r;
2106
2107 interface->host_cmd = cmd;
2108 wmb(); /* DSP gets state by DMA, make sure it is written to memory */
2109 /* before we interrupt the DSP */
2110 r = ioread32(phw->prHDCR);
2111 r |= (u32)C6205_HDCR_DSPINT;
2112 iowrite32(r, phw->prHDCR);
2113 r &= ~(u32)C6205_HDCR_DSPINT;
2114 iowrite32(r, phw->prHDCR);
2115}
2116
2117static unsigned int message_count;
2118
2119static u16 message_response_sequence(struct hpi_adapter_obj *pao,
2120 struct hpi_message *phm, struct hpi_response *phr)
2121{
2122#ifndef HPI6205_NO_HSR_POLL
2123 u32 temp2;
2124#endif
2125 u32 time_out, time_out2;
2126 struct hpi_hw_obj *phw = pao->priv;
2127 struct bus_master_interface *interface = phw->p_interface_buffer;
2128 u16 err = 0;
2129
2130 message_count++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002131 if (phm->size > sizeof(interface->u)) {
Eliot Blennerhassettdeb21a22011-02-10 17:26:03 +13002132 phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002133 phr->specific_error = sizeof(interface->u);
2134 phr->size = sizeof(struct hpi_response_header);
2135 HPI_DEBUG_LOG(ERROR,
2136 "message len %d too big for buffer %ld \n", phm->size,
2137 sizeof(interface->u));
2138 return 0;
2139 }
2140
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002141 /* Assume buffer of type struct bus_master_interface
2142 is allocated "noncacheable" */
2143
2144 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2145 HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002146 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002147 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002148
2149 memcpy(&interface->u.message_buffer, phm, phm->size);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002150 /* signal we want a response */
2151 send_dsp_command(phw, H620_HIF_GET_RESP);
2152
2153 time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
2154
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002155 if (!time_out2) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002156 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002157 "(%u) Timed out waiting for " "GET_RESP state [%x]\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002158 message_count, interface->dsp_ack);
2159 } else {
2160 HPI_DEBUG_LOG(VERBOSE,
2161 "(%u) transition to GET_RESP after %u\n",
2162 message_count, HPI6205_TIMEOUT - time_out2);
2163 }
2164 /* spin waiting on HIF interrupt flag (end of msg process) */
2165 time_out = HPI6205_TIMEOUT;
2166
2167#ifndef HPI6205_NO_HSR_POLL
2168 temp2 = 0;
2169 while ((temp2 == 0) && --time_out) {
2170 temp2 = ioread32(phw->prHSR);
2171 temp2 &= C6205_HSR_INTSRC;
2172 hpios_delay_micro_seconds(1);
2173 }
2174 if (temp2 == C6205_HSR_INTSRC) {
2175 rmb(); /* ensure we see latest value for dsp_ack */
2176 if ((interface->dsp_ack != H620_HIF_GET_RESP)) {
2177 HPI_DEBUG_LOG(DEBUG,
2178 "(%u)interface->dsp_ack(0x%x) != "
2179 "H620_HIF_GET_RESP, t=%u\n", message_count,
2180 interface->dsp_ack,
2181 HPI6205_TIMEOUT - time_out);
2182 } else {
2183 HPI_DEBUG_LOG(VERBOSE,
2184 "(%u)int with GET_RESP after %u\n",
2185 message_count, HPI6205_TIMEOUT - time_out);
2186 }
2187
2188 } else {
2189 /* can we do anything else in response to the error ? */
2190 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002191 "Interrupt from HIF module BAD (function %x)\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002192 phm->function);
2193 }
2194
2195 /* reset the interrupt from the DSP */
2196 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2197#endif
2198
2199 /* read the result */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002200 if (time_out) {
2201 if (interface->u.response_buffer.size <= phr->size)
2202 memcpy(phr, &interface->u.response_buffer,
2203 interface->u.response_buffer.size);
2204 else {
2205 HPI_DEBUG_LOG(ERROR,
2206 "response len %d too big for buffer %d\n",
2207 interface->u.response_buffer.size, phr->size);
2208 memcpy(phr, &interface->u.response_buffer,
2209 sizeof(struct hpi_response_header));
2210 phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
2211 phr->specific_error =
2212 interface->u.response_buffer.size;
2213 phr->size = sizeof(struct hpi_response_header);
2214 }
2215 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002216 /* set interface back to idle */
2217 send_dsp_command(phw, H620_HIF_IDLE);
2218
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002219 if (!time_out || !time_out2) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002220 HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002221 return HPI6205_ERROR_MSG_RESP_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002222 }
2223 /* special case for adapter close - */
2224 /* wait for the DSP to indicate it is idle */
2225 if (phm->function == HPI_ADAPTER_CLOSE) {
2226 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2227 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002228 "Timeout waiting for idle "
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002229 "(on adapter_close)\n");
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +13002230 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002231 }
2232 }
2233 err = hpi_validate_response(phm, phr);
2234 return err;
2235}
2236
2237static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
2238 struct hpi_response *phr)
2239{
2240
2241 u16 err = 0;
2242
2243 hpios_dsplock_lock(pao);
2244
2245 err = message_response_sequence(pao, phm, phr);
2246
2247 /* maybe an error response */
2248 if (err) {
2249 /* something failed in the HPI/DSP interface */
Eliot Blennerhassett0a000442011-02-10 17:26:05 +13002250 if (err >= HPI_ERROR_BACKEND_BASE) {
2251 phr->error = HPI_ERROR_DSP_COMMUNICATION;
2252 phr->specific_error = err;
2253 } else {
2254 phr->error = err;
2255 }
2256
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02002257 pao->dsp_crashed++;
2258
2259 /* just the header of the response is valid */
2260 phr->size = sizeof(struct hpi_response_header);
2261 goto err;
2262 } else
2263 pao->dsp_crashed = 0;
2264
2265 if (phr->error != 0) /* something failed in the DSP */
2266 goto err;
2267
2268 switch (phm->function) {
2269 case HPI_OSTREAM_WRITE:
2270 case HPI_ISTREAM_ANC_WRITE:
2271 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2272 phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);
2273 break;
2274
2275 case HPI_ISTREAM_READ:
2276 case HPI_OSTREAM_ANC_READ:
2277 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2278 phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
2279 break;
2280
2281 case HPI_CONTROL_SET_STATE:
2282 if (phm->object == HPI_OBJ_CONTROLEX
2283 && phm->u.cx.attribute == HPI_COBRANET_SET_DATA)
2284 err = hpi6205_transfer_data(pao,
2285 phm->u.cx.u.cobranet_bigdata.pb_data,
2286 phm->u.cx.u.cobranet_bigdata.byte_count,
2287 H620_HIF_SEND_DATA);
2288 break;
2289
2290 case HPI_CONTROL_GET_STATE:
2291 if (phm->object == HPI_OBJ_CONTROLEX
2292 && phm->u.cx.attribute == HPI_COBRANET_GET_DATA)
2293 err = hpi6205_transfer_data(pao,
2294 phm->u.cx.u.cobranet_bigdata.pb_data,
2295 phr->u.cx.u.cobranet_data.byte_count,
2296 H620_HIF_GET_DATA);
2297 break;
2298 }
2299 phr->error = err;
2300
2301err:
2302 hpios_dsplock_unlock(pao);
2303
2304 return;
2305}