162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci AudioScience HPI driver 562306a36Sopenharmony_ci Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci Hardware Programming Interface (HPI) for AudioScience ASI6200 series adapters. 962306a36Sopenharmony_ci These PCI bus adapters are based on the TI C6711 DSP. 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci Exported functions: 1262306a36Sopenharmony_ci void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci #defines 1562306a36Sopenharmony_ci HIDE_PCI_ASSERTS to show the PCI asserts 1662306a36Sopenharmony_ci PROFILE_DSP2 get profile data from DSP2 if present (instead of DSP 1) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci(C) Copyright AudioScience Inc. 1998-2003 1962306a36Sopenharmony_ci*******************************************************************************/ 2062306a36Sopenharmony_ci#define SOURCEFILE_NAME "hpi6000.c" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "hpi_internal.h" 2362306a36Sopenharmony_ci#include "hpimsginit.h" 2462306a36Sopenharmony_ci#include "hpidebug.h" 2562306a36Sopenharmony_ci#include "hpi6000.h" 2662306a36Sopenharmony_ci#include "hpidspcd.h" 2762306a36Sopenharmony_ci#include "hpicmn.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define HPI_HIF_BASE (0x00000200) /* start of C67xx internal RAM */ 3062306a36Sopenharmony_ci#define HPI_HIF_ADDR(member) \ 3162306a36Sopenharmony_ci (HPI_HIF_BASE + offsetof(struct hpi_hif_6000, member)) 3262306a36Sopenharmony_ci#define HPI_HIF_ERROR_MASK 0x4000 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* HPI6000 specific error codes */ 3562306a36Sopenharmony_ci#define HPI6000_ERROR_BASE 900 /* not actually used anywhere */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* operational/messaging errors */ 3862306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 3962306a36Sopenharmony_ci#define HPI6000_ERROR_RESP_GET_LEN 902 4062306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 4162306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_GET_ADR 904 4262306a36Sopenharmony_ci#define HPI6000_ERROR_RESP_GET_ADR 905 4362306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 4462306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 4962306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_ACK 912 5062306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_ADR 913 5162306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_TIMEOUT 914 5262306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_CMD 915 5362306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_WRITE 916 5462306a36Sopenharmony_ci#define HPI6000_ERROR_SEND_DATA_IDLECMD 917 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 5762306a36Sopenharmony_ci#define HPI6000_ERROR_GET_DATA_ACK 922 5862306a36Sopenharmony_ci#define HPI6000_ERROR_GET_DATA_CMD 923 5962306a36Sopenharmony_ci#define HPI6000_ERROR_GET_DATA_READ 924 6062306a36Sopenharmony_ci#define HPI6000_ERROR_GET_DATA_IDLECMD 925 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define HPI6000_ERROR_CONTROL_CACHE_ADDRLEN 951 6362306a36Sopenharmony_ci#define HPI6000_ERROR_CONTROL_CACHE_READ 952 6462306a36Sopenharmony_ci#define HPI6000_ERROR_CONTROL_CACHE_FLUSH 953 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 6762306a36Sopenharmony_ci#define HPI6000_ERROR_MSG_RESP_IDLECMD 962 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* Initialisation/bootload errors */ 7062306a36Sopenharmony_ci#define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* can't access PCI2040 */ 7362306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_PCI2040 931 7462306a36Sopenharmony_ci/* can't access DSP HPI i/f */ 7562306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_DSPHPI 932 7662306a36Sopenharmony_ci/* can't access internal DSP memory */ 7762306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_DSPINTMEM 933 7862306a36Sopenharmony_ci/* can't access SDRAM - test#1 */ 7962306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_SDRAM1 934 8062306a36Sopenharmony_ci/* can't access SDRAM - test#2 */ 8162306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_SDRAM2 935 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_VERIFY 938 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_NOACK 939 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_PLDTEST1 941 8862306a36Sopenharmony_ci#define HPI6000_ERROR_INIT_PLDTEST2 942 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* local defines */ 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define HIDE_PCI_ASSERTS 9362306a36Sopenharmony_ci#define PROFILE_DSP2 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* for PCI2040 i/f chip */ 9662306a36Sopenharmony_ci/* HPI CSR registers */ 9762306a36Sopenharmony_ci/* word offsets from CSR base */ 9862306a36Sopenharmony_ci/* use when io addresses defined as u32 * */ 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define INTERRUPT_EVENT_SET 0 10162306a36Sopenharmony_ci#define INTERRUPT_EVENT_CLEAR 1 10262306a36Sopenharmony_ci#define INTERRUPT_MASK_SET 2 10362306a36Sopenharmony_ci#define INTERRUPT_MASK_CLEAR 3 10462306a36Sopenharmony_ci#define HPI_ERROR_REPORT 4 10562306a36Sopenharmony_ci#define HPI_RESET 5 10662306a36Sopenharmony_ci#define HPI_DATA_WIDTH 6 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#define MAX_DSPS 2 10962306a36Sopenharmony_ci/* HPI registers, spaced 8K bytes = 2K words apart */ 11062306a36Sopenharmony_ci#define DSP_SPACING 0x800 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define CONTROL 0x0000 11362306a36Sopenharmony_ci#define ADDRESS 0x0200 11462306a36Sopenharmony_ci#define DATA_AUTOINC 0x0400 11562306a36Sopenharmony_ci#define DATA 0x0600 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define TIMEOUT 500000 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistruct dsp_obj { 12062306a36Sopenharmony_ci __iomem u32 *prHPI_control; 12162306a36Sopenharmony_ci __iomem u32 *prHPI_address; 12262306a36Sopenharmony_ci __iomem u32 *prHPI_data; 12362306a36Sopenharmony_ci __iomem u32 *prHPI_data_auto_inc; 12462306a36Sopenharmony_ci char c_dsp_rev; /*A, B */ 12562306a36Sopenharmony_ci u32 control_cache_address_on_dsp; 12662306a36Sopenharmony_ci u32 control_cache_length_on_dsp; 12762306a36Sopenharmony_ci struct hpi_adapter_obj *pa_parent_adapter; 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct hpi_hw_obj { 13162306a36Sopenharmony_ci __iomem u32 *dw2040_HPICSR; 13262306a36Sopenharmony_ci __iomem u32 *dw2040_HPIDSP; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci u16 num_dsp; 13562306a36Sopenharmony_ci struct dsp_obj ado[MAX_DSPS]; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci u32 message_buffer_address_on_dsp; 13862306a36Sopenharmony_ci u32 response_buffer_address_on_dsp; 13962306a36Sopenharmony_ci u32 pCI2040HPI_error_count; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci struct hpi_control_cache_single control_cache[HPI_NMIXER_CONTROLS]; 14262306a36Sopenharmony_ci struct hpi_control_cache *p_cache; 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao, 14662306a36Sopenharmony_ci u16 dsp_index, u32 hpi_address, u32 *source, u32 count); 14762306a36Sopenharmony_cistatic u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, 14862306a36Sopenharmony_ci u16 dsp_index, u32 hpi_address, u32 *dest, u32 count); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, 15162306a36Sopenharmony_ci u32 *pos_error_code); 15262306a36Sopenharmony_cistatic short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao, 15362306a36Sopenharmony_ci u16 read_or_write); 15462306a36Sopenharmony_ci#define H6READ 1 15562306a36Sopenharmony_ci#define H6WRITE 0 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic short hpi6000_update_control_cache(struct hpi_adapter_obj *pao, 15862306a36Sopenharmony_ci struct hpi_message *phm); 15962306a36Sopenharmony_cistatic short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, 16062306a36Sopenharmony_ci u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, 16362306a36Sopenharmony_ci struct hpi_response *phr); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index, 16662306a36Sopenharmony_ci u32 ack_value); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic short hpi6000_send_host_command(struct hpi_adapter_obj *pao, 16962306a36Sopenharmony_ci u16 dsp_index, u32 host_cmd); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index, 17462306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index, 17762306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic u32 hpi_read_word(struct dsp_obj *pdo, u32 address); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata, 18462306a36Sopenharmony_ci u32 length); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, 18762306a36Sopenharmony_ci u32 length); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void subsys_create_adapter(struct hpi_message *phm, 19062306a36Sopenharmony_ci struct hpi_response *phr); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic void adapter_delete(struct hpi_adapter_obj *pao, 19362306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic void adapter_get_asserts(struct hpi_adapter_obj *pao, 19662306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic short create_adapter_obj(struct hpi_adapter_obj *pao, 19962306a36Sopenharmony_ci u32 *pos_error_code); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic void delete_adapter_obj(struct hpi_adapter_obj *pao); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* local globals */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ 20662306a36Sopenharmony_cistatic u16 gw_pci_write_asserts; /* used to count PCI2040 errors */ 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void subsys_message(struct hpi_message *phm, struct hpi_response *phr) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci switch (phm->function) { 21162306a36Sopenharmony_ci case HPI_SUBSYS_CREATE_ADAPTER: 21262306a36Sopenharmony_ci subsys_create_adapter(phm, phr); 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci default: 21562306a36Sopenharmony_ci phr->error = HPI_ERROR_INVALID_FUNC; 21662306a36Sopenharmony_ci break; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void control_message(struct hpi_adapter_obj *pao, 22162306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci switch (phm->function) { 22662306a36Sopenharmony_ci case HPI_CONTROL_GET_STATE: 22762306a36Sopenharmony_ci if (pao->has_control_cache) { 22862306a36Sopenharmony_ci u16 err; 22962306a36Sopenharmony_ci err = hpi6000_update_control_cache(pao, phm); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (err) { 23262306a36Sopenharmony_ci if (err >= HPI_ERROR_BACKEND_BASE) { 23362306a36Sopenharmony_ci phr->error = 23462306a36Sopenharmony_ci HPI_ERROR_CONTROL_CACHING; 23562306a36Sopenharmony_ci phr->specific_error = err; 23662306a36Sopenharmony_ci } else { 23762306a36Sopenharmony_ci phr->error = err; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (hpi_check_control_cache(phw->p_cache, phm, phr)) 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci hw_message(pao, phm, phr); 24662306a36Sopenharmony_ci break; 24762306a36Sopenharmony_ci case HPI_CONTROL_SET_STATE: 24862306a36Sopenharmony_ci hw_message(pao, phm, phr); 24962306a36Sopenharmony_ci hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, phr); 25062306a36Sopenharmony_ci break; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci case HPI_CONTROL_GET_INFO: 25362306a36Sopenharmony_ci default: 25462306a36Sopenharmony_ci hw_message(pao, phm, phr); 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void adapter_message(struct hpi_adapter_obj *pao, 26062306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci switch (phm->function) { 26362306a36Sopenharmony_ci case HPI_ADAPTER_GET_ASSERT: 26462306a36Sopenharmony_ci adapter_get_asserts(pao, phm, phr); 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci case HPI_ADAPTER_DELETE: 26862306a36Sopenharmony_ci adapter_delete(pao, phm, phr); 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci default: 27262306a36Sopenharmony_ci hw_message(pao, phm, phr); 27362306a36Sopenharmony_ci break; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic void outstream_message(struct hpi_adapter_obj *pao, 27862306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci switch (phm->function) { 28162306a36Sopenharmony_ci case HPI_OSTREAM_HOSTBUFFER_ALLOC: 28262306a36Sopenharmony_ci case HPI_OSTREAM_HOSTBUFFER_FREE: 28362306a36Sopenharmony_ci /* Don't let these messages go to the HW function because 28462306a36Sopenharmony_ci * they're called without locking the spinlock. 28562306a36Sopenharmony_ci * For the HPI6000 adapters the HW would return 28662306a36Sopenharmony_ci * HPI_ERROR_INVALID_FUNC anyway. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci phr->error = HPI_ERROR_INVALID_FUNC; 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci default: 29162306a36Sopenharmony_ci hw_message(pao, phm, phr); 29262306a36Sopenharmony_ci return; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic void instream_message(struct hpi_adapter_obj *pao, 29762306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci switch (phm->function) { 30162306a36Sopenharmony_ci case HPI_ISTREAM_HOSTBUFFER_ALLOC: 30262306a36Sopenharmony_ci case HPI_ISTREAM_HOSTBUFFER_FREE: 30362306a36Sopenharmony_ci /* Don't let these messages go to the HW function because 30462306a36Sopenharmony_ci * they're called without locking the spinlock. 30562306a36Sopenharmony_ci * For the HPI6000 adapters the HW would return 30662306a36Sopenharmony_ci * HPI_ERROR_INVALID_FUNC anyway. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci phr->error = HPI_ERROR_INVALID_FUNC; 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci default: 31162306a36Sopenharmony_ci hw_message(pao, phm, phr); 31262306a36Sopenharmony_ci return; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci/************************************************************************/ 31762306a36Sopenharmony_ci/** HPI_6000() 31862306a36Sopenharmony_ci * Entry point from HPIMAN 31962306a36Sopenharmony_ci * All calls to the HPI start here 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_civoid HPI_6000(struct hpi_message *phm, struct hpi_response *phr) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct hpi_adapter_obj *pao = NULL; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (phm->object != HPI_OBJ_SUBSYSTEM) { 32662306a36Sopenharmony_ci pao = hpi_find_adapter(phm->adapter_index); 32762306a36Sopenharmony_ci if (!pao) { 32862306a36Sopenharmony_ci hpi_init_response(phr, phm->object, phm->function, 32962306a36Sopenharmony_ci HPI_ERROR_BAD_ADAPTER_NUMBER); 33062306a36Sopenharmony_ci HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n", 33162306a36Sopenharmony_ci phm->adapter_index); 33262306a36Sopenharmony_ci return; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Don't even try to communicate with crashed DSP */ 33662306a36Sopenharmony_ci if (pao->dsp_crashed >= 10) { 33762306a36Sopenharmony_ci hpi_init_response(phr, phm->object, phm->function, 33862306a36Sopenharmony_ci HPI_ERROR_DSP_HARDWARE); 33962306a36Sopenharmony_ci HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n", 34062306a36Sopenharmony_ci phm->adapter_index); 34162306a36Sopenharmony_ci return; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci /* Init default response including the size field */ 34562306a36Sopenharmony_ci if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) 34662306a36Sopenharmony_ci hpi_init_response(phr, phm->object, phm->function, 34762306a36Sopenharmony_ci HPI_ERROR_PROCESSING_MESSAGE); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci switch (phm->type) { 35062306a36Sopenharmony_ci case HPI_TYPE_REQUEST: 35162306a36Sopenharmony_ci switch (phm->object) { 35262306a36Sopenharmony_ci case HPI_OBJ_SUBSYSTEM: 35362306a36Sopenharmony_ci subsys_message(phm, phr); 35462306a36Sopenharmony_ci break; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci case HPI_OBJ_ADAPTER: 35762306a36Sopenharmony_ci phr->size = 35862306a36Sopenharmony_ci sizeof(struct hpi_response_header) + 35962306a36Sopenharmony_ci sizeof(struct hpi_adapter_res); 36062306a36Sopenharmony_ci adapter_message(pao, phm, phr); 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci case HPI_OBJ_CONTROL: 36462306a36Sopenharmony_ci control_message(pao, phm, phr); 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci case HPI_OBJ_OSTREAM: 36862306a36Sopenharmony_ci outstream_message(pao, phm, phr); 36962306a36Sopenharmony_ci break; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci case HPI_OBJ_ISTREAM: 37262306a36Sopenharmony_ci instream_message(pao, phm, phr); 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci default: 37662306a36Sopenharmony_ci hw_message(pao, phm, phr); 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci break; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci default: 38262306a36Sopenharmony_ci phr->error = HPI_ERROR_INVALID_TYPE; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/************************************************************************/ 38862306a36Sopenharmony_ci/* SUBSYSTEM */ 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/* create an adapter object and initialise it based on resource information 39162306a36Sopenharmony_ci * passed in the message 39262306a36Sopenharmony_ci * NOTE - you cannot use this function AND the FindAdapters function at the 39362306a36Sopenharmony_ci * same time, the application must use only one of them to get the adapters 39462306a36Sopenharmony_ci */ 39562306a36Sopenharmony_cistatic void subsys_create_adapter(struct hpi_message *phm, 39662306a36Sopenharmony_ci struct hpi_response *phr) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci /* create temp adapter obj, because we don't know what index yet */ 39962306a36Sopenharmony_ci struct hpi_adapter_obj ao; 40062306a36Sopenharmony_ci struct hpi_adapter_obj *pao; 40162306a36Sopenharmony_ci u32 os_error_code; 40262306a36Sopenharmony_ci u16 err = 0; 40362306a36Sopenharmony_ci u32 dsp_index = 0; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci memset(&ao, 0, sizeof(ao)); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); 41062306a36Sopenharmony_ci if (!ao.priv) { 41162306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); 41262306a36Sopenharmony_ci phr->error = HPI_ERROR_MEMORY_ALLOC; 41362306a36Sopenharmony_ci return; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci /* create the adapter object based on the resource information */ 41762306a36Sopenharmony_ci ao.pci = *phm->u.s.resource.r.pci; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci err = create_adapter_obj(&ao, &os_error_code); 42062306a36Sopenharmony_ci if (err) { 42162306a36Sopenharmony_ci delete_adapter_obj(&ao); 42262306a36Sopenharmony_ci if (err >= HPI_ERROR_BACKEND_BASE) { 42362306a36Sopenharmony_ci phr->error = HPI_ERROR_DSP_BOOTLOAD; 42462306a36Sopenharmony_ci phr->specific_error = err; 42562306a36Sopenharmony_ci } else { 42662306a36Sopenharmony_ci phr->error = err; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci phr->u.s.data = os_error_code; 43062306a36Sopenharmony_ci return; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci /* need to update paParentAdapter */ 43362306a36Sopenharmony_ci pao = hpi_find_adapter(ao.index); 43462306a36Sopenharmony_ci if (!pao) { 43562306a36Sopenharmony_ci /* We just added this adapter, why can't we find it!? */ 43662306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); 43762306a36Sopenharmony_ci phr->error = HPI_ERROR_BAD_ADAPTER; 43862306a36Sopenharmony_ci return; 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { 44262306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 44362306a36Sopenharmony_ci phw->ado[dsp_index].pa_parent_adapter = pao; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci phr->u.s.adapter_type = ao.type; 44762306a36Sopenharmony_ci phr->u.s.adapter_index = ao.index; 44862306a36Sopenharmony_ci phr->error = 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic void adapter_delete(struct hpi_adapter_obj *pao, 45262306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci delete_adapter_obj(pao); 45562306a36Sopenharmony_ci hpi_delete_adapter(pao); 45662306a36Sopenharmony_ci phr->error = 0; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */ 46062306a36Sopenharmony_cistatic short create_adapter_obj(struct hpi_adapter_obj *pao, 46162306a36Sopenharmony_ci u32 *pos_error_code) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci short boot_error = 0; 46462306a36Sopenharmony_ci u32 dsp_index = 0; 46562306a36Sopenharmony_ci u32 control_cache_size = 0; 46662306a36Sopenharmony_ci u32 control_cache_count = 0; 46762306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* The PCI2040 has the following address map */ 47062306a36Sopenharmony_ci /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ 47162306a36Sopenharmony_ci /* BAR1 - 32K = HPI registers on DSP */ 47262306a36Sopenharmony_ci phw->dw2040_HPICSR = pao->pci.ap_mem_base[0]; 47362306a36Sopenharmony_ci phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1]; 47462306a36Sopenharmony_ci HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR, 47562306a36Sopenharmony_ci phw->dw2040_HPIDSP); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci /* set addresses for the possible DSP HPI interfaces */ 47862306a36Sopenharmony_ci for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { 47962306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_control = 48062306a36Sopenharmony_ci phw->dw2040_HPIDSP + (CONTROL + 48162306a36Sopenharmony_ci DSP_SPACING * dsp_index); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_address = 48462306a36Sopenharmony_ci phw->dw2040_HPIDSP + (ADDRESS + 48562306a36Sopenharmony_ci DSP_SPACING * dsp_index); 48662306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_data = 48762306a36Sopenharmony_ci phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_data_auto_inc = 49062306a36Sopenharmony_ci phw->dw2040_HPIDSP + (DATA_AUTOINC + 49162306a36Sopenharmony_ci DSP_SPACING * dsp_index); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n", 49462306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_control, 49562306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_address, 49662306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_data, 49762306a36Sopenharmony_ci phw->ado[dsp_index].prHPI_data_auto_inc); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci phw->ado[dsp_index].pa_parent_adapter = pao; 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci phw->pCI2040HPI_error_count = 0; 50362306a36Sopenharmony_ci pao->has_control_cache = 0; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci /* Set the default number of DSPs on this card */ 50662306a36Sopenharmony_ci /* This is (conditionally) adjusted after bootloading */ 50762306a36Sopenharmony_ci /* of the first DSP in the bootload section. */ 50862306a36Sopenharmony_ci phw->num_dsp = 1; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code); 51162306a36Sopenharmony_ci if (boot_error) 51262306a36Sopenharmony_ci return boot_error; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci phw->message_buffer_address_on_dsp = 0L; 51762306a36Sopenharmony_ci phw->response_buffer_address_on_dsp = 0L; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* get info about the adapter by asking the adapter */ 52062306a36Sopenharmony_ci /* send a HPI_ADAPTER_GET_INFO message */ 52162306a36Sopenharmony_ci { 52262306a36Sopenharmony_ci struct hpi_message hm; 52362306a36Sopenharmony_ci struct hpi_response hr0; /* response from DSP 0 */ 52462306a36Sopenharmony_ci struct hpi_response hr1; /* response from DSP 1 */ 52562306a36Sopenharmony_ci u16 error = 0; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); 52862306a36Sopenharmony_ci memset(&hm, 0, sizeof(hm)); 52962306a36Sopenharmony_ci hm.type = HPI_TYPE_REQUEST; 53062306a36Sopenharmony_ci hm.size = sizeof(struct hpi_message); 53162306a36Sopenharmony_ci hm.object = HPI_OBJ_ADAPTER; 53262306a36Sopenharmony_ci hm.function = HPI_ADAPTER_GET_INFO; 53362306a36Sopenharmony_ci hm.adapter_index = 0; 53462306a36Sopenharmony_ci memset(&hr0, 0, sizeof(hr0)); 53562306a36Sopenharmony_ci memset(&hr1, 0, sizeof(hr1)); 53662306a36Sopenharmony_ci hr0.size = sizeof(hr0); 53762306a36Sopenharmony_ci hr1.size = sizeof(hr1); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0); 54062306a36Sopenharmony_ci if (hr0.error) { 54162306a36Sopenharmony_ci HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error); 54262306a36Sopenharmony_ci return hr0.error; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci if (phw->num_dsp == 2) { 54562306a36Sopenharmony_ci error = hpi6000_message_response_sequence(pao, 1, &hm, 54662306a36Sopenharmony_ci &hr1); 54762306a36Sopenharmony_ci if (error) 54862306a36Sopenharmony_ci return error; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci pao->type = hr0.u.ax.info.adapter_type; 55162306a36Sopenharmony_ci pao->index = hr0.u.ax.info.adapter_index; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci memset(&phw->control_cache[0], 0, 55562306a36Sopenharmony_ci sizeof(struct hpi_control_cache_single) * 55662306a36Sopenharmony_ci HPI_NMIXER_CONTROLS); 55762306a36Sopenharmony_ci /* Read the control cache length to figure out if it is turned on */ 55862306a36Sopenharmony_ci control_cache_size = 55962306a36Sopenharmony_ci hpi_read_word(&phw->ado[0], 56062306a36Sopenharmony_ci HPI_HIF_ADDR(control_cache_size_in_bytes)); 56162306a36Sopenharmony_ci if (control_cache_size) { 56262306a36Sopenharmony_ci control_cache_count = 56362306a36Sopenharmony_ci hpi_read_word(&phw->ado[0], 56462306a36Sopenharmony_ci HPI_HIF_ADDR(control_cache_count)); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci phw->p_cache = 56762306a36Sopenharmony_ci hpi_alloc_control_cache(control_cache_count, 56862306a36Sopenharmony_ci control_cache_size, (unsigned char *) 56962306a36Sopenharmony_ci &phw->control_cache[0] 57062306a36Sopenharmony_ci ); 57162306a36Sopenharmony_ci if (phw->p_cache) 57262306a36Sopenharmony_ci pao->has_control_cache = 1; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type, 57662306a36Sopenharmony_ci pao->index); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (phw->p_cache) 57962306a36Sopenharmony_ci phw->p_cache->adap_idx = pao->index; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci return hpi_add_adapter(pao); 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_cistatic void delete_adapter_obj(struct hpi_adapter_obj *pao) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (pao->has_control_cache) 58962306a36Sopenharmony_ci hpi_free_control_cache(phw->p_cache); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* reset DSPs on adapter */ 59262306a36Sopenharmony_ci iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci kfree(phw); 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci/************************************************************************/ 59862306a36Sopenharmony_ci/* ADAPTER */ 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic void adapter_get_asserts(struct hpi_adapter_obj *pao, 60162306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci#ifndef HIDE_PCI_ASSERTS 60462306a36Sopenharmony_ci /* if we have PCI2040 asserts then collect them */ 60562306a36Sopenharmony_ci if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { 60662306a36Sopenharmony_ci phr->u.ax.assert.p1 = 60762306a36Sopenharmony_ci gw_pci_read_asserts * 100 + gw_pci_write_asserts; 60862306a36Sopenharmony_ci phr->u.ax.assert.p2 = 0; 60962306a36Sopenharmony_ci phr->u.ax.assert.count = 1; /* assert count */ 61062306a36Sopenharmony_ci phr->u.ax.assert.dsp_index = -1; /* "dsp index" */ 61162306a36Sopenharmony_ci strcpy(phr->u.ax.assert.sz_message, "PCI2040 error"); 61262306a36Sopenharmony_ci phr->u.ax.assert.dsp_msg_addr = 0; 61362306a36Sopenharmony_ci gw_pci_read_asserts = 0; 61462306a36Sopenharmony_ci gw_pci_write_asserts = 0; 61562306a36Sopenharmony_ci phr->error = 0; 61662306a36Sopenharmony_ci } else 61762306a36Sopenharmony_ci#endif 61862306a36Sopenharmony_ci hw_message(pao, phm, phr); /*get DSP asserts */ 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci return; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci/************************************************************************/ 62462306a36Sopenharmony_ci/* LOW-LEVEL */ 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, 62762306a36Sopenharmony_ci u32 *pos_error_code) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 63062306a36Sopenharmony_ci short error; 63162306a36Sopenharmony_ci u32 timeout; 63262306a36Sopenharmony_ci u32 read = 0; 63362306a36Sopenharmony_ci u32 i = 0; 63462306a36Sopenharmony_ci u32 data = 0; 63562306a36Sopenharmony_ci u32 j = 0; 63662306a36Sopenharmony_ci u32 test_addr = 0x80000000; 63762306a36Sopenharmony_ci u32 test_data = 0x00000001; 63862306a36Sopenharmony_ci u32 dw2040_reset = 0; 63962306a36Sopenharmony_ci u32 dsp_index = 0; 64062306a36Sopenharmony_ci u32 endian = 0; 64162306a36Sopenharmony_ci u32 adapter_info = 0; 64262306a36Sopenharmony_ci u32 delay = 0; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci struct dsp_code dsp_code; 64562306a36Sopenharmony_ci u16 boot_load_family = 0; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci /* NOTE don't use wAdapterType in this routine. It is not setup yet */ 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci switch (pao->pci.pci_dev->subsystem_device) { 65062306a36Sopenharmony_ci case 0x5100: 65162306a36Sopenharmony_ci case 0x5110: /* ASI5100 revB or higher with C6711D */ 65262306a36Sopenharmony_ci case 0x5200: /* ASI5200 PCIe version of ASI5100 */ 65362306a36Sopenharmony_ci case 0x6100: 65462306a36Sopenharmony_ci case 0x6200: 65562306a36Sopenharmony_ci boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); 65662306a36Sopenharmony_ci break; 65762306a36Sopenharmony_ci default: 65862306a36Sopenharmony_ci return HPI6000_ERROR_UNHANDLED_SUBSYS_ID; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* reset all DSPs, indicate two DSPs are present 66262306a36Sopenharmony_ci * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode 66362306a36Sopenharmony_ci */ 66462306a36Sopenharmony_ci endian = 0; 66562306a36Sopenharmony_ci dw2040_reset = 0x0003000F; 66662306a36Sopenharmony_ci iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* read back register to make sure PCI2040 chip is functioning 66962306a36Sopenharmony_ci * note that bits 4..15 are read-only and so should always return zero, 67062306a36Sopenharmony_ci * even though we wrote 1 to them 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci hpios_delay_micro_seconds(1000); 67362306a36Sopenharmony_ci delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (delay != dw2040_reset) { 67662306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, 67762306a36Sopenharmony_ci delay); 67862306a36Sopenharmony_ci return HPI6000_ERROR_INIT_PCI2040; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* Indicate that DSP#0,1 is a C6X */ 68262306a36Sopenharmony_ci iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH); 68362306a36Sopenharmony_ci /* set Bit30 and 29 - which will prevent Target aborts from being 68462306a36Sopenharmony_ci * issued upon HPI or GP error 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_ci iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* isolate DSP HAD8 line from PCI2040 so that 68962306a36Sopenharmony_ci * Little endian can be set by pullup 69062306a36Sopenharmony_ci */ 69162306a36Sopenharmony_ci dw2040_reset = dw2040_reset & (~(endian << 3)); 69262306a36Sopenharmony_ci iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci phw->ado[0].c_dsp_rev = 'B'; /* revB */ 69562306a36Sopenharmony_ci phw->ado[1].c_dsp_rev = 'B'; /* revB */ 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci /*Take both DSPs out of reset, setting HAD8 to the correct Endian */ 69862306a36Sopenharmony_ci dw2040_reset = dw2040_reset & (~0x00000001); /* start DSP 0 */ 69962306a36Sopenharmony_ci iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); 70062306a36Sopenharmony_ci dw2040_reset = dw2040_reset & (~0x00000002); /* start DSP 1 */ 70162306a36Sopenharmony_ci iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* set HAD8 back to PCI2040, now that DSP set to little endian mode */ 70462306a36Sopenharmony_ci dw2040_reset = dw2040_reset & (~0x00000008); 70562306a36Sopenharmony_ci iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); 70662306a36Sopenharmony_ci /*delay to allow DSP to get going */ 70762306a36Sopenharmony_ci hpios_delay_micro_seconds(100); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci /* loop through all DSPs, downloading DSP code */ 71062306a36Sopenharmony_ci for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { 71162306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* configure DSP so that we download code into the SRAM */ 71462306a36Sopenharmony_ci /* set control reg for little endian, HWOB=1 */ 71562306a36Sopenharmony_ci iowrite32(0x00010001, pdo->prHPI_control); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* test access to the HPI address register (HPIA) */ 71862306a36Sopenharmony_ci test_data = 0x00000001; 71962306a36Sopenharmony_ci for (j = 0; j < 32; j++) { 72062306a36Sopenharmony_ci iowrite32(test_data, pdo->prHPI_address); 72162306a36Sopenharmony_ci data = ioread32(pdo->prHPI_address); 72262306a36Sopenharmony_ci if (data != test_data) { 72362306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n", 72462306a36Sopenharmony_ci test_data, data, dsp_index); 72562306a36Sopenharmony_ci return HPI6000_ERROR_INIT_DSPHPI; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci test_data = test_data << 1; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci/* if C6713 the setup PLL to generate 225MHz from 25MHz. 73162306a36Sopenharmony_ci* Since the PLLDIV1 read is sometimes wrong, even on a C6713, 73262306a36Sopenharmony_ci* we're going to do this unconditionally 73362306a36Sopenharmony_ci*/ 73462306a36Sopenharmony_ci/* PLLDIV1 should have a value of 8000 after reset */ 73562306a36Sopenharmony_ci/* 73662306a36Sopenharmony_ci if (HpiReadWord(pdo,0x01B7C118) == 0x8000) 73762306a36Sopenharmony_ci*/ 73862306a36Sopenharmony_ci { 73962306a36Sopenharmony_ci /* C6713 datasheet says we cannot program PLL from HPI, 74062306a36Sopenharmony_ci * and indeed if we try to set the PLL multiply from the 74162306a36Sopenharmony_ci * HPI, the PLL does not seem to lock, 74262306a36Sopenharmony_ci * so we enable the PLL and use the default of x 7 74362306a36Sopenharmony_ci */ 74462306a36Sopenharmony_ci /* bypass PLL */ 74562306a36Sopenharmony_ci hpi_write_word(pdo, 0x01B7C100, 0x0000); 74662306a36Sopenharmony_ci hpios_delay_micro_seconds(100); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* ** use default of PLL x7 ** */ 74962306a36Sopenharmony_ci /* EMIF = 225/3=75MHz */ 75062306a36Sopenharmony_ci hpi_write_word(pdo, 0x01B7C120, 0x8002); 75162306a36Sopenharmony_ci hpios_delay_micro_seconds(100); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* peri = 225/2 */ 75462306a36Sopenharmony_ci hpi_write_word(pdo, 0x01B7C11C, 0x8001); 75562306a36Sopenharmony_ci hpios_delay_micro_seconds(100); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci /* cpu = 225/1 */ 75862306a36Sopenharmony_ci hpi_write_word(pdo, 0x01B7C118, 0x8000); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci /* ~2ms delay */ 76162306a36Sopenharmony_ci hpios_delay_micro_seconds(2000); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* PLL not bypassed */ 76462306a36Sopenharmony_ci hpi_write_word(pdo, 0x01B7C100, 0x0001); 76562306a36Sopenharmony_ci /* ~2ms delay */ 76662306a36Sopenharmony_ci hpios_delay_micro_seconds(2000); 76762306a36Sopenharmony_ci } 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci /* test r/w to internal DSP memory 77062306a36Sopenharmony_ci * C6711 has L2 cache mapped to 0x0 when reset 77162306a36Sopenharmony_ci * 77262306a36Sopenharmony_ci * revB - because of bug 3.0.1 last HPI read 77362306a36Sopenharmony_ci * (before HPI address issued) must be non-autoinc 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci /* test each bit in the 32bit word */ 77662306a36Sopenharmony_ci for (i = 0; i < 100; i++) { 77762306a36Sopenharmony_ci test_addr = 0x00000000; 77862306a36Sopenharmony_ci test_data = 0x00000001; 77962306a36Sopenharmony_ci for (j = 0; j < 32; j++) { 78062306a36Sopenharmony_ci hpi_write_word(pdo, test_addr + i, test_data); 78162306a36Sopenharmony_ci data = hpi_read_word(pdo, test_addr + i); 78262306a36Sopenharmony_ci if (data != test_data) { 78362306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, 78462306a36Sopenharmony_ci "DSP mem %x %x %x %x\n", 78562306a36Sopenharmony_ci test_addr + i, test_data, 78662306a36Sopenharmony_ci data, dsp_index); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci return HPI6000_ERROR_INIT_DSPINTMEM; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci test_data = test_data << 1; 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* memory map of ASI6200 79562306a36Sopenharmony_ci 00000000-0000FFFF 16Kx32 internal program 79662306a36Sopenharmony_ci 01800000-019FFFFF Internal peripheral 79762306a36Sopenharmony_ci 80000000-807FFFFF CE0 2Mx32 SDRAM running @ 100MHz 79862306a36Sopenharmony_ci 90000000-9000FFFF CE1 Async peripherals: 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci EMIF config 80162306a36Sopenharmony_ci ------------ 80262306a36Sopenharmony_ci Global EMIF control 80362306a36Sopenharmony_ci 0 - 80462306a36Sopenharmony_ci 1 - 80562306a36Sopenharmony_ci 2 - 80662306a36Sopenharmony_ci 3 CLK2EN = 1 CLKOUT2 enabled 80762306a36Sopenharmony_ci 4 CLK1EN = 0 CLKOUT1 disabled 80862306a36Sopenharmony_ci 5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT 80962306a36Sopenharmony_ci 6 - 81062306a36Sopenharmony_ci 7 NOHOLD = 1 external HOLD disabled 81162306a36Sopenharmony_ci 8 HOLDA = 0 HOLDA output is low 81262306a36Sopenharmony_ci 9 HOLD = 0 HOLD input is low 81362306a36Sopenharmony_ci 10 ARDY = 1 ARDY input is high 81462306a36Sopenharmony_ci 11 BUSREQ = 0 BUSREQ output is low 81562306a36Sopenharmony_ci 12,13 Reserved = 1 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_ci hpi_write_word(pdo, 0x01800000, 0x34A8); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* EMIF CE0 setup - 2Mx32 Sync DRAM 82062306a36Sopenharmony_ci 31..28 Wr setup 82162306a36Sopenharmony_ci 27..22 Wr strobe 82262306a36Sopenharmony_ci 21..20 Wr hold 82362306a36Sopenharmony_ci 19..16 Rd setup 82462306a36Sopenharmony_ci 15..14 - 82562306a36Sopenharmony_ci 13..8 Rd strobe 82662306a36Sopenharmony_ci 7..4 MTYPE 0011 Sync DRAM 32bits 82762306a36Sopenharmony_ci 3 Wr hold MSB 82862306a36Sopenharmony_ci 2..0 Rd hold 82962306a36Sopenharmony_ci */ 83062306a36Sopenharmony_ci hpi_write_word(pdo, 0x01800008, 0x00000030); 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci /* EMIF SDRAM Extension 83362306a36Sopenharmony_ci 31-21 0 83462306a36Sopenharmony_ci 20 WR2RD = 0 83562306a36Sopenharmony_ci 19-18 WR2DEAC = 1 83662306a36Sopenharmony_ci 17 WR2WR = 0 83762306a36Sopenharmony_ci 16-15 R2WDQM = 2 83862306a36Sopenharmony_ci 14-12 RD2WR = 4 83962306a36Sopenharmony_ci 11-10 RD2DEAC = 1 84062306a36Sopenharmony_ci 9 RD2RD = 1 84162306a36Sopenharmony_ci 8-7 THZP = 10b 84262306a36Sopenharmony_ci 6-5 TWR = 2-1 = 01b (tWR = 10ns) 84362306a36Sopenharmony_ci 4 TRRD = 0b = 2 ECLK (tRRD = 14ns) 84462306a36Sopenharmony_ci 3-1 TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK) 84562306a36Sopenharmony_ci 1 CAS latency = 3 ECLK 84662306a36Sopenharmony_ci (for Micron 2M32-7 operating at 100Mhz) 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci /* need to use this else DSP code crashes */ 85062306a36Sopenharmony_ci hpi_write_word(pdo, 0x01800020, 0x001BDF29); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank) 85362306a36Sopenharmony_ci 31 - - 85462306a36Sopenharmony_ci 30 SDBSZ 1 4 bank 85562306a36Sopenharmony_ci 29..28 SDRSZ 00 11 row address pins 85662306a36Sopenharmony_ci 27..26 SDCSZ 01 8 column address pins 85762306a36Sopenharmony_ci 25 RFEN 1 refersh enabled 85862306a36Sopenharmony_ci 24 INIT 1 init SDRAM 85962306a36Sopenharmony_ci 23..20 TRCD 0001 86062306a36Sopenharmony_ci 19..16 TRP 0001 86162306a36Sopenharmony_ci 15..12 TRC 0110 86262306a36Sopenharmony_ci 11..0 - - 86362306a36Sopenharmony_ci */ 86462306a36Sopenharmony_ci /* need to use this else DSP code crashes */ 86562306a36Sopenharmony_ci hpi_write_word(pdo, 0x01800018, 0x47117000); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* EMIF SDRAM Refresh Timing */ 86862306a36Sopenharmony_ci hpi_write_word(pdo, 0x0180001C, 0x00000410); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci /*MIF CE1 setup - Async peripherals 87162306a36Sopenharmony_ci @100MHz bus speed, each cycle is 10ns, 87262306a36Sopenharmony_ci 31..28 Wr setup = 1 87362306a36Sopenharmony_ci 27..22 Wr strobe = 3 30ns 87462306a36Sopenharmony_ci 21..20 Wr hold = 1 87562306a36Sopenharmony_ci 19..16 Rd setup =1 87662306a36Sopenharmony_ci 15..14 Ta = 2 87762306a36Sopenharmony_ci 13..8 Rd strobe = 3 30ns 87862306a36Sopenharmony_ci 7..4 MTYPE 0010 Async 32bits 87962306a36Sopenharmony_ci 3 Wr hold MSB =0 88062306a36Sopenharmony_ci 2..0 Rd hold = 1 88162306a36Sopenharmony_ci */ 88262306a36Sopenharmony_ci { 88362306a36Sopenharmony_ci u32 cE1 = 88462306a36Sopenharmony_ci (1L << 28) | (3L << 22) | (1L << 20) | (1L << 88562306a36Sopenharmony_ci 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L; 88662306a36Sopenharmony_ci hpi_write_word(pdo, 0x01800004, cE1); 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci /* delay a little to allow SDRAM and DSP to "get going" */ 89062306a36Sopenharmony_ci hpios_delay_micro_seconds(1000); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci /* test access to SDRAM */ 89362306a36Sopenharmony_ci { 89462306a36Sopenharmony_ci test_addr = 0x80000000; 89562306a36Sopenharmony_ci test_data = 0x00000001; 89662306a36Sopenharmony_ci /* test each bit in the 32bit word */ 89762306a36Sopenharmony_ci for (j = 0; j < 32; j++) { 89862306a36Sopenharmony_ci hpi_write_word(pdo, test_addr, test_data); 89962306a36Sopenharmony_ci data = hpi_read_word(pdo, test_addr); 90062306a36Sopenharmony_ci if (data != test_data) { 90162306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, 90262306a36Sopenharmony_ci "DSP dram %x %x %x %x\n", 90362306a36Sopenharmony_ci test_addr, test_data, data, 90462306a36Sopenharmony_ci dsp_index); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci return HPI6000_ERROR_INIT_SDRAM1; 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci test_data = test_data << 1; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci /* test every Nth address in the DRAM */ 91162306a36Sopenharmony_ci#define DRAM_SIZE_WORDS 0x200000 /*2_mx32 */ 91262306a36Sopenharmony_ci#define DRAM_INC 1024 91362306a36Sopenharmony_ci test_addr = 0x80000000; 91462306a36Sopenharmony_ci test_data = 0x0; 91562306a36Sopenharmony_ci for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) { 91662306a36Sopenharmony_ci hpi_write_word(pdo, test_addr + i, test_data); 91762306a36Sopenharmony_ci test_data++; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci test_addr = 0x80000000; 92062306a36Sopenharmony_ci test_data = 0x0; 92162306a36Sopenharmony_ci for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) { 92262306a36Sopenharmony_ci data = hpi_read_word(pdo, test_addr + i); 92362306a36Sopenharmony_ci if (data != test_data) { 92462306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, 92562306a36Sopenharmony_ci "DSP dram %x %x %x %x\n", 92662306a36Sopenharmony_ci test_addr + i, test_data, 92762306a36Sopenharmony_ci data, dsp_index); 92862306a36Sopenharmony_ci return HPI6000_ERROR_INIT_SDRAM2; 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci test_data++; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci /* write the DSP code down into the DSPs memory */ 93662306a36Sopenharmony_ci error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev, 93762306a36Sopenharmony_ci &dsp_code, pos_error_code); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci if (error) 94062306a36Sopenharmony_ci return error; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci while (1) { 94362306a36Sopenharmony_ci u32 length; 94462306a36Sopenharmony_ci u32 address; 94562306a36Sopenharmony_ci u32 type; 94662306a36Sopenharmony_ci u32 *pcode; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci error = hpi_dsp_code_read_word(&dsp_code, &length); 94962306a36Sopenharmony_ci if (error) 95062306a36Sopenharmony_ci break; 95162306a36Sopenharmony_ci if (length == 0xFFFFFFFF) 95262306a36Sopenharmony_ci break; /* end of code */ 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci error = hpi_dsp_code_read_word(&dsp_code, &address); 95562306a36Sopenharmony_ci if (error) 95662306a36Sopenharmony_ci break; 95762306a36Sopenharmony_ci error = hpi_dsp_code_read_word(&dsp_code, &type); 95862306a36Sopenharmony_ci if (error) 95962306a36Sopenharmony_ci break; 96062306a36Sopenharmony_ci error = hpi_dsp_code_read_block(length, &dsp_code, 96162306a36Sopenharmony_ci &pcode); 96262306a36Sopenharmony_ci if (error) 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci error = hpi6000_dsp_block_write32(pao, (u16)dsp_index, 96562306a36Sopenharmony_ci address, pcode, length); 96662306a36Sopenharmony_ci if (error) 96762306a36Sopenharmony_ci break; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci if (error) { 97162306a36Sopenharmony_ci hpi_dsp_code_close(&dsp_code); 97262306a36Sopenharmony_ci return error; 97362306a36Sopenharmony_ci } 97462306a36Sopenharmony_ci /* verify that code was written correctly */ 97562306a36Sopenharmony_ci /* this time through, assume no errors in DSP code file/array */ 97662306a36Sopenharmony_ci hpi_dsp_code_rewind(&dsp_code); 97762306a36Sopenharmony_ci while (1) { 97862306a36Sopenharmony_ci u32 length; 97962306a36Sopenharmony_ci u32 address; 98062306a36Sopenharmony_ci u32 type; 98162306a36Sopenharmony_ci u32 *pcode; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci hpi_dsp_code_read_word(&dsp_code, &length); 98462306a36Sopenharmony_ci if (length == 0xFFFFFFFF) 98562306a36Sopenharmony_ci break; /* end of code */ 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci hpi_dsp_code_read_word(&dsp_code, &address); 98862306a36Sopenharmony_ci hpi_dsp_code_read_word(&dsp_code, &type); 98962306a36Sopenharmony_ci hpi_dsp_code_read_block(length, &dsp_code, &pcode); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci for (i = 0; i < length; i++) { 99262306a36Sopenharmony_ci data = hpi_read_word(pdo, address); 99362306a36Sopenharmony_ci if (data != *pcode) { 99462306a36Sopenharmony_ci error = HPI6000_ERROR_INIT_VERIFY; 99562306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, 99662306a36Sopenharmony_ci "DSP verify %x %x %x %x\n", 99762306a36Sopenharmony_ci address, *pcode, data, 99862306a36Sopenharmony_ci dsp_index); 99962306a36Sopenharmony_ci break; 100062306a36Sopenharmony_ci } 100162306a36Sopenharmony_ci pcode++; 100262306a36Sopenharmony_ci address += 4; 100362306a36Sopenharmony_ci } 100462306a36Sopenharmony_ci if (error) 100562306a36Sopenharmony_ci break; 100662306a36Sopenharmony_ci } 100762306a36Sopenharmony_ci hpi_dsp_code_close(&dsp_code); 100862306a36Sopenharmony_ci if (error) 100962306a36Sopenharmony_ci return error; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* zero out the hostmailbox */ 101262306a36Sopenharmony_ci { 101362306a36Sopenharmony_ci u32 address = HPI_HIF_ADDR(host_cmd); 101462306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 101562306a36Sopenharmony_ci hpi_write_word(pdo, address, 0); 101662306a36Sopenharmony_ci address += 4; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci } 101962306a36Sopenharmony_ci /* write the DSP number into the hostmailbox */ 102062306a36Sopenharmony_ci /* structure before starting the DSP */ 102162306a36Sopenharmony_ci hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* write the DSP adapter Info into the */ 102462306a36Sopenharmony_ci /* hostmailbox before starting the DSP */ 102562306a36Sopenharmony_ci if (dsp_index > 0) 102662306a36Sopenharmony_ci hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info), 102762306a36Sopenharmony_ci adapter_info); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* step 3. Start code by sending interrupt */ 103062306a36Sopenharmony_ci iowrite32(0x00030003, pdo->prHPI_control); 103162306a36Sopenharmony_ci hpios_delay_micro_seconds(10000); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* wait for a non-zero value in hostcmd - 103462306a36Sopenharmony_ci * indicating initialization is complete 103562306a36Sopenharmony_ci * 103662306a36Sopenharmony_ci * Init could take a while if DSP checks SDRAM memory 103762306a36Sopenharmony_ci * Was 200000. Increased to 2000000 for ASI8801 so we 103862306a36Sopenharmony_ci * don't get 938 errors. 103962306a36Sopenharmony_ci */ 104062306a36Sopenharmony_ci timeout = 2000000; 104162306a36Sopenharmony_ci while (timeout) { 104262306a36Sopenharmony_ci do { 104362306a36Sopenharmony_ci read = hpi_read_word(pdo, 104462306a36Sopenharmony_ci HPI_HIF_ADDR(host_cmd)); 104562306a36Sopenharmony_ci } while (--timeout 104662306a36Sopenharmony_ci && hpi6000_check_PCI2040_error_flag(pao, 104762306a36Sopenharmony_ci H6READ)); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci if (read) 105062306a36Sopenharmony_ci break; 105162306a36Sopenharmony_ci /* The following is a workaround for bug #94: 105262306a36Sopenharmony_ci * Bluescreen on install and subsequent boots on a 105362306a36Sopenharmony_ci * DELL PowerEdge 600SC PC with 1.8GHz P4 and 105462306a36Sopenharmony_ci * ServerWorks chipset. Without this delay the system 105562306a36Sopenharmony_ci * locks up with a bluescreen (NOT GPF or pagefault). 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_ci else 105862306a36Sopenharmony_ci hpios_delay_micro_seconds(10000); 105962306a36Sopenharmony_ci } 106062306a36Sopenharmony_ci if (timeout == 0) 106162306a36Sopenharmony_ci return HPI6000_ERROR_INIT_NOACK; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci /* read the DSP adapter Info from the */ 106462306a36Sopenharmony_ci /* hostmailbox structure after starting the DSP */ 106562306a36Sopenharmony_ci if (dsp_index == 0) { 106662306a36Sopenharmony_ci /*u32 dwTestData=0; */ 106762306a36Sopenharmony_ci u32 mask = 0; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci adapter_info = 107062306a36Sopenharmony_ci hpi_read_word(pdo, 107162306a36Sopenharmony_ci HPI_HIF_ADDR(adapter_info)); 107262306a36Sopenharmony_ci if (HPI_ADAPTER_FAMILY_ASI 107362306a36Sopenharmony_ci (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER 107462306a36Sopenharmony_ci (adapter_info)) == 107562306a36Sopenharmony_ci HPI_ADAPTER_FAMILY_ASI(0x6200)) 107662306a36Sopenharmony_ci /* all 6200 cards have this many DSPs */ 107762306a36Sopenharmony_ci phw->num_dsp = 2; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci /* test that the PLD is programmed */ 108062306a36Sopenharmony_ci /* and we can read/write 24bits */ 108162306a36Sopenharmony_ci#define PLD_BASE_ADDRESS 0x90000000L /*for ASI6100/6200/8800 */ 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci switch (boot_load_family) { 108462306a36Sopenharmony_ci case HPI_ADAPTER_FAMILY_ASI(0x6200): 108562306a36Sopenharmony_ci /* ASI6100/6200 has 24bit path to FPGA */ 108662306a36Sopenharmony_ci mask = 0xFFFFFF00L; 108762306a36Sopenharmony_ci /* ASI5100 uses AX6 code, */ 108862306a36Sopenharmony_ci /* but has no PLD r/w register to test */ 108962306a36Sopenharmony_ci if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> 109062306a36Sopenharmony_ci subsystem_device) == 109162306a36Sopenharmony_ci HPI_ADAPTER_FAMILY_ASI(0x5100)) 109262306a36Sopenharmony_ci mask = 0x00000000L; 109362306a36Sopenharmony_ci /* ASI5200 uses AX6 code, */ 109462306a36Sopenharmony_ci /* but has no PLD r/w register to test */ 109562306a36Sopenharmony_ci if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> 109662306a36Sopenharmony_ci subsystem_device) == 109762306a36Sopenharmony_ci HPI_ADAPTER_FAMILY_ASI(0x5200)) 109862306a36Sopenharmony_ci mask = 0x00000000L; 109962306a36Sopenharmony_ci break; 110062306a36Sopenharmony_ci case HPI_ADAPTER_FAMILY_ASI(0x8800): 110162306a36Sopenharmony_ci /* ASI8800 has 16bit path to FPGA */ 110262306a36Sopenharmony_ci mask = 0xFFFF0000L; 110362306a36Sopenharmony_ci break; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci test_data = 0xAAAAAA00L & mask; 110662306a36Sopenharmony_ci /* write to 24 bit Debug register (D31-D8) */ 110762306a36Sopenharmony_ci hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data); 110862306a36Sopenharmony_ci read = hpi_read_word(pdo, 110962306a36Sopenharmony_ci PLD_BASE_ADDRESS + 4L) & mask; 111062306a36Sopenharmony_ci if (read != test_data) { 111162306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data, 111262306a36Sopenharmony_ci read); 111362306a36Sopenharmony_ci return HPI6000_ERROR_INIT_PLDTEST1; 111462306a36Sopenharmony_ci } 111562306a36Sopenharmony_ci test_data = 0x55555500L & mask; 111662306a36Sopenharmony_ci hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data); 111762306a36Sopenharmony_ci read = hpi_read_word(pdo, 111862306a36Sopenharmony_ci PLD_BASE_ADDRESS + 4L) & mask; 111962306a36Sopenharmony_ci if (read != test_data) { 112062306a36Sopenharmony_ci HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data, 112162306a36Sopenharmony_ci read); 112262306a36Sopenharmony_ci return HPI6000_ERROR_INIT_PLDTEST2; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci } /* for numDSP */ 112662306a36Sopenharmony_ci return 0; 112762306a36Sopenharmony_ci} 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci#define PCI_TIMEOUT 100 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic int hpi_set_address(struct dsp_obj *pdo, u32 address) 113262306a36Sopenharmony_ci{ 113362306a36Sopenharmony_ci u32 timeout = PCI_TIMEOUT; 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci do { 113662306a36Sopenharmony_ci iowrite32(address, pdo->prHPI_address); 113762306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter, 113862306a36Sopenharmony_ci H6WRITE) 113962306a36Sopenharmony_ci && --timeout); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci if (timeout) 114262306a36Sopenharmony_ci return 0; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci return 1; 114562306a36Sopenharmony_ci} 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci/* write one word to the HPI port */ 114862306a36Sopenharmony_cistatic void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data) 114962306a36Sopenharmony_ci{ 115062306a36Sopenharmony_ci if (hpi_set_address(pdo, address)) 115162306a36Sopenharmony_ci return; 115262306a36Sopenharmony_ci iowrite32(data, pdo->prHPI_data); 115362306a36Sopenharmony_ci} 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci/* read one word from the HPI port */ 115662306a36Sopenharmony_cistatic u32 hpi_read_word(struct dsp_obj *pdo, u32 address) 115762306a36Sopenharmony_ci{ 115862306a36Sopenharmony_ci u32 data = 0; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci if (hpi_set_address(pdo, address)) 116162306a36Sopenharmony_ci return 0; /*? No way to return error */ 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci /* take care of errata in revB DSP (2.0.1) */ 116462306a36Sopenharmony_ci data = ioread32(pdo->prHPI_data); 116562306a36Sopenharmony_ci return data; 116662306a36Sopenharmony_ci} 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci/* write a block of 32bit words to the DSP HPI port using auto-inc mode */ 116962306a36Sopenharmony_cistatic void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata, 117062306a36Sopenharmony_ci u32 length) 117162306a36Sopenharmony_ci{ 117262306a36Sopenharmony_ci u16 length16 = length - 1; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci if (length == 0) 117562306a36Sopenharmony_ci return; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci if (hpi_set_address(pdo, address)) 117862306a36Sopenharmony_ci return; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* take care of errata in revB DSP (2.0.1) */ 118362306a36Sopenharmony_ci /* must end with non auto-inc */ 118462306a36Sopenharmony_ci iowrite32(*(pdata + length - 1), pdo->prHPI_data); 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci/** read a block of 32bit words from the DSP HPI port using auto-inc mode 118862306a36Sopenharmony_ci */ 118962306a36Sopenharmony_cistatic void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, 119062306a36Sopenharmony_ci u32 length) 119162306a36Sopenharmony_ci{ 119262306a36Sopenharmony_ci u16 length16 = length - 1; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if (length == 0) 119562306a36Sopenharmony_ci return; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (hpi_set_address(pdo, address)) 119862306a36Sopenharmony_ci return; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci /* take care of errata in revB DSP (2.0.1) */ 120362306a36Sopenharmony_ci /* must end with non auto-inc */ 120462306a36Sopenharmony_ci *(pdata + length - 1) = ioread32(pdo->prHPI_data); 120562306a36Sopenharmony_ci} 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_cistatic u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao, 120862306a36Sopenharmony_ci u16 dsp_index, u32 hpi_address, u32 *source, u32 count) 120962306a36Sopenharmony_ci{ 121062306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 121162306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 121262306a36Sopenharmony_ci u32 time_out = PCI_TIMEOUT; 121362306a36Sopenharmony_ci int c6711_burst_size = 128; 121462306a36Sopenharmony_ci u32 local_hpi_address = hpi_address; 121562306a36Sopenharmony_ci int local_count = count; 121662306a36Sopenharmony_ci int xfer_size; 121762306a36Sopenharmony_ci u32 *pdata = source; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci while (local_count) { 122062306a36Sopenharmony_ci if (local_count > c6711_burst_size) 122162306a36Sopenharmony_ci xfer_size = c6711_burst_size; 122262306a36Sopenharmony_ci else 122362306a36Sopenharmony_ci xfer_size = local_count; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci time_out = PCI_TIMEOUT; 122662306a36Sopenharmony_ci do { 122762306a36Sopenharmony_ci hpi_write_block(pdo, local_hpi_address, pdata, 122862306a36Sopenharmony_ci xfer_size); 122962306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) 123062306a36Sopenharmony_ci && --time_out); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci if (!time_out) 123362306a36Sopenharmony_ci break; 123462306a36Sopenharmony_ci pdata += xfer_size; 123562306a36Sopenharmony_ci local_hpi_address += sizeof(u32) * xfer_size; 123662306a36Sopenharmony_ci local_count -= xfer_size; 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci if (time_out) 124062306a36Sopenharmony_ci return 0; 124162306a36Sopenharmony_ci else 124262306a36Sopenharmony_ci return 1; 124362306a36Sopenharmony_ci} 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_cistatic u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, 124662306a36Sopenharmony_ci u16 dsp_index, u32 hpi_address, u32 *dest, u32 count) 124762306a36Sopenharmony_ci{ 124862306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 124962306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 125062306a36Sopenharmony_ci u32 time_out = PCI_TIMEOUT; 125162306a36Sopenharmony_ci int c6711_burst_size = 16; 125262306a36Sopenharmony_ci u32 local_hpi_address = hpi_address; 125362306a36Sopenharmony_ci int local_count = count; 125462306a36Sopenharmony_ci int xfer_size; 125562306a36Sopenharmony_ci u32 *pdata = dest; 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci while (local_count) { 125862306a36Sopenharmony_ci if (local_count > c6711_burst_size) 125962306a36Sopenharmony_ci xfer_size = c6711_burst_size; 126062306a36Sopenharmony_ci else 126162306a36Sopenharmony_ci xfer_size = local_count; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci time_out = PCI_TIMEOUT; 126462306a36Sopenharmony_ci do { 126562306a36Sopenharmony_ci hpi_read_block(pdo, local_hpi_address, pdata, 126662306a36Sopenharmony_ci xfer_size); 126762306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) 126862306a36Sopenharmony_ci && --time_out); 126962306a36Sopenharmony_ci if (!time_out) 127062306a36Sopenharmony_ci break; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci pdata += xfer_size; 127362306a36Sopenharmony_ci local_hpi_address += sizeof(u32) * xfer_size; 127462306a36Sopenharmony_ci local_count -= xfer_size; 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci if (time_out) 127862306a36Sopenharmony_ci return 0; 127962306a36Sopenharmony_ci else 128062306a36Sopenharmony_ci return 1; 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, 128462306a36Sopenharmony_ci u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr) 128562306a36Sopenharmony_ci{ 128662306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 128762306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 128862306a36Sopenharmony_ci u32 timeout; 128962306a36Sopenharmony_ci u16 ack; 129062306a36Sopenharmony_ci u32 address; 129162306a36Sopenharmony_ci u32 length; 129262306a36Sopenharmony_ci u32 *p_data; 129362306a36Sopenharmony_ci u16 error = 0; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); 129662306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) { 129762306a36Sopenharmony_ci pao->dsp_crashed++; 129862306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT; 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci pao->dsp_crashed = 0; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci /* get the message address and size */ 130362306a36Sopenharmony_ci if (phw->message_buffer_address_on_dsp == 0) { 130462306a36Sopenharmony_ci timeout = TIMEOUT; 130562306a36Sopenharmony_ci do { 130662306a36Sopenharmony_ci address = 130762306a36Sopenharmony_ci hpi_read_word(pdo, 130862306a36Sopenharmony_ci HPI_HIF_ADDR(message_buffer_address)); 130962306a36Sopenharmony_ci phw->message_buffer_address_on_dsp = address; 131062306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) 131162306a36Sopenharmony_ci && --timeout); 131262306a36Sopenharmony_ci if (!timeout) 131362306a36Sopenharmony_ci return HPI6000_ERROR_MSG_GET_ADR; 131462306a36Sopenharmony_ci } else 131562306a36Sopenharmony_ci address = phw->message_buffer_address_on_dsp; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci length = phm->size; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci /* send the message */ 132062306a36Sopenharmony_ci p_data = (u32 *)phm; 132162306a36Sopenharmony_ci if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, 132262306a36Sopenharmony_ci (u16)length / 4)) 132362306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32; 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP)) 132662306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_GETRESPCMD; 132762306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP); 133062306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 133162306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci /* get the response address */ 133462306a36Sopenharmony_ci if (phw->response_buffer_address_on_dsp == 0) { 133562306a36Sopenharmony_ci timeout = TIMEOUT; 133662306a36Sopenharmony_ci do { 133762306a36Sopenharmony_ci address = 133862306a36Sopenharmony_ci hpi_read_word(pdo, 133962306a36Sopenharmony_ci HPI_HIF_ADDR(response_buffer_address)); 134062306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) 134162306a36Sopenharmony_ci && --timeout); 134262306a36Sopenharmony_ci phw->response_buffer_address_on_dsp = address; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci if (!timeout) 134562306a36Sopenharmony_ci return HPI6000_ERROR_RESP_GET_ADR; 134662306a36Sopenharmony_ci } else 134762306a36Sopenharmony_ci address = phw->response_buffer_address_on_dsp; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci /* read the length of the response back from the DSP */ 135062306a36Sopenharmony_ci timeout = TIMEOUT; 135162306a36Sopenharmony_ci do { 135262306a36Sopenharmony_ci length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); 135362306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); 135462306a36Sopenharmony_ci if (!timeout) 135562306a36Sopenharmony_ci return HPI6000_ERROR_RESP_GET_LEN; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci if (length > phr->size) 135862306a36Sopenharmony_ci return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci /* get the response */ 136162306a36Sopenharmony_ci p_data = (u32 *)phr; 136262306a36Sopenharmony_ci if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, 136362306a36Sopenharmony_ci (u16)length / 4)) 136462306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_BLOCKREAD32; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* set i/f back to idle */ 136762306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) 136862306a36Sopenharmony_ci return HPI6000_ERROR_MSG_RESP_IDLECMD; 136962306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci error = hpi_validate_response(phm, phr); 137262306a36Sopenharmony_ci return error; 137362306a36Sopenharmony_ci} 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci/* have to set up the below defines to match stuff in the MAP file */ 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci#define MSG_ADDRESS (HPI_HIF_BASE+0x18) 137862306a36Sopenharmony_ci#define MSG_LENGTH 11 137962306a36Sopenharmony_ci#define RESP_ADDRESS (HPI_HIF_BASE+0x44) 138062306a36Sopenharmony_ci#define RESP_LENGTH 16 138162306a36Sopenharmony_ci#define QUEUE_START (HPI_HIF_BASE+0x88) 138262306a36Sopenharmony_ci#define QUEUE_SIZE 0x8000 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_cistatic short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords) 138562306a36Sopenharmony_ci{ 138662306a36Sopenharmony_ci/*#define CHECKING // comment this line in to enable checking */ 138762306a36Sopenharmony_ci#ifdef CHECKING 138862306a36Sopenharmony_ci if (address < (u32)MSG_ADDRESS) 138962306a36Sopenharmony_ci return 0; 139062306a36Sopenharmony_ci if (address > (u32)(QUEUE_START + QUEUE_SIZE)) 139162306a36Sopenharmony_ci return 0; 139262306a36Sopenharmony_ci if ((address + (length_in_dwords << 2)) > 139362306a36Sopenharmony_ci (u32)(QUEUE_START + QUEUE_SIZE)) 139462306a36Sopenharmony_ci return 0; 139562306a36Sopenharmony_ci#else 139662306a36Sopenharmony_ci (void)address; 139762306a36Sopenharmony_ci (void)length_in_dwords; 139862306a36Sopenharmony_ci return 1; 139962306a36Sopenharmony_ci#endif 140062306a36Sopenharmony_ci} 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_cistatic short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index, 140362306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 140462306a36Sopenharmony_ci{ 140562306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 140662306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 140762306a36Sopenharmony_ci u32 data_sent = 0; 140862306a36Sopenharmony_ci u16 ack; 140962306a36Sopenharmony_ci u32 length, address; 141062306a36Sopenharmony_ci u32 *p_data = (u32 *)phm->u.d.u.data.pb_data; 141162306a36Sopenharmony_ci u16 time_out = 8; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci (void)phr; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci /* round dwDataSize down to nearest 4 bytes */ 141662306a36Sopenharmony_ci while ((data_sent < (phm->u.d.u.data.data_size & ~3L)) 141762306a36Sopenharmony_ci && --time_out) { 141862306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); 141962306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 142062306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, 142362306a36Sopenharmony_ci HPI_HIF_SEND_DATA)) 142462306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_CMD; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA); 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 143162306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_ACK; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci do { 143462306a36Sopenharmony_ci /* get the address and size */ 143562306a36Sopenharmony_ci address = hpi_read_word(pdo, HPI_HIF_ADDR(address)); 143662306a36Sopenharmony_ci /* DSP returns number of DWORDS */ 143762306a36Sopenharmony_ci length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); 143862306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)); 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci if (!hpi6000_send_data_check_adr(address, length)) 144162306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_ADR; 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci /* send the data. break data into 512 DWORD blocks (2K bytes) 144462306a36Sopenharmony_ci * and send using block write. 2Kbytes is the max as this is the 144562306a36Sopenharmony_ci * memory window given to the HPI data register by the PCI2040 144662306a36Sopenharmony_ci */ 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci { 144962306a36Sopenharmony_ci u32 len = length; 145062306a36Sopenharmony_ci u32 blk_len = 512; 145162306a36Sopenharmony_ci while (len) { 145262306a36Sopenharmony_ci if (len < blk_len) 145362306a36Sopenharmony_ci blk_len = len; 145462306a36Sopenharmony_ci if (hpi6000_dsp_block_write32(pao, dsp_index, 145562306a36Sopenharmony_ci address, p_data, blk_len)) 145662306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_WRITE; 145762306a36Sopenharmony_ci address += blk_len * 4; 145862306a36Sopenharmony_ci p_data += blk_len; 145962306a36Sopenharmony_ci len -= blk_len; 146062306a36Sopenharmony_ci } 146162306a36Sopenharmony_ci } 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) 146462306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_IDLECMD; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci data_sent += length * 4; 146962306a36Sopenharmony_ci } 147062306a36Sopenharmony_ci if (!time_out) 147162306a36Sopenharmony_ci return HPI6000_ERROR_SEND_DATA_TIMEOUT; 147262306a36Sopenharmony_ci return 0; 147362306a36Sopenharmony_ci} 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_cistatic short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index, 147662306a36Sopenharmony_ci struct hpi_message *phm, struct hpi_response *phr) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 147962306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 148062306a36Sopenharmony_ci u32 data_got = 0; 148162306a36Sopenharmony_ci u16 ack; 148262306a36Sopenharmony_ci u32 length, address; 148362306a36Sopenharmony_ci u32 *p_data = (u32 *)phm->u.d.u.data.pb_data; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci (void)phr; /* this parameter not used! */ 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci /* round dwDataSize down to nearest 4 bytes */ 148862306a36Sopenharmony_ci while (data_got < (phm->u.d.u.data.data_size & ~3L)) { 148962306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); 149062306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 149162306a36Sopenharmony_ci return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, 149462306a36Sopenharmony_ci HPI_HIF_GET_DATA)) 149562306a36Sopenharmony_ci return HPI6000_ERROR_GET_DATA_CMD; 149662306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 150162306a36Sopenharmony_ci return HPI6000_ERROR_GET_DATA_ACK; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci /* get the address and size */ 150462306a36Sopenharmony_ci do { 150562306a36Sopenharmony_ci address = hpi_read_word(pdo, HPI_HIF_ADDR(address)); 150662306a36Sopenharmony_ci length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); 150762306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)); 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci /* read the data */ 151062306a36Sopenharmony_ci { 151162306a36Sopenharmony_ci u32 len = length; 151262306a36Sopenharmony_ci u32 blk_len = 512; 151362306a36Sopenharmony_ci while (len) { 151462306a36Sopenharmony_ci if (len < blk_len) 151562306a36Sopenharmony_ci blk_len = len; 151662306a36Sopenharmony_ci if (hpi6000_dsp_block_read32(pao, dsp_index, 151762306a36Sopenharmony_ci address, p_data, blk_len)) 151862306a36Sopenharmony_ci return HPI6000_ERROR_GET_DATA_READ; 151962306a36Sopenharmony_ci address += blk_len * 4; 152062306a36Sopenharmony_ci p_data += blk_len; 152162306a36Sopenharmony_ci len -= blk_len; 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci } 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) 152662306a36Sopenharmony_ci return HPI6000_ERROR_GET_DATA_IDLECMD; 152762306a36Sopenharmony_ci hpi6000_send_dsp_interrupt(pdo); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci data_got += length * 4; 153062306a36Sopenharmony_ci } 153162306a36Sopenharmony_ci return 0; 153262306a36Sopenharmony_ci} 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_cistatic void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci iowrite32(0x00030003, pdo->prHPI_control); /* DSPINT */ 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_cistatic short hpi6000_send_host_command(struct hpi_adapter_obj *pao, 154062306a36Sopenharmony_ci u16 dsp_index, u32 host_cmd) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 154362306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 154462306a36Sopenharmony_ci u32 timeout = TIMEOUT; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* set command */ 154762306a36Sopenharmony_ci do { 154862306a36Sopenharmony_ci hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd); 154962306a36Sopenharmony_ci /* flush the FIFO */ 155062306a36Sopenharmony_ci hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd)); 155162306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* reset the interrupt bit */ 155462306a36Sopenharmony_ci iowrite32(0x00040004, pdo->prHPI_control); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci if (timeout) 155762306a36Sopenharmony_ci return 0; 155862306a36Sopenharmony_ci else 155962306a36Sopenharmony_ci return 1; 156062306a36Sopenharmony_ci} 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci/* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */ 156362306a36Sopenharmony_cistatic short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao, 156462306a36Sopenharmony_ci u16 read_or_write) 156562306a36Sopenharmony_ci{ 156662306a36Sopenharmony_ci u32 hPI_error; 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci /* read the error bits from the PCI2040 */ 157162306a36Sopenharmony_ci hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT); 157262306a36Sopenharmony_ci if (hPI_error) { 157362306a36Sopenharmony_ci /* reset the error flag */ 157462306a36Sopenharmony_ci iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT); 157562306a36Sopenharmony_ci phw->pCI2040HPI_error_count++; 157662306a36Sopenharmony_ci if (read_or_write == 1) 157762306a36Sopenharmony_ci gw_pci_read_asserts++; /************* inc global */ 157862306a36Sopenharmony_ci else 157962306a36Sopenharmony_ci gw_pci_write_asserts++; 158062306a36Sopenharmony_ci return 1; 158162306a36Sopenharmony_ci } else 158262306a36Sopenharmony_ci return 0; 158362306a36Sopenharmony_ci} 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_cistatic short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index, 158662306a36Sopenharmony_ci u32 ack_value) 158762306a36Sopenharmony_ci{ 158862306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 158962306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 159062306a36Sopenharmony_ci u32 ack = 0L; 159162306a36Sopenharmony_ci u32 timeout; 159262306a36Sopenharmony_ci u32 hPIC = 0L; 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* wait for host interrupt to signal ack is ready */ 159562306a36Sopenharmony_ci timeout = TIMEOUT; 159662306a36Sopenharmony_ci while (--timeout) { 159762306a36Sopenharmony_ci hPIC = ioread32(pdo->prHPI_control); 159862306a36Sopenharmony_ci if (hPIC & 0x04) /* 0x04 = HINT from DSP */ 159962306a36Sopenharmony_ci break; 160062306a36Sopenharmony_ci } 160162306a36Sopenharmony_ci if (timeout == 0) 160262306a36Sopenharmony_ci return HPI_HIF_ERROR_MASK; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* wait for dwAckValue */ 160562306a36Sopenharmony_ci timeout = TIMEOUT; 160662306a36Sopenharmony_ci while (--timeout) { 160762306a36Sopenharmony_ci /* read the ack mailbox */ 160862306a36Sopenharmony_ci ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack)); 160962306a36Sopenharmony_ci if (ack == ack_value) 161062306a36Sopenharmony_ci break; 161162306a36Sopenharmony_ci if ((ack & HPI_HIF_ERROR_MASK) 161262306a36Sopenharmony_ci && !hpi6000_check_PCI2040_error_flag(pao, H6READ)) 161362306a36Sopenharmony_ci break; 161462306a36Sopenharmony_ci /*for (i=0;i<1000;i++) */ 161562306a36Sopenharmony_ci /* dwPause=i+1; */ 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci if (ack & HPI_HIF_ERROR_MASK) 161862306a36Sopenharmony_ci /* indicates bad read from DSP - 161962306a36Sopenharmony_ci typically 0xffffff is read for some reason */ 162062306a36Sopenharmony_ci ack = HPI_HIF_ERROR_MASK; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci if (timeout == 0) 162362306a36Sopenharmony_ci ack = HPI_HIF_ERROR_MASK; 162462306a36Sopenharmony_ci return (short)ack; 162562306a36Sopenharmony_ci} 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_cistatic short hpi6000_update_control_cache(struct hpi_adapter_obj *pao, 162862306a36Sopenharmony_ci struct hpi_message *phm) 162962306a36Sopenharmony_ci{ 163062306a36Sopenharmony_ci const u16 dsp_index = 0; 163162306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 163262306a36Sopenharmony_ci struct dsp_obj *pdo = &phw->ado[dsp_index]; 163362306a36Sopenharmony_ci u32 timeout; 163462306a36Sopenharmony_ci u32 cache_dirty_flag; 163562306a36Sopenharmony_ci u16 err; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci hpios_dsplock_lock(pao); 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci timeout = TIMEOUT; 164062306a36Sopenharmony_ci do { 164162306a36Sopenharmony_ci cache_dirty_flag = 164262306a36Sopenharmony_ci hpi_read_word((struct dsp_obj *)pdo, 164362306a36Sopenharmony_ci HPI_HIF_ADDR(control_cache_is_dirty)); 164462306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); 164562306a36Sopenharmony_ci if (!timeout) { 164662306a36Sopenharmony_ci err = HPI6000_ERROR_CONTROL_CACHE_PARAMS; 164762306a36Sopenharmony_ci goto unlock; 164862306a36Sopenharmony_ci } 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci if (cache_dirty_flag) { 165162306a36Sopenharmony_ci /* read the cached controls */ 165262306a36Sopenharmony_ci u32 address; 165362306a36Sopenharmony_ci u32 length; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci timeout = TIMEOUT; 165662306a36Sopenharmony_ci if (pdo->control_cache_address_on_dsp == 0) { 165762306a36Sopenharmony_ci do { 165862306a36Sopenharmony_ci address = 165962306a36Sopenharmony_ci hpi_read_word((struct dsp_obj *)pdo, 166062306a36Sopenharmony_ci HPI_HIF_ADDR(control_cache_address)); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci length = hpi_read_word((struct dsp_obj *)pdo, 166362306a36Sopenharmony_ci HPI_HIF_ADDR 166462306a36Sopenharmony_ci (control_cache_size_in_bytes)); 166562306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) 166662306a36Sopenharmony_ci && --timeout); 166762306a36Sopenharmony_ci if (!timeout) { 166862306a36Sopenharmony_ci err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN; 166962306a36Sopenharmony_ci goto unlock; 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci pdo->control_cache_address_on_dsp = address; 167262306a36Sopenharmony_ci pdo->control_cache_length_on_dsp = length; 167362306a36Sopenharmony_ci } else { 167462306a36Sopenharmony_ci address = pdo->control_cache_address_on_dsp; 167562306a36Sopenharmony_ci length = pdo->control_cache_length_on_dsp; 167662306a36Sopenharmony_ci } 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci if (hpi6000_dsp_block_read32(pao, dsp_index, address, 167962306a36Sopenharmony_ci (u32 *)&phw->control_cache[0], 168062306a36Sopenharmony_ci length / sizeof(u32))) { 168162306a36Sopenharmony_ci err = HPI6000_ERROR_CONTROL_CACHE_READ; 168262306a36Sopenharmony_ci goto unlock; 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci do { 168562306a36Sopenharmony_ci hpi_write_word((struct dsp_obj *)pdo, 168662306a36Sopenharmony_ci HPI_HIF_ADDR(control_cache_is_dirty), 0); 168762306a36Sopenharmony_ci /* flush the FIFO */ 168862306a36Sopenharmony_ci hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd)); 168962306a36Sopenharmony_ci } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) 169062306a36Sopenharmony_ci && --timeout); 169162306a36Sopenharmony_ci if (!timeout) { 169262306a36Sopenharmony_ci err = HPI6000_ERROR_CONTROL_CACHE_FLUSH; 169362306a36Sopenharmony_ci goto unlock; 169462306a36Sopenharmony_ci } 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci } 169762306a36Sopenharmony_ci err = 0; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ciunlock: 170062306a36Sopenharmony_ci hpios_dsplock_unlock(pao); 170162306a36Sopenharmony_ci return err; 170262306a36Sopenharmony_ci} 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci/** Get dsp index for multi DSP adapters only */ 170562306a36Sopenharmony_cistatic u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm) 170662306a36Sopenharmony_ci{ 170762306a36Sopenharmony_ci u16 ret = 0; 170862306a36Sopenharmony_ci switch (phm->object) { 170962306a36Sopenharmony_ci case HPI_OBJ_ISTREAM: 171062306a36Sopenharmony_ci if (phm->obj_index < 2) 171162306a36Sopenharmony_ci ret = 1; 171262306a36Sopenharmony_ci break; 171362306a36Sopenharmony_ci case HPI_OBJ_PROFILE: 171462306a36Sopenharmony_ci ret = phm->obj_index; 171562306a36Sopenharmony_ci break; 171662306a36Sopenharmony_ci default: 171762306a36Sopenharmony_ci break; 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci return ret; 172062306a36Sopenharmony_ci} 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci/** Complete transaction with DSP 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ciSend message, get response, send or get stream data if any. 172562306a36Sopenharmony_ci*/ 172662306a36Sopenharmony_cistatic void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, 172762306a36Sopenharmony_ci struct hpi_response *phr) 172862306a36Sopenharmony_ci{ 172962306a36Sopenharmony_ci u16 error = 0; 173062306a36Sopenharmony_ci u16 dsp_index = 0; 173162306a36Sopenharmony_ci struct hpi_hw_obj *phw = pao->priv; 173262306a36Sopenharmony_ci u16 num_dsp = phw->num_dsp; 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci if (num_dsp < 2) 173562306a36Sopenharmony_ci dsp_index = 0; 173662306a36Sopenharmony_ci else { 173762306a36Sopenharmony_ci dsp_index = get_dsp_index(pao, phm); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci /* is this checked on the DSP anyway? */ 174062306a36Sopenharmony_ci if ((phm->function == HPI_ISTREAM_GROUP_ADD) 174162306a36Sopenharmony_ci || (phm->function == HPI_OSTREAM_GROUP_ADD)) { 174262306a36Sopenharmony_ci struct hpi_message hm; 174362306a36Sopenharmony_ci u16 add_index; 174462306a36Sopenharmony_ci hm.obj_index = phm->u.d.u.stream.stream_index; 174562306a36Sopenharmony_ci hm.object = phm->u.d.u.stream.object_type; 174662306a36Sopenharmony_ci add_index = get_dsp_index(pao, &hm); 174762306a36Sopenharmony_ci if (add_index != dsp_index) { 174862306a36Sopenharmony_ci phr->error = HPI_ERROR_NO_INTERDSP_GROUPS; 174962306a36Sopenharmony_ci return; 175062306a36Sopenharmony_ci } 175162306a36Sopenharmony_ci } 175262306a36Sopenharmony_ci } 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci hpios_dsplock_lock(pao); 175562306a36Sopenharmony_ci error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci if (error) /* something failed in the HPI/DSP interface */ 175862306a36Sopenharmony_ci goto err; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci if (phr->error) /* something failed in the DSP */ 176162306a36Sopenharmony_ci goto out; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci switch (phm->function) { 176462306a36Sopenharmony_ci case HPI_OSTREAM_WRITE: 176562306a36Sopenharmony_ci case HPI_ISTREAM_ANC_WRITE: 176662306a36Sopenharmony_ci error = hpi6000_send_data(pao, dsp_index, phm, phr); 176762306a36Sopenharmony_ci break; 176862306a36Sopenharmony_ci case HPI_ISTREAM_READ: 176962306a36Sopenharmony_ci case HPI_OSTREAM_ANC_READ: 177062306a36Sopenharmony_ci error = hpi6000_get_data(pao, dsp_index, phm, phr); 177162306a36Sopenharmony_ci break; 177262306a36Sopenharmony_ci case HPI_ADAPTER_GET_ASSERT: 177362306a36Sopenharmony_ci phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */ 177462306a36Sopenharmony_ci if (num_dsp == 2) { 177562306a36Sopenharmony_ci if (!phr->u.ax.assert.count) { 177662306a36Sopenharmony_ci /* no assert from dsp 0, check dsp 1 */ 177762306a36Sopenharmony_ci error = hpi6000_message_response_sequence(pao, 177862306a36Sopenharmony_ci 1, phm, phr); 177962306a36Sopenharmony_ci phr->u.ax.assert.dsp_index = 1; 178062306a36Sopenharmony_ci } 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci } 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_cierr: 178562306a36Sopenharmony_ci if (error) { 178662306a36Sopenharmony_ci if (error >= HPI_ERROR_BACKEND_BASE) { 178762306a36Sopenharmony_ci phr->error = HPI_ERROR_DSP_COMMUNICATION; 178862306a36Sopenharmony_ci phr->specific_error = error; 178962306a36Sopenharmony_ci } else { 179062306a36Sopenharmony_ci phr->error = error; 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci /* just the header of the response is valid */ 179462306a36Sopenharmony_ci phr->size = sizeof(struct hpi_response_header); 179562306a36Sopenharmony_ci } 179662306a36Sopenharmony_ciout: 179762306a36Sopenharmony_ci hpios_dsplock_unlock(pao); 179862306a36Sopenharmony_ci return; 179962306a36Sopenharmony_ci} 1800