diff options
Diffstat (limited to 'sound/pci/asihpi/hpi6000.c')
-rw-r--r-- | sound/pci/asihpi/hpi6000.c | 299 |
1 files changed, 137 insertions, 162 deletions
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 1b9bf9395cfe..3e3c2ef6efd8 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c | |||
@@ -43,16 +43,17 @@ | |||
43 | #define HPI_HIF_ERROR_MASK 0x4000 | 43 | #define HPI_HIF_ERROR_MASK 0x4000 |
44 | 44 | ||
45 | /* HPI6000 specific error codes */ | 45 | /* HPI6000 specific error codes */ |
46 | #define HPI6000_ERROR_BASE 900 /* not actually used anywhere */ | ||
46 | 47 | ||
47 | #define HPI6000_ERROR_BASE 900 | 48 | /* operational/messaging errors */ |
48 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 | 49 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 |
49 | #define HPI6000_ERROR_MSG_RESP_SEND_MSG_ACK 902 | 50 | |
50 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 | 51 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 |
51 | #define HPI6000_ERROR_MSG_GET_ADR 904 | 52 | #define HPI6000_ERROR_MSG_GET_ADR 904 |
52 | #define HPI6000_ERROR_RESP_GET_ADR 905 | 53 | #define HPI6000_ERROR_RESP_GET_ADR 905 |
53 | #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 | 54 | #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 |
54 | #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 | 55 | #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 |
55 | #define HPI6000_ERROR_MSG_INVALID_DSP_INDEX 908 | 56 | |
56 | #define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 | 57 | #define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 |
57 | 58 | ||
58 | #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 | 59 | #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 |
@@ -62,7 +63,6 @@ | |||
62 | #define HPI6000_ERROR_SEND_DATA_CMD 915 | 63 | #define HPI6000_ERROR_SEND_DATA_CMD 915 |
63 | #define HPI6000_ERROR_SEND_DATA_WRITE 916 | 64 | #define HPI6000_ERROR_SEND_DATA_WRITE 916 |
64 | #define HPI6000_ERROR_SEND_DATA_IDLECMD 917 | 65 | #define HPI6000_ERROR_SEND_DATA_IDLECMD 917 |
65 | #define HPI6000_ERROR_SEND_DATA_VERIFY 918 | ||
66 | 66 | ||
67 | #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 | 67 | #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 |
68 | #define HPI6000_ERROR_GET_DATA_ACK 922 | 68 | #define HPI6000_ERROR_GET_DATA_ACK 922 |
@@ -76,9 +76,8 @@ | |||
76 | 76 | ||
77 | #define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 | 77 | #define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 |
78 | #define HPI6000_ERROR_MSG_RESP_IDLECMD 962 | 78 | #define HPI6000_ERROR_MSG_RESP_IDLECMD 962 |
79 | #define HPI6000_ERROR_MSG_RESP_BLOCKVERIFY32 963 | ||
80 | 79 | ||
81 | /* adapter init errors */ | 80 | /* Initialisation/bootload errors */ |
82 | #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 | 81 | #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 |
83 | 82 | ||
84 | /* can't access PCI2040 */ | 83 | /* can't access PCI2040 */ |
@@ -210,6 +209,8 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao, | |||
210 | static short create_adapter_obj(struct hpi_adapter_obj *pao, | 209 | static short create_adapter_obj(struct hpi_adapter_obj *pao, |
211 | u32 *pos_error_code); | 210 | u32 *pos_error_code); |
212 | 211 | ||
212 | static void delete_adapter_obj(struct hpi_adapter_obj *pao); | ||
213 | |||
213 | /* local globals */ | 214 | /* local globals */ |
214 | 215 | ||
215 | static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ | 216 | static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ |
@@ -217,17 +218,7 @@ static u16 gw_pci_write_asserts; /* used to count PCI2040 errors */ | |||
217 | 218 | ||
218 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 219 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) |
219 | { | 220 | { |
220 | |||
221 | switch (phm->function) { | 221 | switch (phm->function) { |
222 | case HPI_SUBSYS_OPEN: | ||
223 | case HPI_SUBSYS_CLOSE: | ||
224 | case HPI_SUBSYS_GET_INFO: | ||
225 | case HPI_SUBSYS_DRIVER_UNLOAD: | ||
226 | case HPI_SUBSYS_DRIVER_LOAD: | ||
227 | case HPI_SUBSYS_FIND_ADAPTERS: | ||
228 | /* messages that should not get here */ | ||
229 | phr->error = HPI_ERROR_UNIMPLEMENTED; | ||
230 | break; | ||
231 | case HPI_SUBSYS_CREATE_ADAPTER: | 222 | case HPI_SUBSYS_CREATE_ADAPTER: |
232 | subsys_create_adapter(phm, phr); | 223 | subsys_create_adapter(phm, phr); |
233 | break; | 224 | break; |
@@ -243,7 +234,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | |||
243 | static void control_message(struct hpi_adapter_obj *pao, | 234 | static void control_message(struct hpi_adapter_obj *pao, |
244 | struct hpi_message *phm, struct hpi_response *phr) | 235 | struct hpi_message *phm, struct hpi_response *phr) |
245 | { | 236 | { |
246 | |||
247 | switch (phm->function) { | 237 | switch (phm->function) { |
248 | case HPI_CONTROL_GET_STATE: | 238 | case HPI_CONTROL_GET_STATE: |
249 | if (pao->has_control_cache) { | 239 | if (pao->has_control_cache) { |
@@ -251,7 +241,13 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
251 | err = hpi6000_update_control_cache(pao, phm); | 241 | err = hpi6000_update_control_cache(pao, phm); |
252 | 242 | ||
253 | if (err) { | 243 | if (err) { |
254 | phr->error = err; | 244 | if (err >= HPI_ERROR_BACKEND_BASE) { |
245 | phr->error = | ||
246 | HPI_ERROR_CONTROL_CACHING; | ||
247 | phr->specific_error = err; | ||
248 | } else { | ||
249 | phr->error = err; | ||
250 | } | ||
255 | break; | 251 | break; |
256 | } | 252 | } |
257 | 253 | ||
@@ -262,16 +258,15 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
262 | } | 258 | } |
263 | hw_message(pao, phm, phr); | 259 | hw_message(pao, phm, phr); |
264 | break; | 260 | break; |
265 | case HPI_CONTROL_GET_INFO: | ||
266 | hw_message(pao, phm, phr); | ||
267 | break; | ||
268 | case HPI_CONTROL_SET_STATE: | 261 | case HPI_CONTROL_SET_STATE: |
269 | hw_message(pao, phm, phr); | 262 | hw_message(pao, phm, phr); |
270 | hpi_sync_control_cache(((struct hpi_hw_obj *)pao->priv)-> | 263 | hpi_cmn_control_cache_sync_to_msg(((struct hpi_hw_obj *)pao-> |
271 | p_cache, phm, phr); | 264 | priv)->p_cache, phm, phr); |
272 | break; | 265 | break; |
266 | |||
267 | case HPI_CONTROL_GET_INFO: | ||
273 | default: | 268 | default: |
274 | phr->error = HPI_ERROR_INVALID_FUNC; | 269 | hw_message(pao, phm, phr); |
275 | break; | 270 | break; |
276 | } | 271 | } |
277 | } | 272 | } |
@@ -280,26 +275,12 @@ static void adapter_message(struct hpi_adapter_obj *pao, | |||
280 | struct hpi_message *phm, struct hpi_response *phr) | 275 | struct hpi_message *phm, struct hpi_response *phr) |
281 | { | 276 | { |
282 | switch (phm->function) { | 277 | switch (phm->function) { |
283 | case HPI_ADAPTER_GET_INFO: | ||
284 | hw_message(pao, phm, phr); | ||
285 | break; | ||
286 | case HPI_ADAPTER_GET_ASSERT: | 278 | case HPI_ADAPTER_GET_ASSERT: |
287 | adapter_get_asserts(pao, phm, phr); | 279 | adapter_get_asserts(pao, phm, phr); |
288 | break; | 280 | break; |
289 | case HPI_ADAPTER_OPEN: | 281 | |
290 | case HPI_ADAPTER_CLOSE: | ||
291 | case HPI_ADAPTER_TEST_ASSERT: | ||
292 | case HPI_ADAPTER_SELFTEST: | ||
293 | case HPI_ADAPTER_GET_MODE: | ||
294 | case HPI_ADAPTER_SET_MODE: | ||
295 | case HPI_ADAPTER_FIND_OBJECT: | ||
296 | case HPI_ADAPTER_GET_PROPERTY: | ||
297 | case HPI_ADAPTER_SET_PROPERTY: | ||
298 | case HPI_ADAPTER_ENUM_PROPERTY: | ||
299 | hw_message(pao, phm, phr); | ||
300 | break; | ||
301 | default: | 282 | default: |
302 | phr->error = HPI_ERROR_INVALID_FUNC; | 283 | hw_message(pao, phm, phr); |
303 | break; | 284 | break; |
304 | } | 285 | } |
305 | } | 286 | } |
@@ -311,7 +292,7 @@ static void outstream_message(struct hpi_adapter_obj *pao, | |||
311 | case HPI_OSTREAM_HOSTBUFFER_ALLOC: | 292 | case HPI_OSTREAM_HOSTBUFFER_ALLOC: |
312 | case HPI_OSTREAM_HOSTBUFFER_FREE: | 293 | case HPI_OSTREAM_HOSTBUFFER_FREE: |
313 | /* Don't let these messages go to the HW function because | 294 | /* Don't let these messages go to the HW function because |
314 | * they're called without allocating the spinlock. | 295 | * they're called without locking the spinlock. |
315 | * For the HPI6000 adapters the HW would return | 296 | * For the HPI6000 adapters the HW would return |
316 | * HPI_ERROR_INVALID_FUNC anyway. | 297 | * HPI_ERROR_INVALID_FUNC anyway. |
317 | */ | 298 | */ |
@@ -331,7 +312,7 @@ static void instream_message(struct hpi_adapter_obj *pao, | |||
331 | case HPI_ISTREAM_HOSTBUFFER_ALLOC: | 312 | case HPI_ISTREAM_HOSTBUFFER_ALLOC: |
332 | case HPI_ISTREAM_HOSTBUFFER_FREE: | 313 | case HPI_ISTREAM_HOSTBUFFER_FREE: |
333 | /* Don't let these messages go to the HW function because | 314 | /* Don't let these messages go to the HW function because |
334 | * they're called without allocating the spinlock. | 315 | * they're called without locking the spinlock. |
335 | * For the HPI6000 adapters the HW would return | 316 | * For the HPI6000 adapters the HW would return |
336 | * HPI_ERROR_INVALID_FUNC anyway. | 317 | * HPI_ERROR_INVALID_FUNC anyway. |
337 | */ | 318 | */ |
@@ -355,7 +336,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) | |||
355 | /* subsytem messages get executed by every HPI. */ | 336 | /* subsytem messages get executed by every HPI. */ |
356 | /* All other messages are ignored unless the adapter index matches */ | 337 | /* All other messages are ignored unless the adapter index matches */ |
357 | /* an adapter in the HPI */ | 338 | /* an adapter in the HPI */ |
358 | HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->object, phm->function); | 339 | /*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */ |
359 | 340 | ||
360 | /* if Dsp has crashed then do not communicate with it any more */ | 341 | /* if Dsp has crashed then do not communicate with it any more */ |
361 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | 342 | if (phm->object != HPI_OBJ_SUBSYSTEM) { |
@@ -433,21 +414,13 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
433 | struct hpi_adapter_obj ao; | 414 | struct hpi_adapter_obj ao; |
434 | struct hpi_adapter_obj *pao; | 415 | struct hpi_adapter_obj *pao; |
435 | u32 os_error_code; | 416 | u32 os_error_code; |
436 | short error = 0; | 417 | u16 err = 0; |
437 | u32 dsp_index = 0; | 418 | u32 dsp_index = 0; |
438 | 419 | ||
439 | HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); | 420 | HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); |
440 | 421 | ||
441 | memset(&ao, 0, sizeof(ao)); | 422 | memset(&ao, 0, sizeof(ao)); |
442 | 423 | ||
443 | /* this HPI only creates adapters for TI/PCI2040 based devices */ | ||
444 | if (phm->u.s.resource.bus_type != HPI_BUS_PCI) | ||
445 | return; | ||
446 | if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI) | ||
447 | return; | ||
448 | if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040) | ||
449 | return; | ||
450 | |||
451 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); | 424 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); |
452 | if (!ao.priv) { | 425 | if (!ao.priv) { |
453 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); | 426 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); |
@@ -456,16 +429,19 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
456 | } | 429 | } |
457 | 430 | ||
458 | /* create the adapter object based on the resource information */ | 431 | /* create the adapter object based on the resource information */ |
459 | /*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */ | ||
460 | ao.pci = *phm->u.s.resource.r.pci; | 432 | ao.pci = *phm->u.s.resource.r.pci; |
461 | 433 | ||
462 | error = create_adapter_obj(&ao, &os_error_code); | 434 | err = create_adapter_obj(&ao, &os_error_code); |
463 | if (!error) | 435 | if (err) { |
464 | error = hpi_add_adapter(&ao); | 436 | delete_adapter_obj(&ao); |
465 | if (error) { | 437 | if (err >= HPI_ERROR_BACKEND_BASE) { |
438 | phr->error = HPI_ERROR_DSP_BOOTLOAD; | ||
439 | phr->specific_error = err; | ||
440 | } else { | ||
441 | phr->error = err; | ||
442 | } | ||
443 | |||
466 | phr->u.s.data = os_error_code; | 444 | phr->u.s.data = os_error_code; |
467 | kfree(ao.priv); | ||
468 | phr->error = error; | ||
469 | return; | 445 | return; |
470 | } | 446 | } |
471 | /* need to update paParentAdapter */ | 447 | /* need to update paParentAdapter */ |
@@ -473,7 +449,7 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
473 | if (!pao) { | 449 | if (!pao) { |
474 | /* We just added this adapter, why can't we find it!? */ | 450 | /* We just added this adapter, why can't we find it!? */ |
475 | HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); | 451 | HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); |
476 | phr->error = 950; | 452 | phr->error = HPI_ERROR_BAD_ADAPTER; |
477 | return; | 453 | return; |
478 | } | 454 | } |
479 | 455 | ||
@@ -482,9 +458,8 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
482 | phw->ado[dsp_index].pa_parent_adapter = pao; | 458 | phw->ado[dsp_index].pa_parent_adapter = pao; |
483 | } | 459 | } |
484 | 460 | ||
485 | phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type; | 461 | phr->u.s.adapter_type = ao.adapter_type; |
486 | phr->u.s.adapter_index = ao.index; | 462 | phr->u.s.adapter_index = ao.index; |
487 | phr->u.s.num_adapters++; | ||
488 | phr->error = 0; | 463 | phr->error = 0; |
489 | } | 464 | } |
490 | 465 | ||
@@ -492,20 +467,13 @@ static void subsys_delete_adapter(struct hpi_message *phm, | |||
492 | struct hpi_response *phr) | 467 | struct hpi_response *phr) |
493 | { | 468 | { |
494 | struct hpi_adapter_obj *pao = NULL; | 469 | struct hpi_adapter_obj *pao = NULL; |
495 | struct hpi_hw_obj *phw; | ||
496 | 470 | ||
497 | pao = hpi_find_adapter(phm->adapter_index); | 471 | pao = hpi_find_adapter(phm->obj_index); |
498 | if (!pao) | 472 | if (!pao) |
499 | return; | 473 | return; |
500 | 474 | ||
501 | phw = (struct hpi_hw_obj *)pao->priv; | 475 | delete_adapter_obj(pao); |
502 | |||
503 | if (pao->has_control_cache) | ||
504 | hpi_free_control_cache(phw->p_cache); | ||
505 | |||
506 | hpi_delete_adapter(pao); | 476 | hpi_delete_adapter(pao); |
507 | kfree(phw); | ||
508 | |||
509 | phr->error = 0; | 477 | phr->error = 0; |
510 | } | 478 | } |
511 | 479 | ||
@@ -519,9 +487,6 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
519 | u32 control_cache_count = 0; | 487 | u32 control_cache_count = 0; |
520 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; | 488 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; |
521 | 489 | ||
522 | /* init error reporting */ | ||
523 | pao->dsp_crashed = 0; | ||
524 | |||
525 | /* The PCI2040 has the following address map */ | 490 | /* The PCI2040 has the following address map */ |
526 | /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ | 491 | /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ |
527 | /* BAR1 - 32K = HPI registers on DSP */ | 492 | /* BAR1 - 32K = HPI registers on DSP */ |
@@ -575,36 +540,36 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
575 | /* get info about the adapter by asking the adapter */ | 540 | /* get info about the adapter by asking the adapter */ |
576 | /* send a HPI_ADAPTER_GET_INFO message */ | 541 | /* send a HPI_ADAPTER_GET_INFO message */ |
577 | { | 542 | { |
578 | struct hpi_message hM; | 543 | struct hpi_message hm; |
579 | struct hpi_response hR0; /* response from DSP 0 */ | 544 | struct hpi_response hr0; /* response from DSP 0 */ |
580 | struct hpi_response hR1; /* response from DSP 1 */ | 545 | struct hpi_response hr1; /* response from DSP 1 */ |
581 | u16 error = 0; | 546 | u16 error = 0; |
582 | 547 | ||
583 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); | 548 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); |
584 | memset(&hM, 0, sizeof(hM)); | 549 | memset(&hm, 0, sizeof(hm)); |
585 | hM.type = HPI_TYPE_MESSAGE; | 550 | hm.type = HPI_TYPE_MESSAGE; |
586 | hM.size = sizeof(struct hpi_message); | 551 | hm.size = sizeof(struct hpi_message); |
587 | hM.object = HPI_OBJ_ADAPTER; | 552 | hm.object = HPI_OBJ_ADAPTER; |
588 | hM.function = HPI_ADAPTER_GET_INFO; | 553 | hm.function = HPI_ADAPTER_GET_INFO; |
589 | hM.adapter_index = 0; | 554 | hm.adapter_index = 0; |
590 | memset(&hR0, 0, sizeof(hR0)); | 555 | memset(&hr0, 0, sizeof(hr0)); |
591 | memset(&hR1, 0, sizeof(hR1)); | 556 | memset(&hr1, 0, sizeof(hr1)); |
592 | hR0.size = sizeof(hR0); | 557 | hr0.size = sizeof(hr0); |
593 | hR1.size = sizeof(hR1); | 558 | hr1.size = sizeof(hr1); |
594 | 559 | ||
595 | error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0); | 560 | error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0); |
596 | if (hR0.error) { | 561 | if (hr0.error) { |
597 | HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error); | 562 | HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error); |
598 | return hR0.error; | 563 | return hr0.error; |
599 | } | 564 | } |
600 | if (phw->num_dsp == 2) { | 565 | if (phw->num_dsp == 2) { |
601 | error = hpi6000_message_response_sequence(pao, 1, &hM, | 566 | error = hpi6000_message_response_sequence(pao, 1, &hm, |
602 | &hR1); | 567 | &hr1); |
603 | if (error) | 568 | if (error) |
604 | return error; | 569 | return error; |
605 | } | 570 | } |
606 | pao->adapter_type = hR0.u.a.adapter_type; | 571 | pao->adapter_type = hr0.u.ax.info.adapter_type; |
607 | pao->index = hR0.u.a.adapter_index; | 572 | pao->index = hr0.u.ax.info.adapter_index; |
608 | } | 573 | } |
609 | 574 | ||
610 | memset(&phw->control_cache[0], 0, | 575 | memset(&phw->control_cache[0], 0, |
@@ -618,22 +583,37 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
618 | control_cache_count = | 583 | control_cache_count = |
619 | hpi_read_word(&phw->ado[0], | 584 | hpi_read_word(&phw->ado[0], |
620 | HPI_HIF_ADDR(control_cache_count)); | 585 | HPI_HIF_ADDR(control_cache_count)); |
621 | pao->has_control_cache = 1; | ||
622 | 586 | ||
623 | phw->p_cache = | 587 | phw->p_cache = |
624 | hpi_alloc_control_cache(control_cache_count, | 588 | hpi_alloc_control_cache(control_cache_count, |
625 | control_cache_size, (struct hpi_control_cache_info *) | 589 | control_cache_size, (unsigned char *) |
626 | &phw->control_cache[0] | 590 | &phw->control_cache[0] |
627 | ); | 591 | ); |
628 | if (!phw->p_cache) | 592 | if (phw->p_cache) |
629 | pao->has_control_cache = 0; | 593 | pao->has_control_cache = 1; |
630 | } else | 594 | } |
631 | pao->has_control_cache = 0; | ||
632 | 595 | ||
633 | HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", | 596 | HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", |
634 | pao->adapter_type, pao->index); | 597 | pao->adapter_type, pao->index); |
635 | pao->open = 0; /* upon creation the adapter is closed */ | 598 | pao->open = 0; /* upon creation the adapter is closed */ |
636 | return 0; | 599 | |
600 | if (phw->p_cache) | ||
601 | phw->p_cache->adap_idx = pao->index; | ||
602 | |||
603 | return hpi_add_adapter(pao); | ||
604 | } | ||
605 | |||
606 | static void delete_adapter_obj(struct hpi_adapter_obj *pao) | ||
607 | { | ||
608 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; | ||
609 | |||
610 | if (pao->has_control_cache) | ||
611 | hpi_free_control_cache(phw->p_cache); | ||
612 | |||
613 | /* reset DSPs on adapter */ | ||
614 | iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET); | ||
615 | |||
616 | kfree(phw); | ||
637 | } | 617 | } |
638 | 618 | ||
639 | /************************************************************************/ | 619 | /************************************************************************/ |
@@ -645,11 +625,13 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao, | |||
645 | #ifndef HIDE_PCI_ASSERTS | 625 | #ifndef HIDE_PCI_ASSERTS |
646 | /* if we have PCI2040 asserts then collect them */ | 626 | /* if we have PCI2040 asserts then collect them */ |
647 | if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { | 627 | if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { |
648 | phr->u.a.serial_number = | 628 | phr->u.ax.assert.p1 = |
649 | gw_pci_read_asserts * 100 + gw_pci_write_asserts; | 629 | gw_pci_read_asserts * 100 + gw_pci_write_asserts; |
650 | phr->u.a.adapter_index = 1; /* assert count */ | 630 | phr->u.ax.assert.p2 = 0; |
651 | phr->u.a.adapter_type = -1; /* "dsp index" */ | 631 | phr->u.ax.assert.count = 1; /* assert count */ |
652 | strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error"); | 632 | phr->u.ax.assert.dsp_index = -1; /* "dsp index" */ |
633 | strcpy(phr->u.ax.assert.sz_message, "PCI2040 error"); | ||
634 | phr->u.ax.assert.dsp_msg_addr = 0; | ||
653 | gw_pci_read_asserts = 0; | 635 | gw_pci_read_asserts = 0; |
654 | gw_pci_write_asserts = 0; | 636 | gw_pci_write_asserts = 0; |
655 | phr->error = 0; | 637 | phr->error = 0; |
@@ -686,10 +668,10 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
686 | 668 | ||
687 | /* NOTE don't use wAdapterType in this routine. It is not setup yet */ | 669 | /* NOTE don't use wAdapterType in this routine. It is not setup yet */ |
688 | 670 | ||
689 | switch (pao->pci.subsys_device_id) { | 671 | switch (pao->pci.pci_dev->subsystem_device) { |
690 | case 0x5100: | 672 | case 0x5100: |
691 | case 0x5110: /* ASI5100 revB or higher with C6711D */ | 673 | case 0x5110: /* ASI5100 revB or higher with C6711D */ |
692 | case 0x5200: /* ASI5200 PC_ie version of ASI5100 */ | 674 | case 0x5200: /* ASI5200 PCIe version of ASI5100 */ |
693 | case 0x6100: | 675 | case 0x6100: |
694 | case 0x6200: | 676 | case 0x6200: |
695 | boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); | 677 | boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); |
@@ -709,8 +691,9 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
709 | * note that bits 4..15 are read-only and so should always return zero, | 691 | * note that bits 4..15 are read-only and so should always return zero, |
710 | * even though we wrote 1 to them | 692 | * even though we wrote 1 to them |
711 | */ | 693 | */ |
712 | for (i = 0; i < 1000; i++) | 694 | hpios_delay_micro_seconds(1000); |
713 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | 695 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); |
696 | |||
714 | if (delay != dw2040_reset) { | 697 | if (delay != dw2040_reset) { |
715 | HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, | 698 | HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, |
716 | delay); | 699 | delay); |
@@ -743,8 +726,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
743 | dw2040_reset = dw2040_reset & (~0x00000008); | 726 | dw2040_reset = dw2040_reset & (~0x00000008); |
744 | iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); | 727 | iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); |
745 | /*delay to allow DSP to get going */ | 728 | /*delay to allow DSP to get going */ |
746 | for (i = 0; i < 100; i++) | 729 | hpios_delay_micro_seconds(100); |
747 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
748 | 730 | ||
749 | /* loop through all DSPs, downloading DSP code */ | 731 | /* loop through all DSPs, downloading DSP code */ |
750 | for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { | 732 | for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { |
@@ -783,27 +765,27 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
783 | */ | 765 | */ |
784 | /* bypass PLL */ | 766 | /* bypass PLL */ |
785 | hpi_write_word(pdo, 0x01B7C100, 0x0000); | 767 | hpi_write_word(pdo, 0x01B7C100, 0x0000); |
786 | for (i = 0; i < 100; i++) | 768 | hpios_delay_micro_seconds(100); |
787 | delay = ioread32(phw->dw2040_HPICSR + | ||
788 | HPI_RESET); | ||
789 | 769 | ||
790 | /* ** use default of PLL x7 ** */ | 770 | /* ** use default of PLL x7 ** */ |
791 | /* EMIF = 225/3=75MHz */ | 771 | /* EMIF = 225/3=75MHz */ |
792 | hpi_write_word(pdo, 0x01B7C120, 0x8002); | 772 | hpi_write_word(pdo, 0x01B7C120, 0x8002); |
773 | hpios_delay_micro_seconds(100); | ||
774 | |||
793 | /* peri = 225/2 */ | 775 | /* peri = 225/2 */ |
794 | hpi_write_word(pdo, 0x01B7C11C, 0x8001); | 776 | hpi_write_word(pdo, 0x01B7C11C, 0x8001); |
777 | hpios_delay_micro_seconds(100); | ||
778 | |||
795 | /* cpu = 225/1 */ | 779 | /* cpu = 225/1 */ |
796 | hpi_write_word(pdo, 0x01B7C118, 0x8000); | 780 | hpi_write_word(pdo, 0x01B7C118, 0x8000); |
797 | /* ~200us delay */ | 781 | |
798 | for (i = 0; i < 2000; i++) | 782 | /* ~2ms delay */ |
799 | delay = ioread32(phw->dw2040_HPICSR + | 783 | hpios_delay_micro_seconds(2000); |
800 | HPI_RESET); | 784 | |
801 | /* PLL not bypassed */ | 785 | /* PLL not bypassed */ |
802 | hpi_write_word(pdo, 0x01B7C100, 0x0001); | 786 | hpi_write_word(pdo, 0x01B7C100, 0x0001); |
803 | /* ~200us delay */ | 787 | /* ~2ms delay */ |
804 | for (i = 0; i < 2000; i++) | 788 | hpios_delay_micro_seconds(2000); |
805 | delay = ioread32(phw->dw2040_HPICSR + | ||
806 | HPI_RESET); | ||
807 | } | 789 | } |
808 | 790 | ||
809 | /* test r/w to internal DSP memory | 791 | /* test r/w to internal DSP memory |
@@ -927,9 +909,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
927 | } | 909 | } |
928 | 910 | ||
929 | /* delay a little to allow SDRAM and DSP to "get going" */ | 911 | /* delay a little to allow SDRAM and DSP to "get going" */ |
930 | 912 | hpios_delay_micro_seconds(1000); | |
931 | for (i = 0; i < 1000; i++) | ||
932 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
933 | 913 | ||
934 | /* test access to SDRAM */ | 914 | /* test access to SDRAM */ |
935 | { | 915 | { |
@@ -976,7 +956,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
976 | 956 | ||
977 | /* write the DSP code down into the DSPs memory */ | 957 | /* write the DSP code down into the DSPs memory */ |
978 | /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */ | 958 | /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */ |
979 | dsp_code.ps_dev = pao->pci.p_os_data; | 959 | dsp_code.ps_dev = pao->pci.pci_dev; |
980 | 960 | ||
981 | error = hpi_dsp_code_open(boot_load_family, &dsp_code, | 961 | error = hpi_dsp_code_open(boot_load_family, &dsp_code, |
982 | pos_error_code); | 962 | pos_error_code); |
@@ -1073,8 +1053,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1073 | 1053 | ||
1074 | /* step 3. Start code by sending interrupt */ | 1054 | /* step 3. Start code by sending interrupt */ |
1075 | iowrite32(0x00030003, pdo->prHPI_control); | 1055 | iowrite32(0x00030003, pdo->prHPI_control); |
1076 | for (i = 0; i < 10000; i++) | 1056 | hpios_delay_micro_seconds(10000); |
1077 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
1078 | 1057 | ||
1079 | /* wait for a non-zero value in hostcmd - | 1058 | /* wait for a non-zero value in hostcmd - |
1080 | * indicating initialization is complete | 1059 | * indicating initialization is complete |
@@ -1101,7 +1080,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1101 | * locks up with a bluescreen (NOT GPF or pagefault). | 1080 | * locks up with a bluescreen (NOT GPF or pagefault). |
1102 | */ | 1081 | */ |
1103 | else | 1082 | else |
1104 | hpios_delay_micro_seconds(1000); | 1083 | hpios_delay_micro_seconds(10000); |
1105 | } | 1084 | } |
1106 | if (timeout == 0) | 1085 | if (timeout == 0) |
1107 | return HPI6000_ERROR_INIT_NOACK; | 1086 | return HPI6000_ERROR_INIT_NOACK; |
@@ -1132,14 +1111,14 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1132 | mask = 0xFFFFFF00L; | 1111 | mask = 0xFFFFFF00L; |
1133 | /* ASI5100 uses AX6 code, */ | 1112 | /* ASI5100 uses AX6 code, */ |
1134 | /* but has no PLD r/w register to test */ | 1113 | /* but has no PLD r/w register to test */ |
1135 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci. | 1114 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> |
1136 | subsys_device_id) == | 1115 | subsystem_device) == |
1137 | HPI_ADAPTER_FAMILY_ASI(0x5100)) | 1116 | HPI_ADAPTER_FAMILY_ASI(0x5100)) |
1138 | mask = 0x00000000L; | 1117 | mask = 0x00000000L; |
1139 | /* ASI5200 uses AX6 code, */ | 1118 | /* ASI5200 uses AX6 code, */ |
1140 | /* but has no PLD r/w register to test */ | 1119 | /* but has no PLD r/w register to test */ |
1141 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci. | 1120 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> |
1142 | subsys_device_id) == | 1121 | subsystem_device) == |
1143 | HPI_ADAPTER_FAMILY_ASI(0x5200)) | 1122 | HPI_ADAPTER_FAMILY_ASI(0x5200)) |
1144 | mask = 0x00000000L; | 1123 | mask = 0x00000000L; |
1145 | break; | 1124 | break; |
@@ -1204,7 +1183,7 @@ static u32 hpi_read_word(struct dsp_obj *pdo, u32 address) | |||
1204 | u32 data = 0; | 1183 | u32 data = 0; |
1205 | 1184 | ||
1206 | if (hpi_set_address(pdo, address)) | 1185 | if (hpi_set_address(pdo, address)) |
1207 | return 0; /*? no way to return error */ | 1186 | return 0; /*? No way to return error */ |
1208 | 1187 | ||
1209 | /* take care of errata in revB DSP (2.0.1) */ | 1188 | /* take care of errata in revB DSP (2.0.1) */ |
1210 | data = ioread32(pdo->prHPI_data); | 1189 | data = ioread32(pdo->prHPI_data); |
@@ -1340,10 +1319,6 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1340 | u32 *p_data; | 1319 | u32 *p_data; |
1341 | u16 error = 0; | 1320 | u16 error = 0; |
1342 | 1321 | ||
1343 | /* does the DSP we are referencing exist? */ | ||
1344 | if (dsp_index >= phw->num_dsp) | ||
1345 | return HPI6000_ERROR_MSG_INVALID_DSP_INDEX; | ||
1346 | |||
1347 | ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); | 1322 | ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); |
1348 | if (ack & HPI_HIF_ERROR_MASK) { | 1323 | if (ack & HPI_HIF_ERROR_MASK) { |
1349 | pao->dsp_crashed++; | 1324 | pao->dsp_crashed++; |
@@ -1351,9 +1326,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1351 | } | 1326 | } |
1352 | pao->dsp_crashed = 0; | 1327 | pao->dsp_crashed = 0; |
1353 | 1328 | ||
1354 | /* send the message */ | 1329 | /* get the message address and size */ |
1355 | |||
1356 | /* get the address and size */ | ||
1357 | if (phw->message_buffer_address_on_dsp == 0) { | 1330 | if (phw->message_buffer_address_on_dsp == 0) { |
1358 | timeout = TIMEOUT; | 1331 | timeout = TIMEOUT; |
1359 | do { | 1332 | do { |
@@ -1368,10 +1341,9 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1368 | } else | 1341 | } else |
1369 | address = phw->message_buffer_address_on_dsp; | 1342 | address = phw->message_buffer_address_on_dsp; |
1370 | 1343 | ||
1371 | /* dwLength = sizeof(struct hpi_message); */ | ||
1372 | length = phm->size; | 1344 | length = phm->size; |
1373 | 1345 | ||
1374 | /* send it */ | 1346 | /* send the message */ |
1375 | p_data = (u32 *)phm; | 1347 | p_data = (u32 *)phm; |
1376 | if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, | 1348 | if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, |
1377 | (u16)length / 4)) | 1349 | (u16)length / 4)) |
@@ -1385,7 +1357,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1385 | if (ack & HPI_HIF_ERROR_MASK) | 1357 | if (ack & HPI_HIF_ERROR_MASK) |
1386 | return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; | 1358 | return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; |
1387 | 1359 | ||
1388 | /* get the address and size */ | 1360 | /* get the response address */ |
1389 | if (phw->response_buffer_address_on_dsp == 0) { | 1361 | if (phw->response_buffer_address_on_dsp == 0) { |
1390 | timeout = TIMEOUT; | 1362 | timeout = TIMEOUT; |
1391 | do { | 1363 | do { |
@@ -1409,7 +1381,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1409 | if (!timeout) | 1381 | if (!timeout) |
1410 | length = sizeof(struct hpi_response); | 1382 | length = sizeof(struct hpi_response); |
1411 | 1383 | ||
1412 | /* get it */ | 1384 | /* get the response */ |
1413 | p_data = (u32 *)phr; | 1385 | p_data = (u32 *)phr; |
1414 | if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, | 1386 | if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, |
1415 | (u16)length / 4)) | 1387 | (u16)length / 4)) |
@@ -1805,17 +1777,11 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
1805 | hpios_dsplock_lock(pao); | 1777 | hpios_dsplock_lock(pao); |
1806 | error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); | 1778 | error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); |
1807 | 1779 | ||
1808 | /* maybe an error response */ | 1780 | if (error) /* something failed in the HPI/DSP interface */ |
1809 | if (error) { | ||
1810 | /* something failed in the HPI/DSP interface */ | ||
1811 | phr->error = error; | ||
1812 | /* just the header of the response is valid */ | ||
1813 | phr->size = sizeof(struct hpi_response_header); | ||
1814 | goto err; | 1781 | goto err; |
1815 | } | ||
1816 | 1782 | ||
1817 | if (phr->error != 0) /* something failed in the DSP */ | 1783 | if (phr->error) /* something failed in the DSP */ |
1818 | goto err; | 1784 | goto out; |
1819 | 1785 | ||
1820 | switch (phm->function) { | 1786 | switch (phm->function) { |
1821 | case HPI_OSTREAM_WRITE: | 1787 | case HPI_OSTREAM_WRITE: |
@@ -1827,21 +1793,30 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
1827 | error = hpi6000_get_data(pao, dsp_index, phm, phr); | 1793 | error = hpi6000_get_data(pao, dsp_index, phm, phr); |
1828 | break; | 1794 | break; |
1829 | case HPI_ADAPTER_GET_ASSERT: | 1795 | case HPI_ADAPTER_GET_ASSERT: |
1830 | phr->u.a.adapter_index = 0; /* dsp 0 default */ | 1796 | phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */ |
1831 | if (num_dsp == 2) { | 1797 | if (num_dsp == 2) { |
1832 | if (!phr->u.a.adapter_type) { | 1798 | if (!phr->u.ax.assert.count) { |
1833 | /* no assert from dsp 0, check dsp 1 */ | 1799 | /* no assert from dsp 0, check dsp 1 */ |
1834 | error = hpi6000_message_response_sequence(pao, | 1800 | error = hpi6000_message_response_sequence(pao, |
1835 | 1, phm, phr); | 1801 | 1, phm, phr); |
1836 | phr->u.a.adapter_index = 1; | 1802 | phr->u.ax.assert.dsp_index = 1; |
1837 | } | 1803 | } |
1838 | } | 1804 | } |
1839 | } | 1805 | } |
1840 | 1806 | ||
1841 | if (error) | ||
1842 | phr->error = error; | ||
1843 | |||
1844 | err: | 1807 | err: |
1808 | if (error) { | ||
1809 | if (error >= HPI_ERROR_BACKEND_BASE) { | ||
1810 | phr->error = HPI_ERROR_DSP_COMMUNICATION; | ||
1811 | phr->specific_error = error; | ||
1812 | } else { | ||
1813 | phr->error = error; | ||
1814 | } | ||
1815 | |||
1816 | /* just the header of the response is valid */ | ||
1817 | phr->size = sizeof(struct hpi_response_header); | ||
1818 | } | ||
1819 | out: | ||
1845 | hpios_dsplock_unlock(pao); | 1820 | hpios_dsplock_unlock(pao); |
1846 | return; | 1821 | return; |
1847 | } | 1822 | } |