2220 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/******************************************************************************3 4 AudioScience HPI driver5 Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>6 7 8 Hardware Programming Interface (HPI) for AudioScience9 ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters.10 These PCI and PCIe bus adapters are based on a11 TMS320C6205 PCI bus mastering DSP,12 and (except ASI50xx) TI TMS320C6xxx floating point DSP13 14 Exported function:15 void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)16 17(C) Copyright AudioScience Inc. 1998-201018*******************************************************************************/19#define SOURCEFILE_NAME "hpi6205.c"20 21#include "hpi_internal.h"22#include "hpimsginit.h"23#include "hpidebug.h"24#include "hpi6205.h"25#include "hpidspcd.h"26#include "hpicmn.h"27 28/*****************************************************************************/29/* HPI6205 specific error codes */30#define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */31 32/* operational/messaging errors */33#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 101534#define HPI6205_ERROR_MSG_RESP_TIMEOUT 101635 36/* initialization/bootload errors */37#define HPI6205_ERROR_6205_NO_IRQ 100238#define HPI6205_ERROR_6205_INIT_FAILED 100339#define HPI6205_ERROR_6205_REG 100640#define HPI6205_ERROR_6205_DSPPAGE 100741#define HPI6205_ERROR_C6713_HPIC 100942#define HPI6205_ERROR_C6713_HPIA 101043#define HPI6205_ERROR_C6713_PLL 101144#define HPI6205_ERROR_DSP_INTMEM 101245#define HPI6205_ERROR_DSP_EXTMEM 101346#define HPI6205_ERROR_DSP_PLD 101447#define HPI6205_ERROR_6205_EEPROM 101748#define HPI6205_ERROR_DSP_EMIF1 101849#define HPI6205_ERROR_DSP_EMIF2 101950#define HPI6205_ERROR_DSP_EMIF3 102051#define HPI6205_ERROR_DSP_EMIF4 102152 53/*****************************************************************************/54/* for C6205 PCI i/f */55/* Host Status Register (HSR) bitfields */56#define C6205_HSR_INTSRC 0x0157#define C6205_HSR_INTAVAL 0x0258#define C6205_HSR_INTAM 0x0459#define C6205_HSR_CFGERR 0x0860#define C6205_HSR_EEREAD 0x1061/* Host-to-DSP Control Register (HDCR) bitfields */62#define C6205_HDCR_WARMRESET 0x0163#define C6205_HDCR_DSPINT 0x0264#define C6205_HDCR_PCIBOOT 0x0465/* DSP Page Register (DSPP) bitfields, */66/* defines 4 Mbyte page that BAR0 points to */67#define C6205_DSPP_MAP1 0x40068 69/* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP.70 * BAR1 maps to non-prefetchable 8 Mbyte memory block71 * of DSP memory mapped registers (starting at 0x01800000).72 * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this73 * needs to be added to the BAR1 base address set in the PCI config reg74 */75#define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L)76#define C6205_BAR1_HSR (C6205_BAR1_PCI_IO_OFFSET)77#define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4)78#define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8)79 80/* used to control LED (revA) and reset C6713 (revB) */81#define C6205_BAR0_TIMER1_CTL (0x01980000L)82 83/* For first 6713 in CE1 space, using DA17,16,2 */84#define HPICL_ADDR 0x01400000L85#define HPICH_ADDR 0x01400004L86#define HPIAL_ADDR 0x01410000L87#define HPIAH_ADDR 0x01410004L88#define HPIDIL_ADDR 0x01420000L89#define HPIDIH_ADDR 0x01420004L90#define HPIDL_ADDR 0x01430000L91#define HPIDH_ADDR 0x01430004L92 93#define C6713_EMIF_GCTL 0x0180000094#define C6713_EMIF_CE1 0x0180000495#define C6713_EMIF_CE0 0x0180000896#define C6713_EMIF_CE2 0x0180001097#define C6713_EMIF_CE3 0x0180001498#define C6713_EMIF_SDRAMCTL 0x0180001899#define C6713_EMIF_SDRAMTIMING 0x0180001C100#define C6713_EMIF_SDRAMEXT 0x01800020101 102struct hpi_hw_obj {103 /* PCI registers */104 __iomem u32 *prHSR;105 __iomem u32 *prHDCR;106 __iomem u32 *prDSPP;107 108 u32 dsp_page;109 110 struct consistent_dma_area h_locked_mem;111 struct bus_master_interface *p_interface_buffer;112 113 u16 flag_outstream_just_reset[HPI_MAX_STREAMS];114 /* a non-NULL handle means there is an HPI allocated buffer */115 struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS];116 struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS];117 /* non-zero size means a buffer exists, may be external */118 u32 instream_host_buffer_size[HPI_MAX_STREAMS];119 u32 outstream_host_buffer_size[HPI_MAX_STREAMS];120 121 struct consistent_dma_area h_control_cache;122 struct hpi_control_cache *p_cache;123};124 125/*****************************************************************************/126/* local prototypes */127 128#define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write)129 130static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us);131 132static void send_dsp_command(struct hpi_hw_obj *phw, int cmd);133 134static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,135 u32 *pos_error_code);136 137static u16 message_response_sequence(struct hpi_adapter_obj *pao,138 struct hpi_message *phm, struct hpi_response *phr);139 140static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,141 struct hpi_response *phr);142 143#define HPI6205_TIMEOUT 1000000144 145static void subsys_create_adapter(struct hpi_message *phm,146 struct hpi_response *phr);147static void adapter_delete(struct hpi_adapter_obj *pao,148 struct hpi_message *phm, struct hpi_response *phr);149 150static u16 create_adapter_obj(struct hpi_adapter_obj *pao,151 u32 *pos_error_code);152 153static void delete_adapter_obj(struct hpi_adapter_obj *pao);154 155static int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao,156 u32 message);157 158static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,159 struct hpi_message *phm, struct hpi_response *phr);160 161static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,162 struct hpi_message *phm, struct hpi_response *phr);163 164static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,165 struct hpi_message *phm, struct hpi_response *phr);166static void outstream_write(struct hpi_adapter_obj *pao,167 struct hpi_message *phm, struct hpi_response *phr);168 169static void outstream_get_info(struct hpi_adapter_obj *pao,170 struct hpi_message *phm, struct hpi_response *phr);171 172static void outstream_start(struct hpi_adapter_obj *pao,173 struct hpi_message *phm, struct hpi_response *phr);174 175static void outstream_open(struct hpi_adapter_obj *pao,176 struct hpi_message *phm, struct hpi_response *phr);177 178static void outstream_reset(struct hpi_adapter_obj *pao,179 struct hpi_message *phm, struct hpi_response *phr);180 181static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,182 struct hpi_message *phm, struct hpi_response *phr);183 184static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,185 struct hpi_message *phm, struct hpi_response *phr);186 187static void instream_host_buffer_free(struct hpi_adapter_obj *pao,188 struct hpi_message *phm, struct hpi_response *phr);189 190static void instream_read(struct hpi_adapter_obj *pao,191 struct hpi_message *phm, struct hpi_response *phr);192 193static void instream_get_info(struct hpi_adapter_obj *pao,194 struct hpi_message *phm, struct hpi_response *phr);195 196static void instream_start(struct hpi_adapter_obj *pao,197 struct hpi_message *phm, struct hpi_response *phr);198 199static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,200 u32 address);201 202static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,203 int dsp_index, u32 address, u32 data);204 205static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao,206 int dsp_index);207 208static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,209 u32 address, u32 length);210 211static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,212 int dsp_index);213 214static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,215 int dsp_index);216 217static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);218 219/*****************************************************************************/220 221static void subsys_message(struct hpi_adapter_obj *pao,222 struct hpi_message *phm, struct hpi_response *phr)223{224 switch (phm->function) {225 case HPI_SUBSYS_CREATE_ADAPTER:226 subsys_create_adapter(phm, phr);227 break;228 default:229 phr->error = HPI_ERROR_INVALID_FUNC;230 break;231 }232}233 234static void control_message(struct hpi_adapter_obj *pao,235 struct hpi_message *phm, struct hpi_response *phr)236{237 238 struct hpi_hw_obj *phw = pao->priv;239 u16 pending_cache_error = 0;240 241 switch (phm->function) {242 case HPI_CONTROL_GET_STATE:243 if (pao->has_control_cache) {244 rmb(); /* make sure we see updates DMAed from DSP */245 if (hpi_check_control_cache(phw->p_cache, phm, phr)) {246 break;247 } else if (phm->u.c.attribute == HPI_METER_PEAK) {248 pending_cache_error =249 HPI_ERROR_CONTROL_CACHING;250 }251 }252 hw_message(pao, phm, phr);253 if (pending_cache_error && !phr->error)254 phr->error = pending_cache_error;255 break;256 case HPI_CONTROL_GET_INFO:257 hw_message(pao, phm, phr);258 break;259 case HPI_CONTROL_SET_STATE:260 hw_message(pao, phm, phr);261 if (pao->has_control_cache)262 hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm,263 phr);264 break;265 default:266 phr->error = HPI_ERROR_INVALID_FUNC;267 break;268 }269}270 271static void adapter_message(struct hpi_adapter_obj *pao,272 struct hpi_message *phm, struct hpi_response *phr)273{274 switch (phm->function) {275 case HPI_ADAPTER_DELETE:276 adapter_delete(pao, phm, phr);277 break;278 default:279 hw_message(pao, phm, phr);280 break;281 }282}283 284static void outstream_message(struct hpi_adapter_obj *pao,285 struct hpi_message *phm, struct hpi_response *phr)286{287 288 if (phm->obj_index >= HPI_MAX_STREAMS) {289 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;290 HPI_DEBUG_LOG(WARNING,291 "Message referencing invalid stream %d "292 "on adapter index %d\n", phm->obj_index,293 phm->adapter_index);294 return;295 }296 297 switch (phm->function) {298 case HPI_OSTREAM_WRITE:299 outstream_write(pao, phm, phr);300 break;301 case HPI_OSTREAM_GET_INFO:302 outstream_get_info(pao, phm, phr);303 break;304 case HPI_OSTREAM_HOSTBUFFER_ALLOC:305 outstream_host_buffer_allocate(pao, phm, phr);306 break;307 case HPI_OSTREAM_HOSTBUFFER_GET_INFO:308 outstream_host_buffer_get_info(pao, phm, phr);309 break;310 case HPI_OSTREAM_HOSTBUFFER_FREE:311 outstream_host_buffer_free(pao, phm, phr);312 break;313 case HPI_OSTREAM_START:314 outstream_start(pao, phm, phr);315 break;316 case HPI_OSTREAM_OPEN:317 outstream_open(pao, phm, phr);318 break;319 case HPI_OSTREAM_RESET:320 outstream_reset(pao, phm, phr);321 break;322 default:323 hw_message(pao, phm, phr);324 break;325 }326}327 328static void instream_message(struct hpi_adapter_obj *pao,329 struct hpi_message *phm, struct hpi_response *phr)330{331 332 if (phm->obj_index >= HPI_MAX_STREAMS) {333 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;334 HPI_DEBUG_LOG(WARNING,335 "Message referencing invalid stream %d "336 "on adapter index %d\n", phm->obj_index,337 phm->adapter_index);338 return;339 }340 341 switch (phm->function) {342 case HPI_ISTREAM_READ:343 instream_read(pao, phm, phr);344 break;345 case HPI_ISTREAM_GET_INFO:346 instream_get_info(pao, phm, phr);347 break;348 case HPI_ISTREAM_HOSTBUFFER_ALLOC:349 instream_host_buffer_allocate(pao, phm, phr);350 break;351 case HPI_ISTREAM_HOSTBUFFER_GET_INFO:352 instream_host_buffer_get_info(pao, phm, phr);353 break;354 case HPI_ISTREAM_HOSTBUFFER_FREE:355 instream_host_buffer_free(pao, phm, phr);356 break;357 case HPI_ISTREAM_START:358 instream_start(pao, phm, phr);359 break;360 default:361 hw_message(pao, phm, phr);362 break;363 }364}365 366/*****************************************************************************/367/** Entry point to this HPI backend368 * All calls to the HPI start here369 */370static371void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,372 struct hpi_response *phr)373{374 if (pao && (pao->dsp_crashed >= 10)375 && (phm->function != HPI_ADAPTER_DEBUG_READ)) {376 /* allow last resort debug read even after crash */377 hpi_init_response(phr, phm->object, phm->function,378 HPI_ERROR_DSP_HARDWARE);379 HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object,380 phm->function);381 return;382 }383 384 /* Init default response */385 if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)386 phr->error = HPI_ERROR_PROCESSING_MESSAGE;387 388 HPI_DEBUG_LOG(VERBOSE, "start of switch\n");389 switch (phm->type) {390 case HPI_TYPE_REQUEST:391 switch (phm->object) {392 case HPI_OBJ_SUBSYSTEM:393 subsys_message(pao, phm, phr);394 break;395 396 case HPI_OBJ_ADAPTER:397 adapter_message(pao, phm, phr);398 break;399 400 case HPI_OBJ_CONTROL:401 control_message(pao, phm, phr);402 break;403 404 case HPI_OBJ_OSTREAM:405 outstream_message(pao, phm, phr);406 break;407 408 case HPI_OBJ_ISTREAM:409 instream_message(pao, phm, phr);410 break;411 412 default:413 hw_message(pao, phm, phr);414 break;415 }416 break;417 418 default:419 phr->error = HPI_ERROR_INVALID_TYPE;420 break;421 }422}423 424void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)425{426 struct hpi_adapter_obj *pao = NULL;427 428 if (phm->object != HPI_OBJ_SUBSYSTEM) {429 /* normal messages must have valid adapter index */430 pao = hpi_find_adapter(phm->adapter_index);431 } else {432 /* subsys messages don't address an adapter */433 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;434 return;435 }436 437 if (pao)438 _HPI_6205(pao, phm, phr);439 else440 hpi_init_response(phr, phm->object, phm->function,441 HPI_ERROR_BAD_ADAPTER_NUMBER);442}443 444/*****************************************************************************/445/* SUBSYSTEM */446 447/** Create an adapter object and initialise it based on resource information448 * passed in the message449 * *** NOTE - you cannot use this function AND the FindAdapters function at the450 * same time, the application must use only one of them to get the adapters ***451 */452static void subsys_create_adapter(struct hpi_message *phm,453 struct hpi_response *phr)454{455 /* create temp adapter obj, because we don't know what index yet */456 struct hpi_adapter_obj ao;457 u32 os_error_code;458 u16 err;459 460 HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n");461 462 memset(&ao, 0, sizeof(ao));463 464 ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);465 if (!ao.priv) {466 HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n");467 phr->error = HPI_ERROR_MEMORY_ALLOC;468 return;469 }470 471 ao.pci = *phm->u.s.resource.r.pci;472 err = create_adapter_obj(&ao, &os_error_code);473 if (err) {474 delete_adapter_obj(&ao);475 if (err >= HPI_ERROR_BACKEND_BASE) {476 phr->error = HPI_ERROR_DSP_BOOTLOAD;477 phr->specific_error = err;478 } else {479 phr->error = err;480 }481 phr->u.s.data = os_error_code;482 return;483 }484 485 phr->u.s.adapter_type = ao.type;486 phr->u.s.adapter_index = ao.index;487 phr->error = 0;488}489 490/** delete an adapter - required by WDM driver */491static void adapter_delete(struct hpi_adapter_obj *pao,492 struct hpi_message *phm, struct hpi_response *phr)493{494 struct hpi_hw_obj *phw;495 496 if (!pao) {497 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;498 return;499 }500 phw = pao->priv;501 /* reset adapter h/w */502 /* Reset C6713 #1 */503 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);504 /* reset C6205 */505 iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);506 507 delete_adapter_obj(pao);508 hpi_delete_adapter(pao);509 phr->error = 0;510}511 512/** Create adapter object513 allocate buffers, bootload DSPs, initialise control cache514*/515static u16 create_adapter_obj(struct hpi_adapter_obj *pao,516 u32 *pos_error_code)517{518 struct hpi_hw_obj *phw = pao->priv;519 struct bus_master_interface *interface;520 u32 phys_addr;521 int i;522 u16 err;523 524 /* init error reporting */525 pao->dsp_crashed = 0;526 527 for (i = 0; i < HPI_MAX_STREAMS; i++)528 phw->flag_outstream_just_reset[i] = 1;529 530 /* The C6205 memory area 1 is 8Mbyte window into DSP registers */531 phw->prHSR =532 pao->pci.ap_mem_base[1] +533 C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);534 phw->prHDCR =535 pao->pci.ap_mem_base[1] +536 C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);537 phw->prDSPP =538 pao->pci.ap_mem_base[1] +539 C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);540 541 pao->has_control_cache = 0;542 543 if (hpios_locked_mem_alloc(&phw->h_locked_mem,544 sizeof(struct bus_master_interface),545 pao->pci.pci_dev))546 phw->p_interface_buffer = NULL;547 else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,548 (void *)&phw->p_interface_buffer))549 phw->p_interface_buffer = NULL;550 551 HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",552 phw->p_interface_buffer);553 554 if (phw->p_interface_buffer) {555 memset((void *)phw->p_interface_buffer, 0,556 sizeof(struct bus_master_interface));557 phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;558 }559 560 err = adapter_boot_load_dsp(pao, pos_error_code);561 if (err) {562 HPI_DEBUG_LOG(ERROR, "DSP code load failed\n");563 /* no need to clean up as SubSysCreateAdapter */564 /* calls DeleteAdapter on error. */565 return err;566 }567 HPI_DEBUG_LOG(INFO, "load DSP code OK\n");568 569 /* allow boot load even if mem alloc wont work */570 if (!phw->p_interface_buffer)571 return HPI_ERROR_MEMORY_ALLOC;572 573 interface = phw->p_interface_buffer;574 575 /* make sure the DSP has started ok */576 if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {577 HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");578 return HPI6205_ERROR_6205_INIT_FAILED;579 }580 /* Note that *pao, *phw are zeroed after allocation,581 * so pointers and flags are NULL by default.582 * Allocate bus mastering control cache buffer and tell the DSP about it583 */584 if (interface->control_cache.number_of_controls) {585 u8 *p_control_cache_virtual;586 587 err = hpios_locked_mem_alloc(&phw->h_control_cache,588 interface->control_cache.size_in_bytes,589 pao->pci.pci_dev);590 if (!err)591 err = hpios_locked_mem_get_virt_addr(&phw->592 h_control_cache,593 (void *)&p_control_cache_virtual);594 if (!err) {595 memset(p_control_cache_virtual, 0,596 interface->control_cache.size_in_bytes);597 598 phw->p_cache =599 hpi_alloc_control_cache(interface->600 control_cache.number_of_controls,601 interface->control_cache.size_in_bytes,602 p_control_cache_virtual);603 604 if (!phw->p_cache)605 err = HPI_ERROR_MEMORY_ALLOC;606 }607 if (!err) {608 err = hpios_locked_mem_get_phys_addr(&phw->609 h_control_cache, &phys_addr);610 interface->control_cache.physical_address32 =611 phys_addr;612 }613 614 if (!err)615 pao->has_control_cache = 1;616 else {617 if (hpios_locked_mem_valid(&phw->h_control_cache))618 hpios_locked_mem_free(&phw->h_control_cache);619 pao->has_control_cache = 0;620 }621 }622 send_dsp_command(phw, H620_HIF_IDLE);623 624 {625 struct hpi_message hm;626 struct hpi_response hr;627 628 HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");629 memset(&hm, 0, sizeof(hm));630 /* wAdapterIndex == version == 0 */631 hm.type = HPI_TYPE_REQUEST;632 hm.size = sizeof(hm);633 hm.object = HPI_OBJ_ADAPTER;634 hm.function = HPI_ADAPTER_GET_INFO;635 636 memset(&hr, 0, sizeof(hr));637 hr.size = sizeof(hr);638 639 err = message_response_sequence(pao, &hm, &hr);640 if (err) {641 HPI_DEBUG_LOG(ERROR, "message transport error %d\n",642 err);643 return err;644 }645 if (hr.error)646 return hr.error;647 648 pao->type = hr.u.ax.info.adapter_type;649 pao->index = hr.u.ax.info.adapter_index;650 651 HPI_DEBUG_LOG(VERBOSE,652 "got adapter info type %x index %d serial %d\n",653 hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,654 hr.u.ax.info.serial_number);655 }656 657 if (phw->p_cache)658 phw->p_cache->adap_idx = pao->index;659 660 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");661 662 pao->irq_query_and_clear = adapter_irq_query_and_clear;663 pao->instream_host_buffer_status =664 phw->p_interface_buffer->instream_host_buffer_status;665 pao->outstream_host_buffer_status =666 phw->p_interface_buffer->outstream_host_buffer_status;667 668 return hpi_add_adapter(pao);669}670 671/** Free memory areas allocated by adapter672 * this routine is called from AdapterDelete,673 * and SubSysCreateAdapter if duplicate index674*/675static void delete_adapter_obj(struct hpi_adapter_obj *pao)676{677 struct hpi_hw_obj *phw = pao->priv;678 int i;679 680 if (hpios_locked_mem_valid(&phw->h_control_cache)) {681 hpios_locked_mem_free(&phw->h_control_cache);682 hpi_free_control_cache(phw->p_cache);683 }684 685 if (hpios_locked_mem_valid(&phw->h_locked_mem)) {686 hpios_locked_mem_free(&phw->h_locked_mem);687 phw->p_interface_buffer = NULL;688 }689 690 for (i = 0; i < HPI_MAX_STREAMS; i++)691 if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {692 hpios_locked_mem_free(&phw->instream_host_buffers[i]);693 /*?phw->InStreamHostBuffers[i] = NULL; */694 phw->instream_host_buffer_size[i] = 0;695 }696 697 for (i = 0; i < HPI_MAX_STREAMS; i++)698 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {699 hpios_locked_mem_free(&phw->outstream_host_buffers700 [i]);701 phw->outstream_host_buffer_size[i] = 0;702 }703 kfree(phw);704}705 706/*****************************************************************************/707/* Adapter functions */708static int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao,709 u32 message)710{711 struct hpi_hw_obj *phw = pao->priv;712 u32 hsr = 0;713 714 hsr = ioread32(phw->prHSR);715 if (hsr & C6205_HSR_INTSRC) {716 /* reset the interrupt from the DSP */717 iowrite32(C6205_HSR_INTSRC, phw->prHSR);718 return HPI_IRQ_MIXER;719 }720 721 return HPI_IRQ_NONE;722}723 724/*****************************************************************************/725/* OutStream Host buffer functions */726 727/** Allocate or attach buffer for busmastering728*/729static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,730 struct hpi_message *phm, struct hpi_response *phr)731{732 u16 err = 0;733 u32 command = phm->u.d.u.buffer.command;734 struct hpi_hw_obj *phw = pao->priv;735 struct bus_master_interface *interface = phw->p_interface_buffer;736 737 hpi_init_response(phr, phm->object, phm->function, 0);738 739 if (command == HPI_BUFFER_CMD_EXTERNAL740 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {741 /* ALLOC phase, allocate a buffer with power of 2 size,742 get its bus address for PCI bus mastering743 */744 phm->u.d.u.buffer.buffer_size =745 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);746 /* return old size and allocated size,747 so caller can detect change */748 phr->u.d.u.stream_info.data_available =749 phw->outstream_host_buffer_size[phm->obj_index];750 phr->u.d.u.stream_info.buffer_size =751 phm->u.d.u.buffer.buffer_size;752 753 if (phw->outstream_host_buffer_size[phm->obj_index] ==754 phm->u.d.u.buffer.buffer_size) {755 /* Same size, no action required */756 return;757 }758 759 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->760 obj_index]))761 hpios_locked_mem_free(&phw->outstream_host_buffers762 [phm->obj_index]);763 764 err = hpios_locked_mem_alloc(&phw->outstream_host_buffers765 [phm->obj_index], phm->u.d.u.buffer.buffer_size,766 pao->pci.pci_dev);767 768 if (err) {769 phr->error = HPI_ERROR_INVALID_DATASIZE;770 phw->outstream_host_buffer_size[phm->obj_index] = 0;771 return;772 }773 774 err = hpios_locked_mem_get_phys_addr775 (&phw->outstream_host_buffers[phm->obj_index],776 &phm->u.d.u.buffer.pci_address);777 /* get the phys addr into msg for single call alloc caller778 * needs to do this for split alloc (or use the same message)779 * return the phy address for split alloc in the respose too780 */781 phr->u.d.u.stream_info.auxiliary_data_available =782 phm->u.d.u.buffer.pci_address;783 784 if (err) {785 hpios_locked_mem_free(&phw->outstream_host_buffers786 [phm->obj_index]);787 phw->outstream_host_buffer_size[phm->obj_index] = 0;788 phr->error = HPI_ERROR_MEMORY_ALLOC;789 return;790 }791 }792 793 if (command == HPI_BUFFER_CMD_EXTERNAL794 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {795 /* GRANT phase. Set up the BBM status, tell the DSP about796 the buffer so it can start using BBM.797 */798 struct hpi_hostbuffer_status *status;799 800 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.801 buffer_size - 1)) {802 HPI_DEBUG_LOG(ERROR,803 "Buffer size must be 2^N not %d\n",804 phm->u.d.u.buffer.buffer_size);805 phr->error = HPI_ERROR_INVALID_DATASIZE;806 return;807 }808 phw->outstream_host_buffer_size[phm->obj_index] =809 phm->u.d.u.buffer.buffer_size;810 status = &interface->outstream_host_buffer_status[phm->811 obj_index];812 status->samples_processed = 0;813 status->stream_state = HPI_STATE_STOPPED;814 status->dsp_index = 0;815 status->host_index = status->dsp_index;816 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;817 status->auxiliary_data_available = 0;818 819 hw_message(pao, phm, phr);820 821 if (phr->error822 && hpios_locked_mem_valid(&phw->823 outstream_host_buffers[phm->obj_index])) {824 hpios_locked_mem_free(&phw->outstream_host_buffers825 [phm->obj_index]);826 phw->outstream_host_buffer_size[phm->obj_index] = 0;827 }828 }829}830 831static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,832 struct hpi_message *phm, struct hpi_response *phr)833{834 struct hpi_hw_obj *phw = pao->priv;835 struct bus_master_interface *interface = phw->p_interface_buffer;836 struct hpi_hostbuffer_status *status;837 u8 *p_bbm_data;838 839 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->840 obj_index])) {841 if (hpios_locked_mem_get_virt_addr(&phw->842 outstream_host_buffers[phm->obj_index],843 (void *)&p_bbm_data)) {844 phr->error = HPI_ERROR_INVALID_OPERATION;845 return;846 }847 status = &interface->outstream_host_buffer_status[phm->848 obj_index];849 hpi_init_response(phr, HPI_OBJ_OSTREAM,850 HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);851 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;852 phr->u.d.u.hostbuffer_info.p_status = status;853 } else {854 hpi_init_response(phr, HPI_OBJ_OSTREAM,855 HPI_OSTREAM_HOSTBUFFER_GET_INFO,856 HPI_ERROR_INVALID_OPERATION);857 }858}859 860static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,861 struct hpi_message *phm, struct hpi_response *phr)862{863 struct hpi_hw_obj *phw = pao->priv;864 u32 command = phm->u.d.u.buffer.command;865 866 if (phw->outstream_host_buffer_size[phm->obj_index]) {867 if (command == HPI_BUFFER_CMD_EXTERNAL868 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {869 phw->outstream_host_buffer_size[phm->obj_index] = 0;870 hw_message(pao, phm, phr);871 /* Tell adapter to stop using the host buffer. */872 }873 if (command == HPI_BUFFER_CMD_EXTERNAL874 || command == HPI_BUFFER_CMD_INTERNAL_FREE)875 hpios_locked_mem_free(&phw->outstream_host_buffers876 [phm->obj_index]);877 }878 /* Should HPI_ERROR_INVALID_OPERATION be returned879 if no host buffer is allocated? */880 else881 hpi_init_response(phr, HPI_OBJ_OSTREAM,882 HPI_OSTREAM_HOSTBUFFER_FREE, 0);883 884}885 886static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)887{888 return status->size_in_bytes - (status->host_index -889 status->dsp_index);890}891 892static void outstream_write(struct hpi_adapter_obj *pao,893 struct hpi_message *phm, struct hpi_response *phr)894{895 struct hpi_hw_obj *phw = pao->priv;896 struct bus_master_interface *interface = phw->p_interface_buffer;897 struct hpi_hostbuffer_status *status;898 u32 space_available;899 900 if (!phw->outstream_host_buffer_size[phm->obj_index]) {901 /* there is no BBM buffer, write via message */902 hw_message(pao, phm, phr);903 return;904 }905 906 hpi_init_response(phr, phm->object, phm->function, 0);907 status = &interface->outstream_host_buffer_status[phm->obj_index];908 909 space_available = outstream_get_space_available(status);910 if (space_available < phm->u.d.u.data.data_size) {911 phr->error = HPI_ERROR_INVALID_DATASIZE;912 return;913 }914 915 /* HostBuffers is used to indicate host buffer is internally allocated.916 otherwise, assumed external, data written externally */917 if (phm->u.d.u.data.pb_data918 && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->919 obj_index])) {920 u8 *p_bbm_data;921 u32 l_first_write;922 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;923 924 if (hpios_locked_mem_get_virt_addr(&phw->925 outstream_host_buffers[phm->obj_index],926 (void *)&p_bbm_data)) {927 phr->error = HPI_ERROR_INVALID_OPERATION;928 return;929 }930 931 /* either all data,932 or enough to fit from current to end of BBM buffer */933 l_first_write =934 min(phm->u.d.u.data.data_size,935 status->size_in_bytes -936 (status->host_index & (status->size_in_bytes - 1)));937 938 memcpy(p_bbm_data +939 (status->host_index & (status->size_in_bytes - 1)),940 p_app_data, l_first_write);941 /* remaining data if any */942 memcpy(p_bbm_data, p_app_data + l_first_write,943 phm->u.d.u.data.data_size - l_first_write);944 }945 946 /*947 * This version relies on the DSP code triggering an OStream buffer948 * update immediately following a SET_FORMAT call. The host has949 * already written data into the BBM buffer, but the DSP won't know950 * about it until dwHostIndex is adjusted.951 */952 if (phw->flag_outstream_just_reset[phm->obj_index]) {953 /* Format can only change after reset. Must tell DSP. */954 u16 function = phm->function;955 phw->flag_outstream_just_reset[phm->obj_index] = 0;956 phm->function = HPI_OSTREAM_SET_FORMAT;957 hw_message(pao, phm, phr); /* send the format to the DSP */958 phm->function = function;959 if (phr->error)960 return;961 }962 963 status->host_index += phm->u.d.u.data.data_size;964}965 966static void outstream_get_info(struct hpi_adapter_obj *pao,967 struct hpi_message *phm, struct hpi_response *phr)968{969 struct hpi_hw_obj *phw = pao->priv;970 struct bus_master_interface *interface = phw->p_interface_buffer;971 struct hpi_hostbuffer_status *status;972 973 if (!phw->outstream_host_buffer_size[phm->obj_index]) {974 hw_message(pao, phm, phr);975 return;976 }977 978 hpi_init_response(phr, phm->object, phm->function, 0);979 980 status = &interface->outstream_host_buffer_status[phm->obj_index];981 982 phr->u.d.u.stream_info.state = (u16)status->stream_state;983 phr->u.d.u.stream_info.samples_transferred =984 status->samples_processed;985 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;986 phr->u.d.u.stream_info.data_available =987 status->size_in_bytes - outstream_get_space_available(status);988 phr->u.d.u.stream_info.auxiliary_data_available =989 status->auxiliary_data_available;990}991 992static void outstream_start(struct hpi_adapter_obj *pao,993 struct hpi_message *phm, struct hpi_response *phr)994{995 hw_message(pao, phm, phr);996}997 998static void outstream_reset(struct hpi_adapter_obj *pao,999 struct hpi_message *phm, struct hpi_response *phr)1000{1001 struct hpi_hw_obj *phw = pao->priv;1002 phw->flag_outstream_just_reset[phm->obj_index] = 1;1003 hw_message(pao, phm, phr);1004}1005 1006static void outstream_open(struct hpi_adapter_obj *pao,1007 struct hpi_message *phm, struct hpi_response *phr)1008{1009 outstream_reset(pao, phm, phr);1010}1011 1012/*****************************************************************************/1013/* InStream Host buffer functions */1014 1015static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,1016 struct hpi_message *phm, struct hpi_response *phr)1017{1018 u16 err = 0;1019 u32 command = phm->u.d.u.buffer.command;1020 struct hpi_hw_obj *phw = pao->priv;1021 struct bus_master_interface *interface = phw->p_interface_buffer;1022 1023 hpi_init_response(phr, phm->object, phm->function, 0);1024 1025 if (command == HPI_BUFFER_CMD_EXTERNAL1026 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {1027 1028 phm->u.d.u.buffer.buffer_size =1029 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);1030 phr->u.d.u.stream_info.data_available =1031 phw->instream_host_buffer_size[phm->obj_index];1032 phr->u.d.u.stream_info.buffer_size =1033 phm->u.d.u.buffer.buffer_size;1034 1035 if (phw->instream_host_buffer_size[phm->obj_index] ==1036 phm->u.d.u.buffer.buffer_size) {1037 /* Same size, no action required */1038 return;1039 }1040 1041 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->1042 obj_index]))1043 hpios_locked_mem_free(&phw->instream_host_buffers1044 [phm->obj_index]);1045 1046 err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->1047 obj_index], phm->u.d.u.buffer.buffer_size,1048 pao->pci.pci_dev);1049 1050 if (err) {1051 phr->error = HPI_ERROR_INVALID_DATASIZE;1052 phw->instream_host_buffer_size[phm->obj_index] = 0;1053 return;1054 }1055 1056 err = hpios_locked_mem_get_phys_addr1057 (&phw->instream_host_buffers[phm->obj_index],1058 &phm->u.d.u.buffer.pci_address);1059 /* get the phys addr into msg for single call alloc. Caller1060 needs to do this for split alloc so return the phy address */1061 phr->u.d.u.stream_info.auxiliary_data_available =1062 phm->u.d.u.buffer.pci_address;1063 if (err) {1064 hpios_locked_mem_free(&phw->instream_host_buffers1065 [phm->obj_index]);1066 phw->instream_host_buffer_size[phm->obj_index] = 0;1067 phr->error = HPI_ERROR_MEMORY_ALLOC;1068 return;1069 }1070 }1071 1072 if (command == HPI_BUFFER_CMD_EXTERNAL1073 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {1074 struct hpi_hostbuffer_status *status;1075 1076 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.1077 buffer_size - 1)) {1078 HPI_DEBUG_LOG(ERROR,1079 "Buffer size must be 2^N not %d\n",1080 phm->u.d.u.buffer.buffer_size);1081 phr->error = HPI_ERROR_INVALID_DATASIZE;1082 return;1083 }1084 1085 phw->instream_host_buffer_size[phm->obj_index] =1086 phm->u.d.u.buffer.buffer_size;1087 status = &interface->instream_host_buffer_status[phm->1088 obj_index];1089 status->samples_processed = 0;1090 status->stream_state = HPI_STATE_STOPPED;1091 status->dsp_index = 0;1092 status->host_index = status->dsp_index;1093 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;1094 status->auxiliary_data_available = 0;1095 1096 hw_message(pao, phm, phr);1097 1098 if (phr->error1099 && hpios_locked_mem_valid(&phw->1100 instream_host_buffers[phm->obj_index])) {1101 hpios_locked_mem_free(&phw->instream_host_buffers1102 [phm->obj_index]);1103 phw->instream_host_buffer_size[phm->obj_index] = 0;1104 }1105 }1106}1107 1108static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,1109 struct hpi_message *phm, struct hpi_response *phr)1110{1111 struct hpi_hw_obj *phw = pao->priv;1112 struct bus_master_interface *interface = phw->p_interface_buffer;1113 struct hpi_hostbuffer_status *status;1114 u8 *p_bbm_data;1115 1116 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->1117 obj_index])) {1118 if (hpios_locked_mem_get_virt_addr(&phw->1119 instream_host_buffers[phm->obj_index],1120 (void *)&p_bbm_data)) {1121 phr->error = HPI_ERROR_INVALID_OPERATION;1122 return;1123 }1124 status = &interface->instream_host_buffer_status[phm->1125 obj_index];1126 hpi_init_response(phr, HPI_OBJ_ISTREAM,1127 HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);1128 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;1129 phr->u.d.u.hostbuffer_info.p_status = status;1130 } else {1131 hpi_init_response(phr, HPI_OBJ_ISTREAM,1132 HPI_ISTREAM_HOSTBUFFER_GET_INFO,1133 HPI_ERROR_INVALID_OPERATION);1134 }1135}1136 1137static void instream_host_buffer_free(struct hpi_adapter_obj *pao,1138 struct hpi_message *phm, struct hpi_response *phr)1139{1140 struct hpi_hw_obj *phw = pao->priv;1141 u32 command = phm->u.d.u.buffer.command;1142 1143 if (phw->instream_host_buffer_size[phm->obj_index]) {1144 if (command == HPI_BUFFER_CMD_EXTERNAL1145 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {1146 phw->instream_host_buffer_size[phm->obj_index] = 0;1147 hw_message(pao, phm, phr);1148 }1149 1150 if (command == HPI_BUFFER_CMD_EXTERNAL1151 || command == HPI_BUFFER_CMD_INTERNAL_FREE)1152 hpios_locked_mem_free(&phw->instream_host_buffers1153 [phm->obj_index]);1154 1155 } else {1156 /* Should HPI_ERROR_INVALID_OPERATION be returned1157 if no host buffer is allocated? */1158 hpi_init_response(phr, HPI_OBJ_ISTREAM,1159 HPI_ISTREAM_HOSTBUFFER_FREE, 0);1160 1161 }1162 1163}1164 1165static void instream_start(struct hpi_adapter_obj *pao,1166 struct hpi_message *phm, struct hpi_response *phr)1167{1168 hw_message(pao, phm, phr);1169}1170 1171static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)1172{1173 return status->dsp_index - status->host_index;1174}1175 1176static void instream_read(struct hpi_adapter_obj *pao,1177 struct hpi_message *phm, struct hpi_response *phr)1178{1179 struct hpi_hw_obj *phw = pao->priv;1180 struct bus_master_interface *interface = phw->p_interface_buffer;1181 struct hpi_hostbuffer_status *status;1182 u32 data_available;1183 u8 *p_bbm_data;1184 u32 l_first_read;1185 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;1186 1187 if (!phw->instream_host_buffer_size[phm->obj_index]) {1188 hw_message(pao, phm, phr);1189 return;1190 }1191 hpi_init_response(phr, phm->object, phm->function, 0);1192 1193 status = &interface->instream_host_buffer_status[phm->obj_index];1194 data_available = instream_get_bytes_available(status);1195 if (data_available < phm->u.d.u.data.data_size) {1196 phr->error = HPI_ERROR_INVALID_DATASIZE;1197 return;1198 }1199 1200 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->1201 obj_index])) {1202 if (hpios_locked_mem_get_virt_addr(&phw->1203 instream_host_buffers[phm->obj_index],1204 (void *)&p_bbm_data)) {1205 phr->error = HPI_ERROR_INVALID_OPERATION;1206 return;1207 }1208 1209 /* either all data,1210 or enough to fit from current to end of BBM buffer */1211 l_first_read =1212 min(phm->u.d.u.data.data_size,1213 status->size_in_bytes -1214 (status->host_index & (status->size_in_bytes - 1)));1215 1216 memcpy(p_app_data,1217 p_bbm_data +1218 (status->host_index & (status->size_in_bytes - 1)),1219 l_first_read);1220 /* remaining data if any */1221 memcpy(p_app_data + l_first_read, p_bbm_data,1222 phm->u.d.u.data.data_size - l_first_read);1223 }1224 status->host_index += phm->u.d.u.data.data_size;1225}1226 1227static void instream_get_info(struct hpi_adapter_obj *pao,1228 struct hpi_message *phm, struct hpi_response *phr)1229{1230 struct hpi_hw_obj *phw = pao->priv;1231 struct bus_master_interface *interface = phw->p_interface_buffer;1232 struct hpi_hostbuffer_status *status;1233 if (!phw->instream_host_buffer_size[phm->obj_index]) {1234 hw_message(pao, phm, phr);1235 return;1236 }1237 1238 status = &interface->instream_host_buffer_status[phm->obj_index];1239 1240 hpi_init_response(phr, phm->object, phm->function, 0);1241 1242 phr->u.d.u.stream_info.state = (u16)status->stream_state;1243 phr->u.d.u.stream_info.samples_transferred =1244 status->samples_processed;1245 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;1246 phr->u.d.u.stream_info.data_available =1247 instream_get_bytes_available(status);1248 phr->u.d.u.stream_info.auxiliary_data_available =1249 status->auxiliary_data_available;1250}1251 1252/*****************************************************************************/1253/* LOW-LEVEL */1254#define HPI6205_MAX_FILES_TO_LOAD 21255 1256static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,1257 u32 *pos_error_code)1258{1259 struct hpi_hw_obj *phw = pao->priv;1260 struct dsp_code dsp_code;1261 u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];1262 u32 temp;1263 int dsp = 0, i = 0;1264 u16 err = 0;1265 1266 boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);1267 1268 boot_code_id[1] = pao->pci.pci_dev->subsystem_device;1269 boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]);1270 1271 /* fix up cases where bootcode id[1] != subsys id */1272 switch (boot_code_id[1]) {1273 case HPI_ADAPTER_FAMILY_ASI(0x5000):1274 boot_code_id[0] = boot_code_id[1];1275 boot_code_id[1] = 0;1276 break;1277 case HPI_ADAPTER_FAMILY_ASI(0x5300):1278 case HPI_ADAPTER_FAMILY_ASI(0x5400):1279 case HPI_ADAPTER_FAMILY_ASI(0x6300):1280 boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400);1281 break;1282 case HPI_ADAPTER_FAMILY_ASI(0x5500):1283 case HPI_ADAPTER_FAMILY_ASI(0x5600):1284 case HPI_ADAPTER_FAMILY_ASI(0x6500):1285 boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600);1286 break;1287 case HPI_ADAPTER_FAMILY_ASI(0x8800):1288 boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900);1289 break;1290 default:1291 break;1292 }1293 1294 /* reset DSP by writing a 1 to the WARMRESET bit */1295 temp = C6205_HDCR_WARMRESET;1296 iowrite32(temp, phw->prHDCR);1297 hpios_delay_micro_seconds(1000);1298 1299 /* check that PCI i/f was configured by EEPROM */1300 temp = ioread32(phw->prHSR);1301 if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=1302 C6205_HSR_EEREAD)1303 return HPI6205_ERROR_6205_EEPROM;1304 temp |= 0x04;1305 /* disable PINTA interrupt */1306 iowrite32(temp, phw->prHSR);1307 1308 /* check control register reports PCI boot mode */1309 temp = ioread32(phw->prHDCR);1310 if (!(temp & C6205_HDCR_PCIBOOT))1311 return HPI6205_ERROR_6205_REG;1312 1313 /* try writing a few numbers to the DSP page register */1314 /* and reading them back. */1315 temp = 3;1316 iowrite32(temp, phw->prDSPP);1317 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))1318 return HPI6205_ERROR_6205_DSPPAGE;1319 temp = 2;1320 iowrite32(temp, phw->prDSPP);1321 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))1322 return HPI6205_ERROR_6205_DSPPAGE;1323 temp = 1;1324 iowrite32(temp, phw->prDSPP);1325 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))1326 return HPI6205_ERROR_6205_DSPPAGE;1327 /* reset DSP page to the correct number */1328 temp = 0;1329 iowrite32(temp, phw->prDSPP);1330 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))1331 return HPI6205_ERROR_6205_DSPPAGE;1332 phw->dsp_page = 0;1333 1334 /* release 6713 from reset before 6205 is bootloaded.1335 This ensures that the EMIF is inactive,1336 and the 6713 HPI gets the correct bootmode etc1337 */1338 if (boot_code_id[1] != 0) {1339 /* DSP 1 is a C6713 */1340 /* CLKX0 <- '1' release the C6205 bootmode pulldowns */1341 boot_loader_write_mem32(pao, 0, 0x018C0024, 0x00002202);1342 hpios_delay_micro_seconds(100);1343 /* Reset the 6713 #1 - revB */1344 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);1345 /* value of bit 3 is unknown after DSP reset, other bits shoudl be 0 */1346 if (0 != (boot_loader_read_mem32(pao, 0,1347 (C6205_BAR0_TIMER1_CTL)) & ~8))1348 return HPI6205_ERROR_6205_REG;1349 hpios_delay_micro_seconds(100);1350 1351 /* Release C6713 from reset - revB */1352 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);1353 if (4 != (boot_loader_read_mem32(pao, 0,1354 (C6205_BAR0_TIMER1_CTL)) & ~8))1355 return HPI6205_ERROR_6205_REG;1356 hpios_delay_micro_seconds(100);1357 }1358 1359 for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {1360 /* is there a DSP to load? */1361 if (boot_code_id[dsp] == 0)1362 continue;1363 1364 err = boot_loader_config_emif(pao, dsp);1365 if (err)1366 return err;1367 1368 err = boot_loader_test_internal_memory(pao, dsp);1369 if (err)1370 return err;1371 1372 err = boot_loader_test_external_memory(pao, dsp);1373 if (err)1374 return err;1375 1376 err = boot_loader_test_pld(pao, dsp);1377 if (err)1378 return err;1379 1380 /* write the DSP code down into the DSPs memory */1381 err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev,1382 &dsp_code, pos_error_code);1383 if (err)1384 return err;1385 1386 while (1) {1387 u32 length;1388 u32 address;1389 u32 type;1390 u32 *pcode;1391 1392 err = hpi_dsp_code_read_word(&dsp_code, &length);1393 if (err)1394 break;1395 if (length == 0xFFFFFFFF)1396 break; /* end of code */1397 1398 err = hpi_dsp_code_read_word(&dsp_code, &address);1399 if (err)1400 break;1401 err = hpi_dsp_code_read_word(&dsp_code, &type);1402 if (err)1403 break;1404 err = hpi_dsp_code_read_block(length, &dsp_code,1405 &pcode);1406 if (err)1407 break;1408 for (i = 0; i < (int)length; i++) {1409 boot_loader_write_mem32(pao, dsp, address,1410 *pcode);1411 /* dummy read every 4 words */1412 /* for 6205 advisory 1.4.4 */1413 if (i % 4 == 0)1414 boot_loader_read_mem32(pao, dsp,1415 address);1416 pcode++;1417 address += 4;1418 }1419 1420 }1421 if (err) {1422 hpi_dsp_code_close(&dsp_code);1423 return err;1424 }1425 1426 /* verify code */1427 hpi_dsp_code_rewind(&dsp_code);1428 while (1) {1429 u32 length = 0;1430 u32 address = 0;1431 u32 type = 0;1432 u32 *pcode = NULL;1433 u32 data = 0;1434 1435 hpi_dsp_code_read_word(&dsp_code, &length);1436 if (length == 0xFFFFFFFF)1437 break; /* end of code */1438 1439 hpi_dsp_code_read_word(&dsp_code, &address);1440 hpi_dsp_code_read_word(&dsp_code, &type);1441 hpi_dsp_code_read_block(length, &dsp_code, &pcode);1442 1443 for (i = 0; i < (int)length; i++) {1444 data = boot_loader_read_mem32(pao, dsp,1445 address);1446 if (data != *pcode) {1447 err = 0;1448 break;1449 }1450 pcode++;1451 address += 4;1452 }1453 if (err)1454 break;1455 }1456 hpi_dsp_code_close(&dsp_code);1457 if (err)1458 return err;1459 }1460 1461 /* After bootloading all DSPs, start DSP0 running1462 * The DSP0 code will handle starting and synchronizing with its slaves1463 */1464 if (phw->p_interface_buffer) {1465 /* we need to tell the card the physical PCI address */1466 u32 physicalPC_iaddress;1467 struct bus_master_interface *interface =1468 phw->p_interface_buffer;1469 u32 host_mailbox_address_on_dsp;1470 u32 physicalPC_iaddress_verify = 0;1471 int time_out = 10;1472 /* set ack so we know when DSP is ready to go */1473 /* (dwDspAck will be changed to HIF_RESET) */1474 interface->dsp_ack = H620_HIF_UNKNOWN;1475 wmb(); /* ensure ack is written before dsp writes back */1476 1477 err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,1478 &physicalPC_iaddress);1479 1480 /* locate the host mailbox on the DSP. */1481 host_mailbox_address_on_dsp = 0x80000000;1482 while ((physicalPC_iaddress != physicalPC_iaddress_verify)1483 && time_out--) {1484 boot_loader_write_mem32(pao, 0,1485 host_mailbox_address_on_dsp,1486 physicalPC_iaddress);1487 physicalPC_iaddress_verify =1488 boot_loader_read_mem32(pao, 0,1489 host_mailbox_address_on_dsp);1490 }1491 }1492 HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");1493 /* enable interrupts */1494 temp = ioread32(phw->prHSR);1495 temp &= ~(u32)C6205_HSR_INTAM;1496 iowrite32(temp, phw->prHSR);1497 1498 /* start code running... */1499 temp = ioread32(phw->prHDCR);1500 temp |= (u32)C6205_HDCR_DSPINT;1501 iowrite32(temp, phw->prHDCR);1502 1503 /* give the DSP 10ms to start up */1504 hpios_delay_micro_seconds(10000);1505 return err;1506 1507}1508 1509/*****************************************************************************/1510/* Bootloader utility functions */1511 1512static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,1513 u32 address)1514{1515 struct hpi_hw_obj *phw = pao->priv;1516 u32 data = 0;1517 __iomem u32 *p_data;1518 1519 if (dsp_index == 0) {1520 /* DSP 0 is always C6205 */1521 if ((address >= 0x01800000) & (address < 0x02000000)) {1522 /* BAR1 register access */1523 p_data = pao->pci.ap_mem_base[1] +1524 (address & 0x007fffff) /1525 sizeof(*pao->pci.ap_mem_base[1]);1526 /* HPI_DEBUG_LOG(WARNING,1527 "BAR1 access %08x\n", dwAddress); */1528 } else {1529 u32 dw4M_page = address >> 22L;1530 if (dw4M_page != phw->dsp_page) {1531 phw->dsp_page = dw4M_page;1532 /* *INDENT OFF* */1533 iowrite32(phw->dsp_page, phw->prDSPP);1534 /* *INDENT-ON* */1535 }1536 address &= 0x3fffff; /* address within 4M page */1537 /* BAR0 memory access */1538 p_data = pao->pci.ap_mem_base[0] +1539 address / sizeof(u32);1540 }1541 data = ioread32(p_data);1542 } else if (dsp_index == 1) {1543 /* DSP 1 is a C6713 */1544 u32 lsb;1545 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);1546 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);1547 lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);1548 data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);1549 data = (data << 16) | (lsb & 0xFFFF);1550 }1551 return data;1552}1553 1554static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,1555 int dsp_index, u32 address, u32 data)1556{1557 struct hpi_hw_obj *phw = pao->priv;1558 __iomem u32 *p_data;1559 /* u32 dwVerifyData=0; */1560 1561 if (dsp_index == 0) {1562 /* DSP 0 is always C6205 */1563 if ((address >= 0x01800000) & (address < 0x02000000)) {1564 /* BAR1 - DSP register access using */1565 /* Non-prefetchable PCI access */1566 p_data = pao->pci.ap_mem_base[1] +1567 (address & 0x007fffff) /1568 sizeof(*pao->pci.ap_mem_base[1]);1569 } else {1570 /* BAR0 access - all of DSP memory using */1571 /* pre-fetchable PCI access */1572 u32 dw4M_page = address >> 22L;1573 if (dw4M_page != phw->dsp_page) {1574 phw->dsp_page = dw4M_page;1575 /* *INDENT-OFF* */1576 iowrite32(phw->dsp_page, phw->prDSPP);1577 /* *INDENT-ON* */1578 }1579 address &= 0x3fffff; /* address within 4M page */1580 p_data = pao->pci.ap_mem_base[0] +1581 address / sizeof(u32);1582 }1583 iowrite32(data, p_data);1584 } else if (dsp_index == 1) {1585 /* DSP 1 is a C6713 */1586 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);1587 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);1588 1589 /* dummy read every 4 words for 6205 advisory 1.4.4 */1590 boot_loader_read_mem32(pao, 0, 0);1591 1592 boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);1593 boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);1594 1595 /* dummy read every 4 words for 6205 advisory 1.4.4 */1596 boot_loader_read_mem32(pao, 0, 0);1597 }1598}1599 1600static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)1601{1602 if (dsp_index == 0) {1603 u32 setting;1604 1605 /* DSP 0 is always C6205 */1606 1607 /* Set the EMIF */1608 /* memory map of C6205 */1609 /* 00000000-0000FFFF 16Kx32 internal program */1610 /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */1611 1612 /* EMIF config */1613 /*------------ */1614 /* Global EMIF control */1615 boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);1616#define WS_OFS 281617#define WST_OFS 221618#define WH_OFS 201619#define RS_OFS 161620#define RST_OFS 81621#define MTYPE_OFS 41622#define RH_OFS 01623 1624 /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */1625 setting = 0x00000030;1626 boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);1627 if (setting != boot_loader_read_mem32(pao, dsp_index,1628 0x01800008))1629 return HPI6205_ERROR_DSP_EMIF1;1630 1631 /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */1632 /* which occupies D15..0. 6713 starts at 27MHz, so need */1633 /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */1634 /* WST should be 71, but 63 is max possible */1635 setting =1636 (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |1637 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |1638 (2L << MTYPE_OFS);1639 boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);1640 if (setting != boot_loader_read_mem32(pao, dsp_index,1641 0x01800004))1642 return HPI6205_ERROR_DSP_EMIF2;1643 1644 /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */1645 /* which occupies D15..0. 6713 starts at 27MHz, so need */1646 /* plenty of wait states */1647 setting =1648 (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |1649 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |1650 (2L << MTYPE_OFS);1651 boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);1652 if (setting != boot_loader_read_mem32(pao, dsp_index,1653 0x01800010))1654 return HPI6205_ERROR_DSP_EMIF3;1655 1656 /* EMIF CE3 setup - 32 bit async. */1657 /* This is the PLD on the ASI5000 cards only */1658 setting =1659 (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |1660 (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |1661 (2L << MTYPE_OFS);1662 boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);1663 if (setting != boot_loader_read_mem32(pao, dsp_index,1664 0x01800014))1665 return HPI6205_ERROR_DSP_EMIF4;1666 1667 /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */1668 /* need to use this else DSP code crashes? */1669 boot_loader_write_mem32(pao, dsp_index, 0x01800018,1670 0x07117000);1671 1672 /* EMIF SDRAM Refresh Timing */1673 /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */1674 boot_loader_write_mem32(pao, dsp_index, 0x0180001C,1675 0x00000410);1676 1677 } else if (dsp_index == 1) {1678 /* test access to the C6713s HPI registers */1679 u32 write_data = 0, read_data = 0, i = 0;1680 1681 /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */1682 write_data = 1;1683 boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);1684 boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);1685 /* C67 HPI is on lower 16bits of 32bit EMIF */1686 read_data =1687 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);1688 if (write_data != read_data) {1689 HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,1690 read_data);1691 return HPI6205_ERROR_C6713_HPIC;1692 }1693 /* HPIA - walking ones test */1694 write_data = 1;1695 for (i = 0; i < 32; i++) {1696 boot_loader_write_mem32(pao, 0, HPIAL_ADDR,1697 write_data);1698 boot_loader_write_mem32(pao, 0, HPIAH_ADDR,1699 (write_data >> 16));1700 read_data =1701 0xFFFF & boot_loader_read_mem32(pao, 0,1702 HPIAL_ADDR);1703 read_data =1704 read_data | ((0xFFFF &1705 boot_loader_read_mem32(pao, 0,1706 HPIAH_ADDR))1707 << 16);1708 if (read_data != write_data) {1709 HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",1710 write_data, read_data);1711 return HPI6205_ERROR_C6713_HPIA;1712 }1713 write_data = write_data << 1;1714 }1715 1716 /* setup C67x PLL1717 * ** C6713 datasheet says we cannot program PLL from HPI,1718 * and indeed if we try to set the PLL multiply from the HPI,1719 * the PLL does not seem to lock, so we enable the PLL and1720 * use the default multiply of x 7, which for a 27MHz clock1721 * gives a DSP speed of 189MHz1722 */1723 /* bypass PLL */1724 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);1725 hpios_delay_micro_seconds(1000);1726 /* EMIF = 189/3=63MHz */1727 boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);1728 /* peri = 189/2 */1729 boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);1730 /* cpu = 189/1 */1731 boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);1732 hpios_delay_micro_seconds(1000);1733 /* ** SGT test to take GPO3 high when we start the PLL */1734 /* and low when the delay is completed */1735 /* FSX0 <- '1' (GPO3) */1736 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);1737 /* PLL not bypassed */1738 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);1739 hpios_delay_micro_seconds(1000);1740 /* FSX0 <- '0' (GPO3) */1741 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);1742 1743 /* 6205 EMIF CE1 resetup - 32 bit async. */1744 /* Now 6713 #1 is running at 189MHz can reduce waitstates */1745 boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */1746 (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |1747 (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |1748 (2L << MTYPE_OFS));1749 1750 hpios_delay_micro_seconds(1000);1751 1752 /* check that we can read one of the PLL registers */1753 /* PLL should not be bypassed! */1754 if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)1755 != 0x0001) {1756 return HPI6205_ERROR_C6713_PLL;1757 }1758 /* setup C67x EMIF (note this is the only use of1759 BAR1 via BootLoader_WriteMem32) */1760 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,1761 0x000034A8);1762 1763 /* EMIF CE0 setup - 2Mx32 Sync DRAM1764 31..28 Wr setup1765 27..22 Wr strobe1766 21..20 Wr hold1767 19..16 Rd setup1768 15..14 -1769 13..8 Rd strobe1770 7..4 MTYPE 0011 Sync DRAM 32bits1771 3 Wr hold MSB1772 2..0 Rd hold1773 */1774 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,1775 0x00000030);1776 1777 /* EMIF SDRAM Extension1778 0x001779 31-21 0000b 0000b 000b1780 20 WR2RD = 2cycles-1 = 1b1781 1782 19-18 WR2DEAC = 3cycle-1 = 10b1783 17 WR2WR = 2cycle-1 = 1b1784 16-15 R2WDQM = 4cycle-1 = 11b1785 14-12 RD2WR = 6cycles-1 = 101b1786 1787 11-10 RD2DEAC = 4cycle-1 = 11b1788 9 RD2RD = 2cycle-1 = 1b1789 8-7 THZP = 3cycle-1 = 10b1790 6-5 TWR = 2cycle-1 = 01b (tWR = 17ns)1791 4 TRRD = 2cycle = 0b (tRRD = 14ns)1792 3-1 TRAS = 5cycle-1 = 100b (Tras=42ns)1793 1 CAS latency = 3cyc = 1b1794 (for Micron 2M32-7 operating at 100MHz)1795 */1796 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,1797 0x001BDF29);1798 1799 /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)1800 31 - 0b -1801 30 SDBSZ 1b 4 bank1802 29..28 SDRSZ 00b 11 row address pins1803 1804 27..26 SDCSZ 01b 8 column address pins1805 25 RFEN 1b refersh enabled1806 24 INIT 1b init SDRAM!1807 1808 23..20 TRCD 0001b (Trcd/Tcyc)-1 = (20/10)-1 = 11809 1810 19..16 TRP 0001b (Trp/Tcyc)-1 = (20/10)-1 = 11811 1812 15..12 TRC 0110b (Trc/Tcyc)-1 = (70/10)-1 = 61813 1814 11..0 - 0000b 0000b 0000b1815 */1816 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,1817 0x47116000);1818 1819 /* SDRAM refresh timing1820 Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A1821 */1822 boot_loader_write_mem32(pao, dsp_index,1823 C6713_EMIF_SDRAMTIMING, 0x00000410);1824 1825 hpios_delay_micro_seconds(1000);1826 } else if (dsp_index == 2) {1827 /* DSP 2 is a C6713 */1828 }1829 1830 return 0;1831}1832 1833static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,1834 u32 start_address, u32 length)1835{1836 u32 i = 0, j = 0;1837 u32 test_addr = 0;1838 u32 test_data = 0, data = 0;1839 1840 length = 1000;1841 1842 /* for 1st word, test each bit in the 32bit word, */1843 /* dwLength specifies number of 32bit words to test */1844 /*for(i=0; i<dwLength; i++) */1845 i = 0;1846 {1847 test_addr = start_address + i * 4;1848 test_data = 0x00000001;1849 for (j = 0; j < 32; j++) {1850 boot_loader_write_mem32(pao, dsp_index, test_addr,1851 test_data);1852 data = boot_loader_read_mem32(pao, dsp_index,1853 test_addr);1854 if (data != test_data) {1855 HPI_DEBUG_LOG(VERBOSE,1856 "Memtest error details "1857 "%08x %08x %08x %i\n", test_addr,1858 test_data, data, dsp_index);1859 return 1; /* error */1860 }1861 test_data = test_data << 1;1862 } /* for(j) */1863 } /* for(i) */1864 1865 /* for the next 100 locations test each location, leaving it as zero */1866 /* write a zero to the next word in memory before we read */1867 /* the previous write to make sure every memory location is unique */1868 for (i = 0; i < 100; i++) {1869 test_addr = start_address + i * 4;1870 test_data = 0xA5A55A5A;1871 boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);1872 boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);1873 data = boot_loader_read_mem32(pao, dsp_index, test_addr);1874 if (data != test_data) {1875 HPI_DEBUG_LOG(VERBOSE,1876 "Memtest error details "1877 "%08x %08x %08x %i\n", test_addr, test_data,1878 data, dsp_index);1879 return 1; /* error */1880 }1881 /* leave location as zero */1882 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);1883 }1884 1885 /* zero out entire memory block */1886 for (i = 0; i < length; i++) {1887 test_addr = start_address + i * 4;1888 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);1889 }1890 return 0;1891}1892 1893static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,1894 int dsp_index)1895{1896 int err = 0;1897 if (dsp_index == 0) {1898 /* DSP 0 is a C6205 */1899 /* 64K prog mem */1900 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,1901 0x10000);1902 if (!err)1903 /* 64K data mem */1904 err = boot_loader_test_memory(pao, dsp_index,1905 0x80000000, 0x10000);1906 } else if (dsp_index == 1) {1907 /* DSP 1 is a C6713 */1908 /* 192K internal mem */1909 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,1910 0x30000);1911 if (!err)1912 /* 64K internal mem / L2 cache */1913 err = boot_loader_test_memory(pao, dsp_index,1914 0x00030000, 0x10000);1915 }1916 1917 if (err)1918 return HPI6205_ERROR_DSP_INTMEM;1919 else1920 return 0;1921}1922 1923static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,1924 int dsp_index)1925{1926 u32 dRAM_start_address = 0;1927 u32 dRAM_size = 0;1928 1929 if (dsp_index == 0) {1930 /* only test for SDRAM if an ASI5000 card */1931 if (pao->pci.pci_dev->subsystem_device == 0x5000) {1932 /* DSP 0 is always C6205 */1933 dRAM_start_address = 0x00400000;1934 dRAM_size = 0x200000;1935 /*dwDRAMinc=1024; */1936 } else1937 return 0;1938 } else if (dsp_index == 1) {1939 /* DSP 1 is a C6713 */1940 dRAM_start_address = 0x80000000;1941 dRAM_size = 0x200000;1942 /*dwDRAMinc=1024; */1943 }1944 1945 if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,1946 dRAM_size))1947 return HPI6205_ERROR_DSP_EXTMEM;1948 return 0;1949}1950 1951static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)1952{1953 u32 data = 0;1954 if (dsp_index == 0) {1955 /* only test for DSP0 PLD on ASI5000 card */1956 if (pao->pci.pci_dev->subsystem_device == 0x5000) {1957 /* PLD is located at CE3=0x03000000 */1958 data = boot_loader_read_mem32(pao, dsp_index,1959 0x03000008);1960 if ((data & 0xF) != 0x5)1961 return HPI6205_ERROR_DSP_PLD;1962 data = boot_loader_read_mem32(pao, dsp_index,1963 0x0300000C);1964 if ((data & 0xF) != 0xA)1965 return HPI6205_ERROR_DSP_PLD;1966 }1967 } else if (dsp_index == 1) {1968 /* DSP 1 is a C6713 */1969 if (pao->pci.pci_dev->subsystem_device == 0x8700) {1970 /* PLD is located at CE1=0x90000000 */1971 data = boot_loader_read_mem32(pao, dsp_index,1972 0x90000010);1973 if ((data & 0xFF) != 0xAA)1974 return HPI6205_ERROR_DSP_PLD;1975 /* 8713 - LED on */1976 boot_loader_write_mem32(pao, dsp_index, 0x90000000,1977 0x02);1978 }1979 }1980 return 0;1981}1982 1983/** Transfer data to or from DSP1984 nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA1985*/1986static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,1987 u32 data_size, int operation)1988{1989 struct hpi_hw_obj *phw = pao->priv;1990 u32 data_transferred = 0;1991 u16 err = 0;1992 u32 temp2;1993 struct bus_master_interface *interface = phw->p_interface_buffer;1994 1995 if (!p_data)1996 return HPI_ERROR_INVALID_DATA_POINTER;1997 1998 data_size &= ~3L; /* round data_size down to nearest 4 bytes */1999 2000 /* make sure state is IDLE */2001 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))2002 return HPI_ERROR_DSP_HARDWARE;2003 2004 while (data_transferred < data_size) {2005 u32 this_copy = data_size - data_transferred;2006 2007 if (this_copy > HPI6205_SIZEOF_DATA)2008 this_copy = HPI6205_SIZEOF_DATA;2009 2010 if (operation == H620_HIF_SEND_DATA)2011 memcpy((void *)&interface->u.b_data[0],2012 &p_data[data_transferred], this_copy);2013 2014 interface->transfer_size_in_bytes = this_copy;2015 2016 /* DSP must change this back to nOperation */2017 interface->dsp_ack = H620_HIF_IDLE;2018 send_dsp_command(phw, operation);2019 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,2027 "Timed out waiting for " "state %d got %d\n",2028 operation, interface->dsp_ack);2029 2030 break;2031 }2032 if (operation == H620_HIF_GET_DATA)2033 memcpy(&p_data[data_transferred],2034 (void *)&interface->u.b_data[0], this_copy);2035 2036 data_transferred += this_copy;2037 }2038 if (interface->dsp_ack != operation)2039 HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",2040 interface->dsp_ack, operation);2041 /* err=HPI_ERROR_DSP_HARDWARE; */2042 2043 send_dsp_command(phw, H620_HIF_IDLE);2044 2045 return err;2046}2047 2048/* wait for up to timeout_us microseconds for the DSP2049 to signal state by DMA into dwDspAck2050*/2051static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)2052{2053 struct bus_master_interface *interface = phw->p_interface_buffer;2054 int t = timeout_us / 4;2055 2056 rmb(); /* ensure interface->dsp_ack is up to date */2057 while ((interface->dsp_ack != state) && --t) {2058 hpios_delay_micro_seconds(4);2059 rmb(); /* DSP changes dsp_ack by DMA */2060 }2061 2062 /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */2063 return t * 4;2064}2065 2066/* set the busmaster interface to cmd, then interrupt the DSP */2067static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)2068{2069 struct bus_master_interface *interface = phw->p_interface_buffer;2070 u32 r;2071 2072 interface->host_cmd = cmd;2073 wmb(); /* DSP gets state by DMA, make sure it is written to memory */2074 /* before we interrupt the DSP */2075 r = ioread32(phw->prHDCR);2076 r |= (u32)C6205_HDCR_DSPINT;2077 iowrite32(r, phw->prHDCR);2078 r &= ~(u32)C6205_HDCR_DSPINT;2079 iowrite32(r, phw->prHDCR);2080}2081 2082static unsigned int message_count;2083 2084static u16 message_response_sequence(struct hpi_adapter_obj *pao,2085 struct hpi_message *phm, struct hpi_response *phr)2086{2087 u32 time_out, time_out2;2088 struct hpi_hw_obj *phw = pao->priv;2089 struct bus_master_interface *interface = phw->p_interface_buffer;2090 u16 err = 0;2091 2092 message_count++;2093 if (phm->size > sizeof(interface->u.message_buffer)) {2094 phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;2095 phr->specific_error = sizeof(interface->u.message_buffer);2096 phr->size = sizeof(struct hpi_response_header);2097 HPI_DEBUG_LOG(ERROR,2098 "message len %d too big for buffer %zd \n", phm->size,2099 sizeof(interface->u.message_buffer));2100 return 0;2101 }2102 2103 /* Assume buffer of type struct bus_master_interface_622104 is allocated "noncacheable" */2105 2106 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {2107 HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");2108 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;2109 }2110 2111 memcpy(&interface->u.message_buffer, phm, phm->size);2112 /* signal we want a response */2113 send_dsp_command(phw, H620_HIF_GET_RESP);2114 2115 time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);2116 2117 if (!time_out2) {2118 HPI_DEBUG_LOG(ERROR,2119 "(%u) Timed out waiting for " "GET_RESP state [%x]\n",2120 message_count, interface->dsp_ack);2121 } else {2122 HPI_DEBUG_LOG(VERBOSE,2123 "(%u) transition to GET_RESP after %u\n",2124 message_count, HPI6205_TIMEOUT - time_out2);2125 }2126 /* spin waiting on HIF interrupt flag (end of msg process) */2127 time_out = HPI6205_TIMEOUT;2128 2129 /* read the result */2130 if (time_out) {2131 if (interface->u.response_buffer.response.size <= phr->size)2132 memcpy(phr, &interface->u.response_buffer,2133 interface->u.response_buffer.response.size);2134 else {2135 HPI_DEBUG_LOG(ERROR,2136 "response len %d too big for buffer %d\n",2137 interface->u.response_buffer.response.size,2138 phr->size);2139 memcpy(phr, &interface->u.response_buffer,2140 sizeof(struct hpi_response_header));2141 phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;2142 phr->specific_error =2143 interface->u.response_buffer.response.size;2144 phr->size = sizeof(struct hpi_response_header);2145 }2146 }2147 /* set interface back to idle */2148 send_dsp_command(phw, H620_HIF_IDLE);2149 2150 if (!time_out || !time_out2) {2151 HPI_DEBUG_LOG(DEBUG, "something timed out!\n");2152 return HPI6205_ERROR_MSG_RESP_TIMEOUT;2153 }2154 /* special case for adapter close - */2155 /* wait for the DSP to indicate it is idle */2156 if (phm->function == HPI_ADAPTER_CLOSE) {2157 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {2158 HPI_DEBUG_LOG(DEBUG,2159 "Timeout waiting for idle "2160 "(on adapter_close)\n");2161 return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;2162 }2163 }2164 err = hpi_validate_response(phm, phr);2165 return err;2166}2167 2168static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,2169 struct hpi_response *phr)2170{2171 2172 u16 err = 0;2173 2174 hpios_dsplock_lock(pao);2175 2176 err = message_response_sequence(pao, phm, phr);2177 2178 /* maybe an error response */2179 if (err) {2180 /* something failed in the HPI/DSP interface */2181 if (err >= HPI_ERROR_BACKEND_BASE) {2182 phr->error = HPI_ERROR_DSP_COMMUNICATION;2183 phr->specific_error = err;2184 } else {2185 phr->error = err;2186 }2187 2188 pao->dsp_crashed++;2189 2190 /* just the header of the response is valid */2191 phr->size = sizeof(struct hpi_response_header);2192 goto err;2193 } else2194 pao->dsp_crashed = 0;2195 2196 if (phr->error != 0) /* something failed in the DSP */2197 goto err;2198 2199 switch (phm->function) {2200 case HPI_OSTREAM_WRITE:2201 case HPI_ISTREAM_ANC_WRITE:2202 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,2203 phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);2204 break;2205 2206 case HPI_ISTREAM_READ:2207 case HPI_OSTREAM_ANC_READ:2208 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,2209 phm->u.d.u.data.data_size, H620_HIF_GET_DATA);2210 break;2211 2212 }2213 phr->error = err;2214 2215err:2216 hpios_dsplock_unlock(pao);2217 2218 return;2219}2220