1719f82d3SEliot Blennerhassett /****************************************************************************** 2719f82d3SEliot Blennerhassett 3719f82d3SEliot Blennerhassett AudioScience HPI driver 4*f9a376c3SEliot Blennerhassett Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com> 5719f82d3SEliot Blennerhassett 6719f82d3SEliot Blennerhassett This program is free software; you can redistribute it and/or modify 7719f82d3SEliot Blennerhassett it under the terms of version 2 of the GNU General Public License as 8719f82d3SEliot Blennerhassett published by the Free Software Foundation; 9719f82d3SEliot Blennerhassett 10719f82d3SEliot Blennerhassett This program is distributed in the hope that it will be useful, 11719f82d3SEliot Blennerhassett but WITHOUT ANY WARRANTY; without even the implied warranty of 12719f82d3SEliot Blennerhassett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13719f82d3SEliot Blennerhassett GNU General Public License for more details. 14719f82d3SEliot Blennerhassett 15719f82d3SEliot Blennerhassett You should have received a copy of the GNU General Public License 16719f82d3SEliot Blennerhassett along with this program; if not, write to the Free Software 17719f82d3SEliot Blennerhassett Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18719f82d3SEliot Blennerhassett 19719f82d3SEliot Blennerhassett Hardware Programming Interface (HPI) for AudioScience 20719f82d3SEliot Blennerhassett ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters. 21719f82d3SEliot Blennerhassett These PCI and PCIe bus adapters are based on a 22719f82d3SEliot Blennerhassett TMS320C6205 PCI bus mastering DSP, 23719f82d3SEliot Blennerhassett and (except ASI50xx) TI TMS320C6xxx floating point DSP 24719f82d3SEliot Blennerhassett 25719f82d3SEliot Blennerhassett Exported function: 26719f82d3SEliot Blennerhassett void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) 27719f82d3SEliot Blennerhassett 28719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 1998-2010 29719f82d3SEliot Blennerhassett *******************************************************************************/ 30719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpi6205.c" 31719f82d3SEliot Blennerhassett 32719f82d3SEliot Blennerhassett #include "hpi_internal.h" 33719f82d3SEliot Blennerhassett #include "hpimsginit.h" 34719f82d3SEliot Blennerhassett #include "hpidebug.h" 35719f82d3SEliot Blennerhassett #include "hpi6205.h" 36719f82d3SEliot Blennerhassett #include "hpidspcd.h" 37719f82d3SEliot Blennerhassett #include "hpicmn.h" 38719f82d3SEliot Blennerhassett 39719f82d3SEliot Blennerhassett /*****************************************************************************/ 40719f82d3SEliot Blennerhassett /* HPI6205 specific error codes */ 413285ea10SEliot Blennerhassett #define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */ 423285ea10SEliot Blennerhassett 433285ea10SEliot Blennerhassett /* operational/messaging errors */ 443285ea10SEliot Blennerhassett #define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015 453285ea10SEliot Blennerhassett #define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016 463285ea10SEliot Blennerhassett 473285ea10SEliot Blennerhassett /* initialization/bootload errors */ 48719f82d3SEliot Blennerhassett #define HPI6205_ERROR_6205_NO_IRQ 1002 49719f82d3SEliot Blennerhassett #define HPI6205_ERROR_6205_INIT_FAILED 1003 50719f82d3SEliot Blennerhassett #define HPI6205_ERROR_6205_REG 1006 51719f82d3SEliot Blennerhassett #define HPI6205_ERROR_6205_DSPPAGE 1007 52719f82d3SEliot Blennerhassett #define HPI6205_ERROR_C6713_HPIC 1009 53719f82d3SEliot Blennerhassett #define HPI6205_ERROR_C6713_HPIA 1010 54719f82d3SEliot Blennerhassett #define HPI6205_ERROR_C6713_PLL 1011 55719f82d3SEliot Blennerhassett #define HPI6205_ERROR_DSP_INTMEM 1012 56719f82d3SEliot Blennerhassett #define HPI6205_ERROR_DSP_EXTMEM 1013 57719f82d3SEliot Blennerhassett #define HPI6205_ERROR_DSP_PLD 1014 58719f82d3SEliot Blennerhassett #define HPI6205_ERROR_6205_EEPROM 1017 594e225e26SEliot Blennerhassett #define HPI6205_ERROR_DSP_EMIF1 1018 604e225e26SEliot Blennerhassett #define HPI6205_ERROR_DSP_EMIF2 1019 614e225e26SEliot Blennerhassett #define HPI6205_ERROR_DSP_EMIF3 1020 624e225e26SEliot Blennerhassett #define HPI6205_ERROR_DSP_EMIF4 1021 63719f82d3SEliot Blennerhassett 64719f82d3SEliot Blennerhassett /*****************************************************************************/ 65719f82d3SEliot Blennerhassett /* for C6205 PCI i/f */ 66719f82d3SEliot Blennerhassett /* Host Status Register (HSR) bitfields */ 67719f82d3SEliot Blennerhassett #define C6205_HSR_INTSRC 0x01 68719f82d3SEliot Blennerhassett #define C6205_HSR_INTAVAL 0x02 69719f82d3SEliot Blennerhassett #define C6205_HSR_INTAM 0x04 70719f82d3SEliot Blennerhassett #define C6205_HSR_CFGERR 0x08 71719f82d3SEliot Blennerhassett #define C6205_HSR_EEREAD 0x10 72719f82d3SEliot Blennerhassett /* Host-to-DSP Control Register (HDCR) bitfields */ 73719f82d3SEliot Blennerhassett #define C6205_HDCR_WARMRESET 0x01 74719f82d3SEliot Blennerhassett #define C6205_HDCR_DSPINT 0x02 75719f82d3SEliot Blennerhassett #define C6205_HDCR_PCIBOOT 0x04 76719f82d3SEliot Blennerhassett /* DSP Page Register (DSPP) bitfields, */ 77719f82d3SEliot Blennerhassett /* defines 4 Mbyte page that BAR0 points to */ 78719f82d3SEliot Blennerhassett #define C6205_DSPP_MAP1 0x400 79719f82d3SEliot Blennerhassett 80719f82d3SEliot Blennerhassett /* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP. 81719f82d3SEliot Blennerhassett * BAR1 maps to non-prefetchable 8 Mbyte memory block 82719f82d3SEliot Blennerhassett * of DSP memory mapped registers (starting at 0x01800000). 83719f82d3SEliot Blennerhassett * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this 84719f82d3SEliot Blennerhassett * needs to be added to the BAR1 base address set in the PCI config reg 85719f82d3SEliot Blennerhassett */ 86719f82d3SEliot Blennerhassett #define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L) 87719f82d3SEliot Blennerhassett #define C6205_BAR1_HSR (C6205_BAR1_PCI_IO_OFFSET) 88719f82d3SEliot Blennerhassett #define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4) 89719f82d3SEliot Blennerhassett #define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8) 90719f82d3SEliot Blennerhassett 91719f82d3SEliot Blennerhassett /* used to control LED (revA) and reset C6713 (revB) */ 92719f82d3SEliot Blennerhassett #define C6205_BAR0_TIMER1_CTL (0x01980000L) 93719f82d3SEliot Blennerhassett 94719f82d3SEliot Blennerhassett /* For first 6713 in CE1 space, using DA17,16,2 */ 95719f82d3SEliot Blennerhassett #define HPICL_ADDR 0x01400000L 96719f82d3SEliot Blennerhassett #define HPICH_ADDR 0x01400004L 97719f82d3SEliot Blennerhassett #define HPIAL_ADDR 0x01410000L 98719f82d3SEliot Blennerhassett #define HPIAH_ADDR 0x01410004L 99719f82d3SEliot Blennerhassett #define HPIDIL_ADDR 0x01420000L 100719f82d3SEliot Blennerhassett #define HPIDIH_ADDR 0x01420004L 101719f82d3SEliot Blennerhassett #define HPIDL_ADDR 0x01430000L 102719f82d3SEliot Blennerhassett #define HPIDH_ADDR 0x01430004L 103719f82d3SEliot Blennerhassett 104719f82d3SEliot Blennerhassett #define C6713_EMIF_GCTL 0x01800000 105719f82d3SEliot Blennerhassett #define C6713_EMIF_CE1 0x01800004 106719f82d3SEliot Blennerhassett #define C6713_EMIF_CE0 0x01800008 107719f82d3SEliot Blennerhassett #define C6713_EMIF_CE2 0x01800010 108719f82d3SEliot Blennerhassett #define C6713_EMIF_CE3 0x01800014 109719f82d3SEliot Blennerhassett #define C6713_EMIF_SDRAMCTL 0x01800018 110719f82d3SEliot Blennerhassett #define C6713_EMIF_SDRAMTIMING 0x0180001C 111719f82d3SEliot Blennerhassett #define C6713_EMIF_SDRAMEXT 0x01800020 112719f82d3SEliot Blennerhassett 113719f82d3SEliot Blennerhassett struct hpi_hw_obj { 114719f82d3SEliot Blennerhassett /* PCI registers */ 115719f82d3SEliot Blennerhassett __iomem u32 *prHSR; 116719f82d3SEliot Blennerhassett __iomem u32 *prHDCR; 117719f82d3SEliot Blennerhassett __iomem u32 *prDSPP; 118719f82d3SEliot Blennerhassett 119719f82d3SEliot Blennerhassett u32 dsp_page; 120719f82d3SEliot Blennerhassett 121719f82d3SEliot Blennerhassett struct consistent_dma_area h_locked_mem; 122719f82d3SEliot Blennerhassett struct bus_master_interface *p_interface_buffer; 123719f82d3SEliot Blennerhassett 124719f82d3SEliot Blennerhassett u16 flag_outstream_just_reset[HPI_MAX_STREAMS]; 125719f82d3SEliot Blennerhassett /* a non-NULL handle means there is an HPI allocated buffer */ 126719f82d3SEliot Blennerhassett struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS]; 127719f82d3SEliot Blennerhassett struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS]; 128719f82d3SEliot Blennerhassett /* non-zero size means a buffer exists, may be external */ 129719f82d3SEliot Blennerhassett u32 instream_host_buffer_size[HPI_MAX_STREAMS]; 130719f82d3SEliot Blennerhassett u32 outstream_host_buffer_size[HPI_MAX_STREAMS]; 131719f82d3SEliot Blennerhassett 132719f82d3SEliot Blennerhassett struct consistent_dma_area h_control_cache; 133719f82d3SEliot Blennerhassett struct hpi_control_cache *p_cache; 134719f82d3SEliot Blennerhassett }; 135719f82d3SEliot Blennerhassett 136719f82d3SEliot Blennerhassett /*****************************************************************************/ 137719f82d3SEliot Blennerhassett /* local prototypes */ 138719f82d3SEliot Blennerhassett 139719f82d3SEliot Blennerhassett #define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write) 140719f82d3SEliot Blennerhassett 141719f82d3SEliot Blennerhassett static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us); 142719f82d3SEliot Blennerhassett 143719f82d3SEliot Blennerhassett static void send_dsp_command(struct hpi_hw_obj *phw, int cmd); 144719f82d3SEliot Blennerhassett 145719f82d3SEliot Blennerhassett static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, 146719f82d3SEliot Blennerhassett u32 *pos_error_code); 147719f82d3SEliot Blennerhassett 148719f82d3SEliot Blennerhassett static u16 message_response_sequence(struct hpi_adapter_obj *pao, 149719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 150719f82d3SEliot Blennerhassett 151719f82d3SEliot Blennerhassett static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, 152719f82d3SEliot Blennerhassett struct hpi_response *phr); 153719f82d3SEliot Blennerhassett 154719f82d3SEliot Blennerhassett #define HPI6205_TIMEOUT 1000000 155719f82d3SEliot Blennerhassett 156719f82d3SEliot Blennerhassett static void subsys_create_adapter(struct hpi_message *phm, 157719f82d3SEliot Blennerhassett struct hpi_response *phr); 1586d0b898eSEliot Blennerhassett static void adapter_delete(struct hpi_adapter_obj *pao, 1596d0b898eSEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 160719f82d3SEliot Blennerhassett 161719f82d3SEliot Blennerhassett static u16 create_adapter_obj(struct hpi_adapter_obj *pao, 162719f82d3SEliot Blennerhassett u32 *pos_error_code); 163719f82d3SEliot Blennerhassett 164719f82d3SEliot Blennerhassett static void delete_adapter_obj(struct hpi_adapter_obj *pao); 165719f82d3SEliot Blennerhassett 166*f9a376c3SEliot Blennerhassett static int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao, 167*f9a376c3SEliot Blennerhassett u32 message); 168*f9a376c3SEliot Blennerhassett 169719f82d3SEliot Blennerhassett static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, 170719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 171719f82d3SEliot Blennerhassett 172719f82d3SEliot Blennerhassett static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao, 173719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 174719f82d3SEliot Blennerhassett 175719f82d3SEliot Blennerhassett static void outstream_host_buffer_free(struct hpi_adapter_obj *pao, 176719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 177719f82d3SEliot Blennerhassett static void outstream_write(struct hpi_adapter_obj *pao, 178719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 179719f82d3SEliot Blennerhassett 180719f82d3SEliot Blennerhassett static void outstream_get_info(struct hpi_adapter_obj *pao, 181719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 182719f82d3SEliot Blennerhassett 183719f82d3SEliot Blennerhassett static void outstream_start(struct hpi_adapter_obj *pao, 184719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 185719f82d3SEliot Blennerhassett 186719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_adapter_obj *pao, 187719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 188719f82d3SEliot Blennerhassett 189719f82d3SEliot Blennerhassett static void outstream_reset(struct hpi_adapter_obj *pao, 190719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 191719f82d3SEliot Blennerhassett 192719f82d3SEliot Blennerhassett static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, 193719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 194719f82d3SEliot Blennerhassett 195719f82d3SEliot Blennerhassett static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao, 196719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 197719f82d3SEliot Blennerhassett 198719f82d3SEliot Blennerhassett static void instream_host_buffer_free(struct hpi_adapter_obj *pao, 199719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 200719f82d3SEliot Blennerhassett 201719f82d3SEliot Blennerhassett static void instream_read(struct hpi_adapter_obj *pao, 202719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 203719f82d3SEliot Blennerhassett 204719f82d3SEliot Blennerhassett static void instream_get_info(struct hpi_adapter_obj *pao, 205719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 206719f82d3SEliot Blennerhassett 207719f82d3SEliot Blennerhassett static void instream_start(struct hpi_adapter_obj *pao, 208719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr); 209719f82d3SEliot Blennerhassett 210719f82d3SEliot Blennerhassett static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, 211719f82d3SEliot Blennerhassett u32 address); 212719f82d3SEliot Blennerhassett 2133285ea10SEliot Blennerhassett static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, 2143285ea10SEliot Blennerhassett int dsp_index, u32 address, u32 data); 215719f82d3SEliot Blennerhassett 216719f82d3SEliot Blennerhassett static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, 217719f82d3SEliot Blennerhassett int dsp_index); 218719f82d3SEliot Blennerhassett 219719f82d3SEliot Blennerhassett static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, 220719f82d3SEliot Blennerhassett u32 address, u32 length); 221719f82d3SEliot Blennerhassett 222719f82d3SEliot Blennerhassett static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao, 223719f82d3SEliot Blennerhassett int dsp_index); 224719f82d3SEliot Blennerhassett 225719f82d3SEliot Blennerhassett static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao, 226719f82d3SEliot Blennerhassett int dsp_index); 227719f82d3SEliot Blennerhassett 228719f82d3SEliot Blennerhassett static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index); 229719f82d3SEliot Blennerhassett 230719f82d3SEliot Blennerhassett /*****************************************************************************/ 231719f82d3SEliot Blennerhassett 2326d0b898eSEliot Blennerhassett static void subsys_message(struct hpi_adapter_obj *pao, 2336d0b898eSEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 234719f82d3SEliot Blennerhassett { 235719f82d3SEliot Blennerhassett switch (phm->function) { 236719f82d3SEliot Blennerhassett case HPI_SUBSYS_CREATE_ADAPTER: 237719f82d3SEliot Blennerhassett subsys_create_adapter(phm, phr); 238719f82d3SEliot Blennerhassett break; 239719f82d3SEliot Blennerhassett default: 240719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_FUNC; 241719f82d3SEliot Blennerhassett break; 242719f82d3SEliot Blennerhassett } 243719f82d3SEliot Blennerhassett } 244719f82d3SEliot Blennerhassett 245719f82d3SEliot Blennerhassett static void control_message(struct hpi_adapter_obj *pao, 246719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 247719f82d3SEliot Blennerhassett { 248719f82d3SEliot Blennerhassett 249719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 2503285ea10SEliot Blennerhassett u16 pending_cache_error = 0; 251719f82d3SEliot Blennerhassett 252719f82d3SEliot Blennerhassett switch (phm->function) { 253719f82d3SEliot Blennerhassett case HPI_CONTROL_GET_STATE: 254719f82d3SEliot Blennerhassett if (pao->has_control_cache) { 2553285ea10SEliot Blennerhassett rmb(); /* make sure we see updates DMAed from DSP */ 2563285ea10SEliot Blennerhassett if (hpi_check_control_cache(phw->p_cache, phm, phr)) { 257719f82d3SEliot Blennerhassett break; 2583285ea10SEliot Blennerhassett } else if (phm->u.c.attribute == HPI_METER_PEAK) { 2593285ea10SEliot Blennerhassett pending_cache_error = 2603285ea10SEliot Blennerhassett HPI_ERROR_CONTROL_CACHING; 2613285ea10SEliot Blennerhassett } 262719f82d3SEliot Blennerhassett } 263719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 2643285ea10SEliot Blennerhassett if (pending_cache_error && !phr->error) 2653285ea10SEliot Blennerhassett phr->error = pending_cache_error; 266719f82d3SEliot Blennerhassett break; 267719f82d3SEliot Blennerhassett case HPI_CONTROL_GET_INFO: 268719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 269719f82d3SEliot Blennerhassett break; 270719f82d3SEliot Blennerhassett case HPI_CONTROL_SET_STATE: 271719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 272719f82d3SEliot Blennerhassett if (pao->has_control_cache) 2733285ea10SEliot Blennerhassett hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, 2743285ea10SEliot Blennerhassett phr); 275719f82d3SEliot Blennerhassett break; 276719f82d3SEliot Blennerhassett default: 277719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_FUNC; 278719f82d3SEliot Blennerhassett break; 279719f82d3SEliot Blennerhassett } 280719f82d3SEliot Blennerhassett } 281719f82d3SEliot Blennerhassett 282719f82d3SEliot Blennerhassett static void adapter_message(struct hpi_adapter_obj *pao, 283719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 284719f82d3SEliot Blennerhassett { 285719f82d3SEliot Blennerhassett switch (phm->function) { 2866d0b898eSEliot Blennerhassett case HPI_ADAPTER_DELETE: 2876d0b898eSEliot Blennerhassett adapter_delete(pao, phm, phr); 2886d0b898eSEliot Blennerhassett break; 289719f82d3SEliot Blennerhassett default: 290719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 291719f82d3SEliot Blennerhassett break; 292719f82d3SEliot Blennerhassett } 293719f82d3SEliot Blennerhassett } 294719f82d3SEliot Blennerhassett 295719f82d3SEliot Blennerhassett static void outstream_message(struct hpi_adapter_obj *pao, 296719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 297719f82d3SEliot Blennerhassett { 298719f82d3SEliot Blennerhassett 299719f82d3SEliot Blennerhassett if (phm->obj_index >= HPI_MAX_STREAMS) { 300deb21a23SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OBJ_INDEX; 301719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(WARNING, 3023285ea10SEliot Blennerhassett "Message referencing invalid stream %d " 303719f82d3SEliot Blennerhassett "on adapter index %d\n", phm->obj_index, 304719f82d3SEliot Blennerhassett phm->adapter_index); 305719f82d3SEliot Blennerhassett return; 306719f82d3SEliot Blennerhassett } 307719f82d3SEliot Blennerhassett 308719f82d3SEliot Blennerhassett switch (phm->function) { 309719f82d3SEliot Blennerhassett case HPI_OSTREAM_WRITE: 310719f82d3SEliot Blennerhassett outstream_write(pao, phm, phr); 311719f82d3SEliot Blennerhassett break; 312719f82d3SEliot Blennerhassett case HPI_OSTREAM_GET_INFO: 313719f82d3SEliot Blennerhassett outstream_get_info(pao, phm, phr); 314719f82d3SEliot Blennerhassett break; 315719f82d3SEliot Blennerhassett case HPI_OSTREAM_HOSTBUFFER_ALLOC: 316719f82d3SEliot Blennerhassett outstream_host_buffer_allocate(pao, phm, phr); 317719f82d3SEliot Blennerhassett break; 318719f82d3SEliot Blennerhassett case HPI_OSTREAM_HOSTBUFFER_GET_INFO: 319719f82d3SEliot Blennerhassett outstream_host_buffer_get_info(pao, phm, phr); 320719f82d3SEliot Blennerhassett break; 321719f82d3SEliot Blennerhassett case HPI_OSTREAM_HOSTBUFFER_FREE: 322719f82d3SEliot Blennerhassett outstream_host_buffer_free(pao, phm, phr); 323719f82d3SEliot Blennerhassett break; 324719f82d3SEliot Blennerhassett case HPI_OSTREAM_START: 325719f82d3SEliot Blennerhassett outstream_start(pao, phm, phr); 326719f82d3SEliot Blennerhassett break; 327719f82d3SEliot Blennerhassett case HPI_OSTREAM_OPEN: 328719f82d3SEliot Blennerhassett outstream_open(pao, phm, phr); 329719f82d3SEliot Blennerhassett break; 330719f82d3SEliot Blennerhassett case HPI_OSTREAM_RESET: 331719f82d3SEliot Blennerhassett outstream_reset(pao, phm, phr); 332719f82d3SEliot Blennerhassett break; 333719f82d3SEliot Blennerhassett default: 334719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 335719f82d3SEliot Blennerhassett break; 336719f82d3SEliot Blennerhassett } 337719f82d3SEliot Blennerhassett } 338719f82d3SEliot Blennerhassett 339719f82d3SEliot Blennerhassett static void instream_message(struct hpi_adapter_obj *pao, 340719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 341719f82d3SEliot Blennerhassett { 342719f82d3SEliot Blennerhassett 343719f82d3SEliot Blennerhassett if (phm->obj_index >= HPI_MAX_STREAMS) { 344deb21a23SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OBJ_INDEX; 345719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(WARNING, 3463285ea10SEliot Blennerhassett "Message referencing invalid stream %d " 347719f82d3SEliot Blennerhassett "on adapter index %d\n", phm->obj_index, 348719f82d3SEliot Blennerhassett phm->adapter_index); 349719f82d3SEliot Blennerhassett return; 350719f82d3SEliot Blennerhassett } 351719f82d3SEliot Blennerhassett 352719f82d3SEliot Blennerhassett switch (phm->function) { 353719f82d3SEliot Blennerhassett case HPI_ISTREAM_READ: 354719f82d3SEliot Blennerhassett instream_read(pao, phm, phr); 355719f82d3SEliot Blennerhassett break; 356719f82d3SEliot Blennerhassett case HPI_ISTREAM_GET_INFO: 357719f82d3SEliot Blennerhassett instream_get_info(pao, phm, phr); 358719f82d3SEliot Blennerhassett break; 359719f82d3SEliot Blennerhassett case HPI_ISTREAM_HOSTBUFFER_ALLOC: 360719f82d3SEliot Blennerhassett instream_host_buffer_allocate(pao, phm, phr); 361719f82d3SEliot Blennerhassett break; 362719f82d3SEliot Blennerhassett case HPI_ISTREAM_HOSTBUFFER_GET_INFO: 363719f82d3SEliot Blennerhassett instream_host_buffer_get_info(pao, phm, phr); 364719f82d3SEliot Blennerhassett break; 365719f82d3SEliot Blennerhassett case HPI_ISTREAM_HOSTBUFFER_FREE: 366719f82d3SEliot Blennerhassett instream_host_buffer_free(pao, phm, phr); 367719f82d3SEliot Blennerhassett break; 368719f82d3SEliot Blennerhassett case HPI_ISTREAM_START: 369719f82d3SEliot Blennerhassett instream_start(pao, phm, phr); 370719f82d3SEliot Blennerhassett break; 371719f82d3SEliot Blennerhassett default: 372719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 373719f82d3SEliot Blennerhassett break; 374719f82d3SEliot Blennerhassett } 375719f82d3SEliot Blennerhassett } 376719f82d3SEliot Blennerhassett 377719f82d3SEliot Blennerhassett /*****************************************************************************/ 378719f82d3SEliot Blennerhassett /** Entry point to this HPI backend 379719f82d3SEliot Blennerhassett * All calls to the HPI start here 380719f82d3SEliot Blennerhassett */ 38133162d2dSEliot Blennerhassett static 3826d0b898eSEliot Blennerhassett void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, 3836d0b898eSEliot Blennerhassett struct hpi_response *phr) 384719f82d3SEliot Blennerhassett { 3856d0b898eSEliot Blennerhassett if (pao && (pao->dsp_crashed >= 10) 386719f82d3SEliot Blennerhassett && (phm->function != HPI_ADAPTER_DEBUG_READ)) { 387719f82d3SEliot Blennerhassett /* allow last resort debug read even after crash */ 388719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 389719f82d3SEliot Blennerhassett HPI_ERROR_DSP_HARDWARE); 3906d0b898eSEliot Blennerhassett HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object, 3916d0b898eSEliot Blennerhassett phm->function); 392719f82d3SEliot Blennerhassett return; 393719f82d3SEliot Blennerhassett } 394719f82d3SEliot Blennerhassett 395719f82d3SEliot Blennerhassett /* Init default response */ 396719f82d3SEliot Blennerhassett if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) 3973285ea10SEliot Blennerhassett phr->error = HPI_ERROR_PROCESSING_MESSAGE; 398719f82d3SEliot Blennerhassett 399719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); 400719f82d3SEliot Blennerhassett switch (phm->type) { 40182b5774fSEliot Blennerhassett case HPI_TYPE_REQUEST: 402719f82d3SEliot Blennerhassett switch (phm->object) { 403719f82d3SEliot Blennerhassett case HPI_OBJ_SUBSYSTEM: 4046d0b898eSEliot Blennerhassett subsys_message(pao, phm, phr); 405719f82d3SEliot Blennerhassett break; 406719f82d3SEliot Blennerhassett 407719f82d3SEliot Blennerhassett case HPI_OBJ_ADAPTER: 408719f82d3SEliot Blennerhassett adapter_message(pao, phm, phr); 409719f82d3SEliot Blennerhassett break; 410719f82d3SEliot Blennerhassett 411719f82d3SEliot Blennerhassett case HPI_OBJ_CONTROL: 412719f82d3SEliot Blennerhassett control_message(pao, phm, phr); 413719f82d3SEliot Blennerhassett break; 414719f82d3SEliot Blennerhassett 415719f82d3SEliot Blennerhassett case HPI_OBJ_OSTREAM: 416719f82d3SEliot Blennerhassett outstream_message(pao, phm, phr); 417719f82d3SEliot Blennerhassett break; 418719f82d3SEliot Blennerhassett 419719f82d3SEliot Blennerhassett case HPI_OBJ_ISTREAM: 420719f82d3SEliot Blennerhassett instream_message(pao, phm, phr); 421719f82d3SEliot Blennerhassett break; 422719f82d3SEliot Blennerhassett 423719f82d3SEliot Blennerhassett default: 424719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 425719f82d3SEliot Blennerhassett break; 426719f82d3SEliot Blennerhassett } 427719f82d3SEliot Blennerhassett break; 428719f82d3SEliot Blennerhassett 429719f82d3SEliot Blennerhassett default: 430719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_TYPE; 431719f82d3SEliot Blennerhassett break; 432719f82d3SEliot Blennerhassett } 433719f82d3SEliot Blennerhassett } 434719f82d3SEliot Blennerhassett 4356d0b898eSEliot Blennerhassett void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) 4366d0b898eSEliot Blennerhassett { 4376d0b898eSEliot Blennerhassett struct hpi_adapter_obj *pao = NULL; 4386d0b898eSEliot Blennerhassett 4396d0b898eSEliot Blennerhassett if (phm->object != HPI_OBJ_SUBSYSTEM) { 4406d0b898eSEliot Blennerhassett /* normal messages must have valid adapter index */ 4416d0b898eSEliot Blennerhassett pao = hpi_find_adapter(phm->adapter_index); 4426d0b898eSEliot Blennerhassett } else { 4436d0b898eSEliot Blennerhassett /* subsys messages don't address an adapter */ 4446d0b898eSEliot Blennerhassett _HPI_6205(NULL, phm, phr); 4456d0b898eSEliot Blennerhassett return; 4466d0b898eSEliot Blennerhassett } 4476d0b898eSEliot Blennerhassett 4486d0b898eSEliot Blennerhassett if (pao) 4496d0b898eSEliot Blennerhassett _HPI_6205(pao, phm, phr); 4506d0b898eSEliot Blennerhassett else 4516d0b898eSEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 4526d0b898eSEliot Blennerhassett HPI_ERROR_BAD_ADAPTER_NUMBER); 4536d0b898eSEliot Blennerhassett } 4546d0b898eSEliot Blennerhassett 455719f82d3SEliot Blennerhassett /*****************************************************************************/ 456719f82d3SEliot Blennerhassett /* SUBSYSTEM */ 457719f82d3SEliot Blennerhassett 458719f82d3SEliot Blennerhassett /** Create an adapter object and initialise it based on resource information 459719f82d3SEliot Blennerhassett * passed in in the message 460719f82d3SEliot Blennerhassett * *** NOTE - you cannot use this function AND the FindAdapters function at the 461719f82d3SEliot Blennerhassett * same time, the application must use only one of them to get the adapters *** 462719f82d3SEliot Blennerhassett */ 463719f82d3SEliot Blennerhassett static void subsys_create_adapter(struct hpi_message *phm, 464719f82d3SEliot Blennerhassett struct hpi_response *phr) 465719f82d3SEliot Blennerhassett { 466719f82d3SEliot Blennerhassett /* create temp adapter obj, because we don't know what index yet */ 467719f82d3SEliot Blennerhassett struct hpi_adapter_obj ao; 468719f82d3SEliot Blennerhassett u32 os_error_code; 469719f82d3SEliot Blennerhassett u16 err; 470719f82d3SEliot Blennerhassett 471719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n"); 472719f82d3SEliot Blennerhassett 473719f82d3SEliot Blennerhassett memset(&ao, 0, sizeof(ao)); 474719f82d3SEliot Blennerhassett 475550a8b69SJulia Lawall ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); 476719f82d3SEliot Blennerhassett if (!ao.priv) { 47725985edcSLucas De Marchi HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); 478719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_MEMORY_ALLOC; 479719f82d3SEliot Blennerhassett return; 480719f82d3SEliot Blennerhassett } 481719f82d3SEliot Blennerhassett 482719f82d3SEliot Blennerhassett ao.pci = *phm->u.s.resource.r.pci; 483719f82d3SEliot Blennerhassett err = create_adapter_obj(&ao, &os_error_code); 484719f82d3SEliot Blennerhassett if (err) { 485719f82d3SEliot Blennerhassett delete_adapter_obj(&ao); 4860a00044dSEliot Blennerhassett if (err >= HPI_ERROR_BACKEND_BASE) { 4870a00044dSEliot Blennerhassett phr->error = HPI_ERROR_DSP_BOOTLOAD; 4880a00044dSEliot Blennerhassett phr->specific_error = err; 4890a00044dSEliot Blennerhassett } else { 490719f82d3SEliot Blennerhassett phr->error = err; 4910a00044dSEliot Blennerhassett } 4923285ea10SEliot Blennerhassett phr->u.s.data = os_error_code; 493719f82d3SEliot Blennerhassett return; 494719f82d3SEliot Blennerhassett } 495719f82d3SEliot Blennerhassett 4967036b92dSEliot Blennerhassett phr->u.s.adapter_type = ao.type; 497719f82d3SEliot Blennerhassett phr->u.s.adapter_index = ao.index; 498719f82d3SEliot Blennerhassett phr->error = 0; 499719f82d3SEliot Blennerhassett } 500719f82d3SEliot Blennerhassett 501719f82d3SEliot Blennerhassett /** delete an adapter - required by WDM driver */ 5026d0b898eSEliot Blennerhassett static void adapter_delete(struct hpi_adapter_obj *pao, 5036d0b898eSEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 504719f82d3SEliot Blennerhassett { 505719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw; 506719f82d3SEliot Blennerhassett 507719f82d3SEliot Blennerhassett if (!pao) { 508719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OBJ_INDEX; 509719f82d3SEliot Blennerhassett return; 510719f82d3SEliot Blennerhassett } 5117036b92dSEliot Blennerhassett phw = pao->priv; 512719f82d3SEliot Blennerhassett /* reset adapter h/w */ 513719f82d3SEliot Blennerhassett /* Reset C6713 #1 */ 514719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0); 515719f82d3SEliot Blennerhassett /* reset C6205 */ 516719f82d3SEliot Blennerhassett iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR); 517719f82d3SEliot Blennerhassett 518719f82d3SEliot Blennerhassett delete_adapter_obj(pao); 5193285ea10SEliot Blennerhassett hpi_delete_adapter(pao); 520719f82d3SEliot Blennerhassett phr->error = 0; 521719f82d3SEliot Blennerhassett } 522719f82d3SEliot Blennerhassett 523719f82d3SEliot Blennerhassett /** Create adapter object 524719f82d3SEliot Blennerhassett allocate buffers, bootload DSPs, initialise control cache 525719f82d3SEliot Blennerhassett */ 526719f82d3SEliot Blennerhassett static u16 create_adapter_obj(struct hpi_adapter_obj *pao, 527719f82d3SEliot Blennerhassett u32 *pos_error_code) 528719f82d3SEliot Blennerhassett { 529719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 530719f82d3SEliot Blennerhassett struct bus_master_interface *interface; 531719f82d3SEliot Blennerhassett u32 phys_addr; 532719f82d3SEliot Blennerhassett int i; 533719f82d3SEliot Blennerhassett u16 err; 534719f82d3SEliot Blennerhassett 535719f82d3SEliot Blennerhassett /* init error reporting */ 536719f82d3SEliot Blennerhassett pao->dsp_crashed = 0; 537719f82d3SEliot Blennerhassett 538719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) 539719f82d3SEliot Blennerhassett phw->flag_outstream_just_reset[i] = 1; 540719f82d3SEliot Blennerhassett 541719f82d3SEliot Blennerhassett /* The C6205 memory area 1 is 8Mbyte window into DSP registers */ 542719f82d3SEliot Blennerhassett phw->prHSR = 543719f82d3SEliot Blennerhassett pao->pci.ap_mem_base[1] + 544719f82d3SEliot Blennerhassett C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]); 545719f82d3SEliot Blennerhassett phw->prHDCR = 546719f82d3SEliot Blennerhassett pao->pci.ap_mem_base[1] + 547719f82d3SEliot Blennerhassett C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]); 548719f82d3SEliot Blennerhassett phw->prDSPP = 549719f82d3SEliot Blennerhassett pao->pci.ap_mem_base[1] + 550719f82d3SEliot Blennerhassett C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]); 551719f82d3SEliot Blennerhassett 552719f82d3SEliot Blennerhassett pao->has_control_cache = 0; 553719f82d3SEliot Blennerhassett 554719f82d3SEliot Blennerhassett if (hpios_locked_mem_alloc(&phw->h_locked_mem, 555719f82d3SEliot Blennerhassett sizeof(struct bus_master_interface), 5563285ea10SEliot Blennerhassett pao->pci.pci_dev)) 557719f82d3SEliot Blennerhassett phw->p_interface_buffer = NULL; 558719f82d3SEliot Blennerhassett else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem, 559719f82d3SEliot Blennerhassett (void *)&phw->p_interface_buffer)) 560719f82d3SEliot Blennerhassett phw->p_interface_buffer = NULL; 561719f82d3SEliot Blennerhassett 562719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n", 563719f82d3SEliot Blennerhassett phw->p_interface_buffer); 564719f82d3SEliot Blennerhassett 565719f82d3SEliot Blennerhassett if (phw->p_interface_buffer) { 566719f82d3SEliot Blennerhassett memset((void *)phw->p_interface_buffer, 0, 567719f82d3SEliot Blennerhassett sizeof(struct bus_master_interface)); 568719f82d3SEliot Blennerhassett phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN; 569719f82d3SEliot Blennerhassett } 570719f82d3SEliot Blennerhassett 571719f82d3SEliot Blennerhassett err = adapter_boot_load_dsp(pao, pos_error_code); 5726d0b898eSEliot Blennerhassett if (err) { 5736d0b898eSEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "DSP code load failed\n"); 574719f82d3SEliot Blennerhassett /* no need to clean up as SubSysCreateAdapter */ 575719f82d3SEliot Blennerhassett /* calls DeleteAdapter on error. */ 576719f82d3SEliot Blennerhassett return err; 5776d0b898eSEliot Blennerhassett } 578719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(INFO, "load DSP code OK\n"); 579719f82d3SEliot Blennerhassett 580719f82d3SEliot Blennerhassett /* allow boot load even if mem alloc wont work */ 581719f82d3SEliot Blennerhassett if (!phw->p_interface_buffer) 5823285ea10SEliot Blennerhassett return HPI_ERROR_MEMORY_ALLOC; 583719f82d3SEliot Blennerhassett 584719f82d3SEliot Blennerhassett interface = phw->p_interface_buffer; 585719f82d3SEliot Blennerhassett 586719f82d3SEliot Blennerhassett /* make sure the DSP has started ok */ 587719f82d3SEliot Blennerhassett if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) { 588719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n"); 5893285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_INIT_FAILED; 590719f82d3SEliot Blennerhassett } 591719f82d3SEliot Blennerhassett /* Note that *pao, *phw are zeroed after allocation, 592719f82d3SEliot Blennerhassett * so pointers and flags are NULL by default. 593719f82d3SEliot Blennerhassett * Allocate bus mastering control cache buffer and tell the DSP about it 594719f82d3SEliot Blennerhassett */ 595719f82d3SEliot Blennerhassett if (interface->control_cache.number_of_controls) { 5963285ea10SEliot Blennerhassett u8 *p_control_cache_virtual; 597719f82d3SEliot Blennerhassett 598719f82d3SEliot Blennerhassett err = hpios_locked_mem_alloc(&phw->h_control_cache, 599719f82d3SEliot Blennerhassett interface->control_cache.size_in_bytes, 6003285ea10SEliot Blennerhassett pao->pci.pci_dev); 601719f82d3SEliot Blennerhassett if (!err) 602719f82d3SEliot Blennerhassett err = hpios_locked_mem_get_virt_addr(&phw-> 6033285ea10SEliot Blennerhassett h_control_cache, 6043285ea10SEliot Blennerhassett (void *)&p_control_cache_virtual); 605719f82d3SEliot Blennerhassett if (!err) { 606719f82d3SEliot Blennerhassett memset(p_control_cache_virtual, 0, 607719f82d3SEliot Blennerhassett interface->control_cache.size_in_bytes); 608719f82d3SEliot Blennerhassett 609719f82d3SEliot Blennerhassett phw->p_cache = 610719f82d3SEliot Blennerhassett hpi_alloc_control_cache(interface-> 611719f82d3SEliot Blennerhassett control_cache.number_of_controls, 612719f82d3SEliot Blennerhassett interface->control_cache.size_in_bytes, 613719f82d3SEliot Blennerhassett p_control_cache_virtual); 6146d0b898eSEliot Blennerhassett 615fd0977d0SJesper Juhl if (!phw->p_cache) 616fd0977d0SJesper Juhl err = HPI_ERROR_MEMORY_ALLOC; 617719f82d3SEliot Blennerhassett } 618719f82d3SEliot Blennerhassett if (!err) { 619719f82d3SEliot Blennerhassett err = hpios_locked_mem_get_phys_addr(&phw-> 620719f82d3SEliot Blennerhassett h_control_cache, &phys_addr); 621719f82d3SEliot Blennerhassett interface->control_cache.physical_address32 = 622719f82d3SEliot Blennerhassett phys_addr; 623719f82d3SEliot Blennerhassett } 624719f82d3SEliot Blennerhassett 625719f82d3SEliot Blennerhassett if (!err) 626719f82d3SEliot Blennerhassett pao->has_control_cache = 1; 627719f82d3SEliot Blennerhassett else { 628719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->h_control_cache)) 629719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->h_control_cache); 630719f82d3SEliot Blennerhassett pao->has_control_cache = 0; 631719f82d3SEliot Blennerhassett } 632719f82d3SEliot Blennerhassett } 633719f82d3SEliot Blennerhassett send_dsp_command(phw, H620_HIF_IDLE); 634719f82d3SEliot Blennerhassett 635719f82d3SEliot Blennerhassett { 6363285ea10SEliot Blennerhassett struct hpi_message hm; 6373285ea10SEliot Blennerhassett struct hpi_response hr; 638719f82d3SEliot Blennerhassett u32 max_streams; 639719f82d3SEliot Blennerhassett 640719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); 6413285ea10SEliot Blennerhassett memset(&hm, 0, sizeof(hm)); 64282b5774fSEliot Blennerhassett /* wAdapterIndex == version == 0 */ 64382b5774fSEliot Blennerhassett hm.type = HPI_TYPE_REQUEST; 6443285ea10SEliot Blennerhassett hm.size = sizeof(hm); 6453285ea10SEliot Blennerhassett hm.object = HPI_OBJ_ADAPTER; 6463285ea10SEliot Blennerhassett hm.function = HPI_ADAPTER_GET_INFO; 64782b5774fSEliot Blennerhassett 6483285ea10SEliot Blennerhassett memset(&hr, 0, sizeof(hr)); 6493285ea10SEliot Blennerhassett hr.size = sizeof(hr); 650719f82d3SEliot Blennerhassett 6513285ea10SEliot Blennerhassett err = message_response_sequence(pao, &hm, &hr); 652719f82d3SEliot Blennerhassett if (err) { 653719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "message transport error %d\n", 654719f82d3SEliot Blennerhassett err); 655719f82d3SEliot Blennerhassett return err; 656719f82d3SEliot Blennerhassett } 6573285ea10SEliot Blennerhassett if (hr.error) 6583285ea10SEliot Blennerhassett return hr.error; 659719f82d3SEliot Blennerhassett 6607036b92dSEliot Blennerhassett pao->type = hr.u.ax.info.adapter_type; 6613285ea10SEliot Blennerhassett pao->index = hr.u.ax.info.adapter_index; 662719f82d3SEliot Blennerhassett 6633285ea10SEliot Blennerhassett max_streams = 6643285ea10SEliot Blennerhassett hr.u.ax.info.num_outstreams + 6653285ea10SEliot Blennerhassett hr.u.ax.info.num_instreams; 666719f82d3SEliot Blennerhassett 667719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, 668719f82d3SEliot Blennerhassett "got adapter info type %x index %d serial %d\n", 6693285ea10SEliot Blennerhassett hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, 6703285ea10SEliot Blennerhassett hr.u.ax.info.serial_number); 671719f82d3SEliot Blennerhassett } 672719f82d3SEliot Blennerhassett 673ffdb5787SEliot Blennerhassett if (phw->p_cache) 674ffdb5787SEliot Blennerhassett phw->p_cache->adap_idx = pao->index; 675ffdb5787SEliot Blennerhassett 676719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); 6773285ea10SEliot Blennerhassett 678*f9a376c3SEliot Blennerhassett pao->irq_query_and_clear = adapter_irq_query_and_clear; 679*f9a376c3SEliot Blennerhassett pao->instream_host_buffer_status = 680*f9a376c3SEliot Blennerhassett phw->p_interface_buffer->instream_host_buffer_status; 681*f9a376c3SEliot Blennerhassett pao->outstream_host_buffer_status = 682*f9a376c3SEliot Blennerhassett phw->p_interface_buffer->outstream_host_buffer_status; 683*f9a376c3SEliot Blennerhassett 6843285ea10SEliot Blennerhassett return hpi_add_adapter(pao); 685719f82d3SEliot Blennerhassett } 686719f82d3SEliot Blennerhassett 687719f82d3SEliot Blennerhassett /** Free memory areas allocated by adapter 6886d0b898eSEliot Blennerhassett * this routine is called from AdapterDelete, 689719f82d3SEliot Blennerhassett * and SubSysCreateAdapter if duplicate index 690719f82d3SEliot Blennerhassett */ 691719f82d3SEliot Blennerhassett static void delete_adapter_obj(struct hpi_adapter_obj *pao) 692719f82d3SEliot Blennerhassett { 6936d0b898eSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 694719f82d3SEliot Blennerhassett int i; 695719f82d3SEliot Blennerhassett 696719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->h_control_cache)) { 697719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->h_control_cache); 698719f82d3SEliot Blennerhassett hpi_free_control_cache(phw->p_cache); 699719f82d3SEliot Blennerhassett } 700719f82d3SEliot Blennerhassett 701719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->h_locked_mem)) { 702719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->h_locked_mem); 703719f82d3SEliot Blennerhassett phw->p_interface_buffer = NULL; 704719f82d3SEliot Blennerhassett } 705719f82d3SEliot Blennerhassett 706719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) 707719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) { 708719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->instream_host_buffers[i]); 709719f82d3SEliot Blennerhassett /*?phw->InStreamHostBuffers[i] = NULL; */ 710719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[i] = 0; 711719f82d3SEliot Blennerhassett } 712719f82d3SEliot Blennerhassett 713719f82d3SEliot Blennerhassett for (i = 0; i < HPI_MAX_STREAMS; i++) 714719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) { 715719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->outstream_host_buffers 716719f82d3SEliot Blennerhassett [i]); 717719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[i] = 0; 718719f82d3SEliot Blennerhassett } 719719f82d3SEliot Blennerhassett kfree(phw); 720719f82d3SEliot Blennerhassett } 721719f82d3SEliot Blennerhassett 722719f82d3SEliot Blennerhassett /*****************************************************************************/ 7231d595d2aSEliot Blennerhassett /* Adapter functions */ 724*f9a376c3SEliot Blennerhassett static int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao, 725*f9a376c3SEliot Blennerhassett u32 message) 726*f9a376c3SEliot Blennerhassett { 727*f9a376c3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 728*f9a376c3SEliot Blennerhassett u32 hsr = 0; 729*f9a376c3SEliot Blennerhassett 730*f9a376c3SEliot Blennerhassett hsr = ioread32(phw->prHSR); 731*f9a376c3SEliot Blennerhassett if (hsr & C6205_HSR_INTSRC) { 732*f9a376c3SEliot Blennerhassett /* reset the interrupt from the DSP */ 733*f9a376c3SEliot Blennerhassett iowrite32(C6205_HSR_INTSRC, phw->prHSR); 734*f9a376c3SEliot Blennerhassett return HPI_IRQ_MIXER; 735*f9a376c3SEliot Blennerhassett } 736*f9a376c3SEliot Blennerhassett 737*f9a376c3SEliot Blennerhassett return HPI_IRQ_NONE; 738*f9a376c3SEliot Blennerhassett } 7391d595d2aSEliot Blennerhassett 7401d595d2aSEliot Blennerhassett /*****************************************************************************/ 741719f82d3SEliot Blennerhassett /* OutStream Host buffer functions */ 742719f82d3SEliot Blennerhassett 743719f82d3SEliot Blennerhassett /** Allocate or attach buffer for busmastering 744719f82d3SEliot Blennerhassett */ 745719f82d3SEliot Blennerhassett static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, 746719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 747719f82d3SEliot Blennerhassett { 748719f82d3SEliot Blennerhassett u16 err = 0; 749719f82d3SEliot Blennerhassett u32 command = phm->u.d.u.buffer.command; 750719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 751719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 752719f82d3SEliot Blennerhassett 753719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 754719f82d3SEliot Blennerhassett 755719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 756719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) { 757719f82d3SEliot Blennerhassett /* ALLOC phase, allocate a buffer with power of 2 size, 758719f82d3SEliot Blennerhassett get its bus address for PCI bus mastering 759719f82d3SEliot Blennerhassett */ 760719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size = 761719f82d3SEliot Blennerhassett roundup_pow_of_two(phm->u.d.u.buffer.buffer_size); 762719f82d3SEliot Blennerhassett /* return old size and allocated size, 763719f82d3SEliot Blennerhassett so caller can detect change */ 764719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.data_available = 765719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index]; 766719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.buffer_size = 767719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size; 768719f82d3SEliot Blennerhassett 769719f82d3SEliot Blennerhassett if (phw->outstream_host_buffer_size[phm->obj_index] == 770719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size) { 771719f82d3SEliot Blennerhassett /* Same size, no action required */ 772719f82d3SEliot Blennerhassett return; 773719f82d3SEliot Blennerhassett } 774719f82d3SEliot Blennerhassett 775719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> 776719f82d3SEliot Blennerhassett obj_index])) 777719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->outstream_host_buffers 778719f82d3SEliot Blennerhassett [phm->obj_index]); 779719f82d3SEliot Blennerhassett 780719f82d3SEliot Blennerhassett err = hpios_locked_mem_alloc(&phw->outstream_host_buffers 781719f82d3SEliot Blennerhassett [phm->obj_index], phm->u.d.u.buffer.buffer_size, 7823285ea10SEliot Blennerhassett pao->pci.pci_dev); 783719f82d3SEliot Blennerhassett 784719f82d3SEliot Blennerhassett if (err) { 785719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 786719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index] = 0; 787719f82d3SEliot Blennerhassett return; 788719f82d3SEliot Blennerhassett } 789719f82d3SEliot Blennerhassett 790719f82d3SEliot Blennerhassett err = hpios_locked_mem_get_phys_addr 791719f82d3SEliot Blennerhassett (&phw->outstream_host_buffers[phm->obj_index], 792719f82d3SEliot Blennerhassett &phm->u.d.u.buffer.pci_address); 793719f82d3SEliot Blennerhassett /* get the phys addr into msg for single call alloc caller 794719f82d3SEliot Blennerhassett * needs to do this for split alloc (or use the same message) 795719f82d3SEliot Blennerhassett * return the phy address for split alloc in the respose too 796719f82d3SEliot Blennerhassett */ 797719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.auxiliary_data_available = 798719f82d3SEliot Blennerhassett phm->u.d.u.buffer.pci_address; 799719f82d3SEliot Blennerhassett 800719f82d3SEliot Blennerhassett if (err) { 801719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->outstream_host_buffers 802719f82d3SEliot Blennerhassett [phm->obj_index]); 803719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index] = 0; 804719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_MEMORY_ALLOC; 805719f82d3SEliot Blennerhassett return; 806719f82d3SEliot Blennerhassett } 807719f82d3SEliot Blennerhassett } 808719f82d3SEliot Blennerhassett 809719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 810719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) { 811719f82d3SEliot Blennerhassett /* GRANT phase. Set up the BBM status, tell the DSP about 812719f82d3SEliot Blennerhassett the buffer so it can start using BBM. 813719f82d3SEliot Blennerhassett */ 814719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 815719f82d3SEliot Blennerhassett 816719f82d3SEliot Blennerhassett if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. 817719f82d3SEliot Blennerhassett buffer_size - 1)) { 818719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 8193285ea10SEliot Blennerhassett "Buffer size must be 2^N not %d\n", 820719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size); 821719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 822719f82d3SEliot Blennerhassett return; 823719f82d3SEliot Blennerhassett } 824719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index] = 825719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size; 826719f82d3SEliot Blennerhassett status = &interface->outstream_host_buffer_status[phm-> 827719f82d3SEliot Blennerhassett obj_index]; 828719f82d3SEliot Blennerhassett status->samples_processed = 0; 829719f82d3SEliot Blennerhassett status->stream_state = HPI_STATE_STOPPED; 8308e0874eaSEliot Blennerhassett status->dsp_index = 0; 8318e0874eaSEliot Blennerhassett status->host_index = status->dsp_index; 832719f82d3SEliot Blennerhassett status->size_in_bytes = phm->u.d.u.buffer.buffer_size; 833deb21a23SEliot Blennerhassett status->auxiliary_data_available = 0; 834719f82d3SEliot Blennerhassett 835719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 836719f82d3SEliot Blennerhassett 837719f82d3SEliot Blennerhassett if (phr->error 838719f82d3SEliot Blennerhassett && hpios_locked_mem_valid(&phw-> 839719f82d3SEliot Blennerhassett outstream_host_buffers[phm->obj_index])) { 840719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->outstream_host_buffers 841719f82d3SEliot Blennerhassett [phm->obj_index]); 842719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index] = 0; 843719f82d3SEliot Blennerhassett } 844719f82d3SEliot Blennerhassett } 845719f82d3SEliot Blennerhassett } 846719f82d3SEliot Blennerhassett 847719f82d3SEliot Blennerhassett static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao, 848719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 849719f82d3SEliot Blennerhassett { 850719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 851719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 852719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 853719f82d3SEliot Blennerhassett u8 *p_bbm_data; 854719f82d3SEliot Blennerhassett 855719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> 856719f82d3SEliot Blennerhassett obj_index])) { 857719f82d3SEliot Blennerhassett if (hpios_locked_mem_get_virt_addr(&phw-> 858719f82d3SEliot Blennerhassett outstream_host_buffers[phm->obj_index], 859719f82d3SEliot Blennerhassett (void *)&p_bbm_data)) { 860719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OPERATION; 861719f82d3SEliot Blennerhassett return; 862719f82d3SEliot Blennerhassett } 863719f82d3SEliot Blennerhassett status = &interface->outstream_host_buffer_status[phm-> 864719f82d3SEliot Blennerhassett obj_index]; 865719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, 866719f82d3SEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0); 867719f82d3SEliot Blennerhassett phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data; 868719f82d3SEliot Blennerhassett phr->u.d.u.hostbuffer_info.p_status = status; 869719f82d3SEliot Blennerhassett } else { 870719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, 871719f82d3SEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_GET_INFO, 872719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OPERATION); 873719f82d3SEliot Blennerhassett } 874719f82d3SEliot Blennerhassett } 875719f82d3SEliot Blennerhassett 876719f82d3SEliot Blennerhassett static void outstream_host_buffer_free(struct hpi_adapter_obj *pao, 877719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 878719f82d3SEliot Blennerhassett { 879719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 880719f82d3SEliot Blennerhassett u32 command = phm->u.d.u.buffer.command; 881719f82d3SEliot Blennerhassett 882719f82d3SEliot Blennerhassett if (phw->outstream_host_buffer_size[phm->obj_index]) { 883719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 884719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) { 885719f82d3SEliot Blennerhassett phw->outstream_host_buffer_size[phm->obj_index] = 0; 886719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 887719f82d3SEliot Blennerhassett /* Tell adapter to stop using the host buffer. */ 888719f82d3SEliot Blennerhassett } 889719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 890719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_FREE) 891719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->outstream_host_buffers 892719f82d3SEliot Blennerhassett [phm->obj_index]); 893719f82d3SEliot Blennerhassett } 894719f82d3SEliot Blennerhassett /* Should HPI_ERROR_INVALID_OPERATION be returned 895719f82d3SEliot Blennerhassett if no host buffer is allocated? */ 896719f82d3SEliot Blennerhassett else 897719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_OSTREAM, 898719f82d3SEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_FREE, 0); 899719f82d3SEliot Blennerhassett 900719f82d3SEliot Blennerhassett } 901719f82d3SEliot Blennerhassett 90260f1deb5SEliot Blennerhassett static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status) 903719f82d3SEliot Blennerhassett { 9042a383cb3SEliot Blennerhassett return status->size_in_bytes - (status->host_index - 9058e0874eaSEliot Blennerhassett status->dsp_index); 906719f82d3SEliot Blennerhassett } 907719f82d3SEliot Blennerhassett 908719f82d3SEliot Blennerhassett static void outstream_write(struct hpi_adapter_obj *pao, 909719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 910719f82d3SEliot Blennerhassett { 911719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 912719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 913719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 9142a383cb3SEliot Blennerhassett u32 space_available; 915719f82d3SEliot Blennerhassett 916719f82d3SEliot Blennerhassett if (!phw->outstream_host_buffer_size[phm->obj_index]) { 917719f82d3SEliot Blennerhassett /* there is no BBM buffer, write via message */ 918719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 919719f82d3SEliot Blennerhassett return; 920719f82d3SEliot Blennerhassett } 921719f82d3SEliot Blennerhassett 922719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 923719f82d3SEliot Blennerhassett status = &interface->outstream_host_buffer_status[phm->obj_index]; 924719f82d3SEliot Blennerhassett 925719f82d3SEliot Blennerhassett space_available = outstream_get_space_available(status); 9262a383cb3SEliot Blennerhassett if (space_available < phm->u.d.u.data.data_size) { 927719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 928719f82d3SEliot Blennerhassett return; 929719f82d3SEliot Blennerhassett } 930719f82d3SEliot Blennerhassett 931719f82d3SEliot Blennerhassett /* HostBuffers is used to indicate host buffer is internally allocated. 932719f82d3SEliot Blennerhassett otherwise, assumed external, data written externally */ 933719f82d3SEliot Blennerhassett if (phm->u.d.u.data.pb_data 934719f82d3SEliot Blennerhassett && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> 935719f82d3SEliot Blennerhassett obj_index])) { 936719f82d3SEliot Blennerhassett u8 *p_bbm_data; 9372a383cb3SEliot Blennerhassett u32 l_first_write; 938719f82d3SEliot Blennerhassett u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; 939719f82d3SEliot Blennerhassett 940719f82d3SEliot Blennerhassett if (hpios_locked_mem_get_virt_addr(&phw-> 941719f82d3SEliot Blennerhassett outstream_host_buffers[phm->obj_index], 942719f82d3SEliot Blennerhassett (void *)&p_bbm_data)) { 943719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OPERATION; 944719f82d3SEliot Blennerhassett return; 945719f82d3SEliot Blennerhassett } 946719f82d3SEliot Blennerhassett 947719f82d3SEliot Blennerhassett /* either all data, 948719f82d3SEliot Blennerhassett or enough to fit from current to end of BBM buffer */ 949719f82d3SEliot Blennerhassett l_first_write = 950719f82d3SEliot Blennerhassett min(phm->u.d.u.data.data_size, 951719f82d3SEliot Blennerhassett status->size_in_bytes - 952719f82d3SEliot Blennerhassett (status->host_index & (status->size_in_bytes - 1))); 953719f82d3SEliot Blennerhassett 954719f82d3SEliot Blennerhassett memcpy(p_bbm_data + 955719f82d3SEliot Blennerhassett (status->host_index & (status->size_in_bytes - 1)), 956719f82d3SEliot Blennerhassett p_app_data, l_first_write); 957719f82d3SEliot Blennerhassett /* remaining data if any */ 958719f82d3SEliot Blennerhassett memcpy(p_bbm_data, p_app_data + l_first_write, 959719f82d3SEliot Blennerhassett phm->u.d.u.data.data_size - l_first_write); 960719f82d3SEliot Blennerhassett } 9613285ea10SEliot Blennerhassett 9623285ea10SEliot Blennerhassett /* 9633285ea10SEliot Blennerhassett * This version relies on the DSP code triggering an OStream buffer 9643285ea10SEliot Blennerhassett * update immediately following a SET_FORMAT call. The host has 965deb21a23SEliot Blennerhassett * already written data into the BBM buffer, but the DSP won't know 966deb21a23SEliot Blennerhassett * about it until dwHostIndex is adjusted. 9673285ea10SEliot Blennerhassett */ 9683285ea10SEliot Blennerhassett if (phw->flag_outstream_just_reset[phm->obj_index]) { 9693285ea10SEliot Blennerhassett /* Format can only change after reset. Must tell DSP. */ 9703285ea10SEliot Blennerhassett u16 function = phm->function; 9713285ea10SEliot Blennerhassett phw->flag_outstream_just_reset[phm->obj_index] = 0; 9723285ea10SEliot Blennerhassett phm->function = HPI_OSTREAM_SET_FORMAT; 9733285ea10SEliot Blennerhassett hw_message(pao, phm, phr); /* send the format to the DSP */ 9743285ea10SEliot Blennerhassett phm->function = function; 9753285ea10SEliot Blennerhassett if (phr->error) 9763285ea10SEliot Blennerhassett return; 9773285ea10SEliot Blennerhassett } 9783285ea10SEliot Blennerhassett 979719f82d3SEliot Blennerhassett status->host_index += phm->u.d.u.data.data_size; 980719f82d3SEliot Blennerhassett } 981719f82d3SEliot Blennerhassett 982719f82d3SEliot Blennerhassett static void outstream_get_info(struct hpi_adapter_obj *pao, 983719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 984719f82d3SEliot Blennerhassett { 985719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 986719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 987719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 988719f82d3SEliot Blennerhassett 989719f82d3SEliot Blennerhassett if (!phw->outstream_host_buffer_size[phm->obj_index]) { 990719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 991719f82d3SEliot Blennerhassett return; 992719f82d3SEliot Blennerhassett } 993719f82d3SEliot Blennerhassett 994719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 995719f82d3SEliot Blennerhassett 996719f82d3SEliot Blennerhassett status = &interface->outstream_host_buffer_status[phm->obj_index]; 997719f82d3SEliot Blennerhassett 998719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.state = (u16)status->stream_state; 999719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.samples_transferred = 1000719f82d3SEliot Blennerhassett status->samples_processed; 1001719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.buffer_size = status->size_in_bytes; 1002719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.data_available = 1003719f82d3SEliot Blennerhassett status->size_in_bytes - outstream_get_space_available(status); 1004719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.auxiliary_data_available = 1005719f82d3SEliot Blennerhassett status->auxiliary_data_available; 1006719f82d3SEliot Blennerhassett } 1007719f82d3SEliot Blennerhassett 1008719f82d3SEliot Blennerhassett static void outstream_start(struct hpi_adapter_obj *pao, 1009719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1010719f82d3SEliot Blennerhassett { 1011719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1012719f82d3SEliot Blennerhassett } 1013719f82d3SEliot Blennerhassett 1014719f82d3SEliot Blennerhassett static void outstream_reset(struct hpi_adapter_obj *pao, 1015719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1016719f82d3SEliot Blennerhassett { 1017719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1018719f82d3SEliot Blennerhassett phw->flag_outstream_just_reset[phm->obj_index] = 1; 1019719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1020719f82d3SEliot Blennerhassett } 1021719f82d3SEliot Blennerhassett 1022719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_adapter_obj *pao, 1023719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1024719f82d3SEliot Blennerhassett { 1025719f82d3SEliot Blennerhassett outstream_reset(pao, phm, phr); 1026719f82d3SEliot Blennerhassett } 1027719f82d3SEliot Blennerhassett 1028719f82d3SEliot Blennerhassett /*****************************************************************************/ 1029719f82d3SEliot Blennerhassett /* InStream Host buffer functions */ 1030719f82d3SEliot Blennerhassett 1031719f82d3SEliot Blennerhassett static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, 1032719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1033719f82d3SEliot Blennerhassett { 1034719f82d3SEliot Blennerhassett u16 err = 0; 1035719f82d3SEliot Blennerhassett u32 command = phm->u.d.u.buffer.command; 1036719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1037719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 1038719f82d3SEliot Blennerhassett 1039719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 1040719f82d3SEliot Blennerhassett 1041719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 1042719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) { 1043719f82d3SEliot Blennerhassett 1044719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size = 1045719f82d3SEliot Blennerhassett roundup_pow_of_two(phm->u.d.u.buffer.buffer_size); 1046719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.data_available = 1047719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index]; 1048719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.buffer_size = 1049719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size; 1050719f82d3SEliot Blennerhassett 1051719f82d3SEliot Blennerhassett if (phw->instream_host_buffer_size[phm->obj_index] == 1052719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size) { 1053719f82d3SEliot Blennerhassett /* Same size, no action required */ 1054719f82d3SEliot Blennerhassett return; 1055719f82d3SEliot Blennerhassett } 1056719f82d3SEliot Blennerhassett 1057719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> 1058719f82d3SEliot Blennerhassett obj_index])) 1059719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->instream_host_buffers 1060719f82d3SEliot Blennerhassett [phm->obj_index]); 1061719f82d3SEliot Blennerhassett 1062719f82d3SEliot Blennerhassett err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm-> 1063719f82d3SEliot Blennerhassett obj_index], phm->u.d.u.buffer.buffer_size, 10643285ea10SEliot Blennerhassett pao->pci.pci_dev); 1065719f82d3SEliot Blennerhassett 1066719f82d3SEliot Blennerhassett if (err) { 1067719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 1068719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index] = 0; 1069719f82d3SEliot Blennerhassett return; 1070719f82d3SEliot Blennerhassett } 1071719f82d3SEliot Blennerhassett 1072719f82d3SEliot Blennerhassett err = hpios_locked_mem_get_phys_addr 1073719f82d3SEliot Blennerhassett (&phw->instream_host_buffers[phm->obj_index], 1074719f82d3SEliot Blennerhassett &phm->u.d.u.buffer.pci_address); 1075719f82d3SEliot Blennerhassett /* get the phys addr into msg for single call alloc. Caller 1076719f82d3SEliot Blennerhassett needs to do this for split alloc so return the phy address */ 1077719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.auxiliary_data_available = 1078719f82d3SEliot Blennerhassett phm->u.d.u.buffer.pci_address; 1079719f82d3SEliot Blennerhassett if (err) { 1080719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->instream_host_buffers 1081719f82d3SEliot Blennerhassett [phm->obj_index]); 1082719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index] = 0; 1083719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_MEMORY_ALLOC; 1084719f82d3SEliot Blennerhassett return; 1085719f82d3SEliot Blennerhassett } 1086719f82d3SEliot Blennerhassett } 1087719f82d3SEliot Blennerhassett 1088719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 1089719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) { 1090719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 1091719f82d3SEliot Blennerhassett 1092719f82d3SEliot Blennerhassett if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. 1093719f82d3SEliot Blennerhassett buffer_size - 1)) { 1094719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 10953285ea10SEliot Blennerhassett "Buffer size must be 2^N not %d\n", 1096719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size); 1097719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 1098719f82d3SEliot Blennerhassett return; 1099719f82d3SEliot Blennerhassett } 1100719f82d3SEliot Blennerhassett 1101719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index] = 1102719f82d3SEliot Blennerhassett phm->u.d.u.buffer.buffer_size; 1103719f82d3SEliot Blennerhassett status = &interface->instream_host_buffer_status[phm-> 1104719f82d3SEliot Blennerhassett obj_index]; 1105719f82d3SEliot Blennerhassett status->samples_processed = 0; 1106719f82d3SEliot Blennerhassett status->stream_state = HPI_STATE_STOPPED; 11078e0874eaSEliot Blennerhassett status->dsp_index = 0; 11088e0874eaSEliot Blennerhassett status->host_index = status->dsp_index; 1109719f82d3SEliot Blennerhassett status->size_in_bytes = phm->u.d.u.buffer.buffer_size; 1110deb21a23SEliot Blennerhassett status->auxiliary_data_available = 0; 1111719f82d3SEliot Blennerhassett 1112719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1113ba3a9099SEliot Blennerhassett 1114719f82d3SEliot Blennerhassett if (phr->error 1115719f82d3SEliot Blennerhassett && hpios_locked_mem_valid(&phw-> 1116719f82d3SEliot Blennerhassett instream_host_buffers[phm->obj_index])) { 1117719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->instream_host_buffers 1118719f82d3SEliot Blennerhassett [phm->obj_index]); 1119719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index] = 0; 1120719f82d3SEliot Blennerhassett } 1121719f82d3SEliot Blennerhassett } 1122719f82d3SEliot Blennerhassett } 1123719f82d3SEliot Blennerhassett 1124719f82d3SEliot Blennerhassett static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao, 1125719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1126719f82d3SEliot Blennerhassett { 1127719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1128719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 1129719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 1130719f82d3SEliot Blennerhassett u8 *p_bbm_data; 1131719f82d3SEliot Blennerhassett 1132719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> 1133719f82d3SEliot Blennerhassett obj_index])) { 1134719f82d3SEliot Blennerhassett if (hpios_locked_mem_get_virt_addr(&phw-> 1135719f82d3SEliot Blennerhassett instream_host_buffers[phm->obj_index], 1136719f82d3SEliot Blennerhassett (void *)&p_bbm_data)) { 1137719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OPERATION; 1138719f82d3SEliot Blennerhassett return; 1139719f82d3SEliot Blennerhassett } 1140719f82d3SEliot Blennerhassett status = &interface->instream_host_buffer_status[phm-> 1141719f82d3SEliot Blennerhassett obj_index]; 1142719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, 1143719f82d3SEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0); 1144719f82d3SEliot Blennerhassett phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data; 1145719f82d3SEliot Blennerhassett phr->u.d.u.hostbuffer_info.p_status = status; 1146719f82d3SEliot Blennerhassett } else { 1147719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, 1148719f82d3SEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_GET_INFO, 1149719f82d3SEliot Blennerhassett HPI_ERROR_INVALID_OPERATION); 1150719f82d3SEliot Blennerhassett } 1151719f82d3SEliot Blennerhassett } 1152719f82d3SEliot Blennerhassett 1153719f82d3SEliot Blennerhassett static void instream_host_buffer_free(struct hpi_adapter_obj *pao, 1154719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1155719f82d3SEliot Blennerhassett { 1156719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1157719f82d3SEliot Blennerhassett u32 command = phm->u.d.u.buffer.command; 1158719f82d3SEliot Blennerhassett 1159719f82d3SEliot Blennerhassett if (phw->instream_host_buffer_size[phm->obj_index]) { 1160719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 1161719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) { 1162719f82d3SEliot Blennerhassett phw->instream_host_buffer_size[phm->obj_index] = 0; 1163719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1164719f82d3SEliot Blennerhassett } 1165719f82d3SEliot Blennerhassett 1166719f82d3SEliot Blennerhassett if (command == HPI_BUFFER_CMD_EXTERNAL 1167719f82d3SEliot Blennerhassett || command == HPI_BUFFER_CMD_INTERNAL_FREE) 1168719f82d3SEliot Blennerhassett hpios_locked_mem_free(&phw->instream_host_buffers 1169719f82d3SEliot Blennerhassett [phm->obj_index]); 1170719f82d3SEliot Blennerhassett 1171719f82d3SEliot Blennerhassett } else { 1172719f82d3SEliot Blennerhassett /* Should HPI_ERROR_INVALID_OPERATION be returned 1173719f82d3SEliot Blennerhassett if no host buffer is allocated? */ 1174719f82d3SEliot Blennerhassett hpi_init_response(phr, HPI_OBJ_ISTREAM, 1175719f82d3SEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_FREE, 0); 1176719f82d3SEliot Blennerhassett 1177719f82d3SEliot Blennerhassett } 1178719f82d3SEliot Blennerhassett 1179719f82d3SEliot Blennerhassett } 1180719f82d3SEliot Blennerhassett 1181719f82d3SEliot Blennerhassett static void instream_start(struct hpi_adapter_obj *pao, 1182719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1183719f82d3SEliot Blennerhassett { 1184719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1185719f82d3SEliot Blennerhassett } 1186719f82d3SEliot Blennerhassett 11872a383cb3SEliot Blennerhassett static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status) 1188719f82d3SEliot Blennerhassett { 11898e0874eaSEliot Blennerhassett return status->dsp_index - status->host_index; 1190719f82d3SEliot Blennerhassett } 1191719f82d3SEliot Blennerhassett 1192719f82d3SEliot Blennerhassett static void instream_read(struct hpi_adapter_obj *pao, 1193719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1194719f82d3SEliot Blennerhassett { 1195719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1196719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 1197719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 11982a383cb3SEliot Blennerhassett u32 data_available; 1199719f82d3SEliot Blennerhassett u8 *p_bbm_data; 12002a383cb3SEliot Blennerhassett u32 l_first_read; 1201719f82d3SEliot Blennerhassett u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; 1202719f82d3SEliot Blennerhassett 1203719f82d3SEliot Blennerhassett if (!phw->instream_host_buffer_size[phm->obj_index]) { 1204719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1205719f82d3SEliot Blennerhassett return; 1206719f82d3SEliot Blennerhassett } 1207719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 1208719f82d3SEliot Blennerhassett 1209719f82d3SEliot Blennerhassett status = &interface->instream_host_buffer_status[phm->obj_index]; 1210719f82d3SEliot Blennerhassett data_available = instream_get_bytes_available(status); 12112a383cb3SEliot Blennerhassett if (data_available < phm->u.d.u.data.data_size) { 1212719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_DATASIZE; 1213719f82d3SEliot Blennerhassett return; 1214719f82d3SEliot Blennerhassett } 1215719f82d3SEliot Blennerhassett 1216719f82d3SEliot Blennerhassett if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> 1217719f82d3SEliot Blennerhassett obj_index])) { 1218719f82d3SEliot Blennerhassett if (hpios_locked_mem_get_virt_addr(&phw-> 1219719f82d3SEliot Blennerhassett instream_host_buffers[phm->obj_index], 1220719f82d3SEliot Blennerhassett (void *)&p_bbm_data)) { 1221719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_OPERATION; 1222719f82d3SEliot Blennerhassett return; 1223719f82d3SEliot Blennerhassett } 1224719f82d3SEliot Blennerhassett 1225719f82d3SEliot Blennerhassett /* either all data, 1226719f82d3SEliot Blennerhassett or enough to fit from current to end of BBM buffer */ 1227719f82d3SEliot Blennerhassett l_first_read = 1228719f82d3SEliot Blennerhassett min(phm->u.d.u.data.data_size, 1229719f82d3SEliot Blennerhassett status->size_in_bytes - 1230719f82d3SEliot Blennerhassett (status->host_index & (status->size_in_bytes - 1))); 1231719f82d3SEliot Blennerhassett 1232719f82d3SEliot Blennerhassett memcpy(p_app_data, 1233719f82d3SEliot Blennerhassett p_bbm_data + 1234719f82d3SEliot Blennerhassett (status->host_index & (status->size_in_bytes - 1)), 1235719f82d3SEliot Blennerhassett l_first_read); 1236719f82d3SEliot Blennerhassett /* remaining data if any */ 1237719f82d3SEliot Blennerhassett memcpy(p_app_data + l_first_read, p_bbm_data, 1238719f82d3SEliot Blennerhassett phm->u.d.u.data.data_size - l_first_read); 1239719f82d3SEliot Blennerhassett } 1240719f82d3SEliot Blennerhassett status->host_index += phm->u.d.u.data.data_size; 1241719f82d3SEliot Blennerhassett } 1242719f82d3SEliot Blennerhassett 1243719f82d3SEliot Blennerhassett static void instream_get_info(struct hpi_adapter_obj *pao, 1244719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 1245719f82d3SEliot Blennerhassett { 1246719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1247719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 1248719f82d3SEliot Blennerhassett struct hpi_hostbuffer_status *status; 1249719f82d3SEliot Blennerhassett if (!phw->instream_host_buffer_size[phm->obj_index]) { 1250719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); 1251719f82d3SEliot Blennerhassett return; 1252719f82d3SEliot Blennerhassett } 1253719f82d3SEliot Blennerhassett 1254719f82d3SEliot Blennerhassett status = &interface->instream_host_buffer_status[phm->obj_index]; 1255719f82d3SEliot Blennerhassett 1256719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function, 0); 1257719f82d3SEliot Blennerhassett 1258719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.state = (u16)status->stream_state; 1259719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.samples_transferred = 1260719f82d3SEliot Blennerhassett status->samples_processed; 1261719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.buffer_size = status->size_in_bytes; 1262719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.data_available = 1263719f82d3SEliot Blennerhassett instream_get_bytes_available(status); 1264719f82d3SEliot Blennerhassett phr->u.d.u.stream_info.auxiliary_data_available = 1265719f82d3SEliot Blennerhassett status->auxiliary_data_available; 1266719f82d3SEliot Blennerhassett } 1267719f82d3SEliot Blennerhassett 1268719f82d3SEliot Blennerhassett /*****************************************************************************/ 1269719f82d3SEliot Blennerhassett /* LOW-LEVEL */ 1270719f82d3SEliot Blennerhassett #define HPI6205_MAX_FILES_TO_LOAD 2 1271719f82d3SEliot Blennerhassett 1272719f82d3SEliot Blennerhassett static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, 1273719f82d3SEliot Blennerhassett u32 *pos_error_code) 1274719f82d3SEliot Blennerhassett { 1275719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1276719f82d3SEliot Blennerhassett struct dsp_code dsp_code; 1277719f82d3SEliot Blennerhassett u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD]; 1278719f82d3SEliot Blennerhassett u32 temp; 1279719f82d3SEliot Blennerhassett int dsp = 0, i = 0; 1280719f82d3SEliot Blennerhassett u16 err = 0; 1281719f82d3SEliot Blennerhassett 1282719f82d3SEliot Blennerhassett boot_code_id[0] = HPI_ADAPTER_ASI(0x6205); 1283719f82d3SEliot Blennerhassett 1284ee246fc0SEliot Blennerhassett boot_code_id[1] = pao->pci.pci_dev->subsystem_device; 1285ee246fc0SEliot Blennerhassett boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]); 1286ee246fc0SEliot Blennerhassett 1287ee246fc0SEliot Blennerhassett /* fix up cases where bootcode id[1] != subsys id */ 1288ee246fc0SEliot Blennerhassett switch (boot_code_id[1]) { 1289719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x5000): 1290ee246fc0SEliot Blennerhassett boot_code_id[0] = boot_code_id[1]; 1291ee246fc0SEliot Blennerhassett boot_code_id[1] = 0; 1292719f82d3SEliot Blennerhassett break; 1293719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x5300): 1294719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x5400): 1295719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x6300): 1296ee246fc0SEliot Blennerhassett boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); 1297719f82d3SEliot Blennerhassett break; 12986d0b898eSEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x5500): 1299719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x5600): 1300719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x6500): 1301ee246fc0SEliot Blennerhassett boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); 1302719f82d3SEliot Blennerhassett break; 1303cadae428SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x8800): 1304ee246fc0SEliot Blennerhassett boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900); 1305ee246fc0SEliot Blennerhassett break; 1306ee246fc0SEliot Blennerhassett default: 1307cadae428SEliot Blennerhassett break; 1308719f82d3SEliot Blennerhassett } 1309719f82d3SEliot Blennerhassett 1310719f82d3SEliot Blennerhassett /* reset DSP by writing a 1 to the WARMRESET bit */ 1311719f82d3SEliot Blennerhassett temp = C6205_HDCR_WARMRESET; 1312719f82d3SEliot Blennerhassett iowrite32(temp, phw->prHDCR); 1313719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1314719f82d3SEliot Blennerhassett 1315719f82d3SEliot Blennerhassett /* check that PCI i/f was configured by EEPROM */ 1316719f82d3SEliot Blennerhassett temp = ioread32(phw->prHSR); 1317719f82d3SEliot Blennerhassett if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) != 1318719f82d3SEliot Blennerhassett C6205_HSR_EEREAD) 13193285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_EEPROM; 1320719f82d3SEliot Blennerhassett temp |= 0x04; 1321719f82d3SEliot Blennerhassett /* disable PINTA interrupt */ 1322719f82d3SEliot Blennerhassett iowrite32(temp, phw->prHSR); 1323719f82d3SEliot Blennerhassett 1324719f82d3SEliot Blennerhassett /* check control register reports PCI boot mode */ 1325719f82d3SEliot Blennerhassett temp = ioread32(phw->prHDCR); 1326719f82d3SEliot Blennerhassett if (!(temp & C6205_HDCR_PCIBOOT)) 13273285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_REG; 1328719f82d3SEliot Blennerhassett 13293285ea10SEliot Blennerhassett /* try writing a few numbers to the DSP page register */ 1330719f82d3SEliot Blennerhassett /* and reading them back. */ 1331719f82d3SEliot Blennerhassett temp = 3; 1332719f82d3SEliot Blennerhassett iowrite32(temp, phw->prDSPP); 1333719f82d3SEliot Blennerhassett if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) 13343285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_DSPPAGE; 13353285ea10SEliot Blennerhassett temp = 2; 13363285ea10SEliot Blennerhassett iowrite32(temp, phw->prDSPP); 13373285ea10SEliot Blennerhassett if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) 13383285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_DSPPAGE; 13393285ea10SEliot Blennerhassett temp = 1; 13403285ea10SEliot Blennerhassett iowrite32(temp, phw->prDSPP); 13413285ea10SEliot Blennerhassett if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) 13423285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_DSPPAGE; 1343719f82d3SEliot Blennerhassett /* reset DSP page to the correct number */ 1344719f82d3SEliot Blennerhassett temp = 0; 1345719f82d3SEliot Blennerhassett iowrite32(temp, phw->prDSPP); 1346719f82d3SEliot Blennerhassett if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) 13473285ea10SEliot Blennerhassett return HPI6205_ERROR_6205_DSPPAGE; 1348719f82d3SEliot Blennerhassett phw->dsp_page = 0; 1349719f82d3SEliot Blennerhassett 1350719f82d3SEliot Blennerhassett /* release 6713 from reset before 6205 is bootloaded. 1351719f82d3SEliot Blennerhassett This ensures that the EMIF is inactive, 1352719f82d3SEliot Blennerhassett and the 6713 HPI gets the correct bootmode etc 1353719f82d3SEliot Blennerhassett */ 1354719f82d3SEliot Blennerhassett if (boot_code_id[1] != 0) { 1355719f82d3SEliot Blennerhassett /* DSP 1 is a C6713 */ 1356719f82d3SEliot Blennerhassett /* CLKX0 <- '1' release the C6205 bootmode pulldowns */ 1357*f9a376c3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, 0x018C0024, 0x00002202); 1358719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(100); 1359719f82d3SEliot Blennerhassett /* Reset the 6713 #1 - revB */ 1360719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0); 1361*f9a376c3SEliot Blennerhassett /* value of bit 3 is unknown after DSP reset, other bits shoudl be 0 */ 1362*f9a376c3SEliot Blennerhassett if (0 != (boot_loader_read_mem32(pao, 0, 1363*f9a376c3SEliot Blennerhassett (C6205_BAR0_TIMER1_CTL)) & ~8)) 1364*f9a376c3SEliot Blennerhassett return HPI6205_ERROR_6205_REG; 1365719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(100); 1366*f9a376c3SEliot Blennerhassett 1367719f82d3SEliot Blennerhassett /* Release C6713 from reset - revB */ 1368719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4); 1369*f9a376c3SEliot Blennerhassett if (4 != (boot_loader_read_mem32(pao, 0, 1370*f9a376c3SEliot Blennerhassett (C6205_BAR0_TIMER1_CTL)) & ~8)) 1371*f9a376c3SEliot Blennerhassett return HPI6205_ERROR_6205_REG; 1372719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(100); 1373719f82d3SEliot Blennerhassett } 1374719f82d3SEliot Blennerhassett 1375719f82d3SEliot Blennerhassett for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) { 1376719f82d3SEliot Blennerhassett /* is there a DSP to load? */ 1377719f82d3SEliot Blennerhassett if (boot_code_id[dsp] == 0) 1378719f82d3SEliot Blennerhassett continue; 1379719f82d3SEliot Blennerhassett 1380719f82d3SEliot Blennerhassett err = boot_loader_config_emif(pao, dsp); 1381719f82d3SEliot Blennerhassett if (err) 1382719f82d3SEliot Blennerhassett return err; 1383719f82d3SEliot Blennerhassett 1384719f82d3SEliot Blennerhassett err = boot_loader_test_internal_memory(pao, dsp); 1385719f82d3SEliot Blennerhassett if (err) 1386719f82d3SEliot Blennerhassett return err; 1387719f82d3SEliot Blennerhassett 1388719f82d3SEliot Blennerhassett err = boot_loader_test_external_memory(pao, dsp); 1389719f82d3SEliot Blennerhassett if (err) 1390719f82d3SEliot Blennerhassett return err; 1391719f82d3SEliot Blennerhassett 1392719f82d3SEliot Blennerhassett err = boot_loader_test_pld(pao, dsp); 1393719f82d3SEliot Blennerhassett if (err) 1394719f82d3SEliot Blennerhassett return err; 1395719f82d3SEliot Blennerhassett 1396719f82d3SEliot Blennerhassett /* write the DSP code down into the DSPs memory */ 139795a4c6e7SEliot Blennerhassett err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev, 139895a4c6e7SEliot Blennerhassett &dsp_code, pos_error_code); 1399719f82d3SEliot Blennerhassett if (err) 1400719f82d3SEliot Blennerhassett return err; 1401719f82d3SEliot Blennerhassett 1402719f82d3SEliot Blennerhassett while (1) { 1403719f82d3SEliot Blennerhassett u32 length; 1404719f82d3SEliot Blennerhassett u32 address; 1405719f82d3SEliot Blennerhassett u32 type; 1406719f82d3SEliot Blennerhassett u32 *pcode; 1407719f82d3SEliot Blennerhassett 1408719f82d3SEliot Blennerhassett err = hpi_dsp_code_read_word(&dsp_code, &length); 1409719f82d3SEliot Blennerhassett if (err) 1410719f82d3SEliot Blennerhassett break; 1411719f82d3SEliot Blennerhassett if (length == 0xFFFFFFFF) 1412719f82d3SEliot Blennerhassett break; /* end of code */ 1413719f82d3SEliot Blennerhassett 1414719f82d3SEliot Blennerhassett err = hpi_dsp_code_read_word(&dsp_code, &address); 1415719f82d3SEliot Blennerhassett if (err) 1416719f82d3SEliot Blennerhassett break; 1417719f82d3SEliot Blennerhassett err = hpi_dsp_code_read_word(&dsp_code, &type); 1418719f82d3SEliot Blennerhassett if (err) 1419719f82d3SEliot Blennerhassett break; 1420719f82d3SEliot Blennerhassett err = hpi_dsp_code_read_block(length, &dsp_code, 1421719f82d3SEliot Blennerhassett &pcode); 1422719f82d3SEliot Blennerhassett if (err) 1423719f82d3SEliot Blennerhassett break; 1424719f82d3SEliot Blennerhassett for (i = 0; i < (int)length; i++) { 14253285ea10SEliot Blennerhassett boot_loader_write_mem32(pao, dsp, address, 14263285ea10SEliot Blennerhassett *pcode); 1427719f82d3SEliot Blennerhassett /* dummy read every 4 words */ 1428719f82d3SEliot Blennerhassett /* for 6205 advisory 1.4.4 */ 1429719f82d3SEliot Blennerhassett if (i % 4 == 0) 1430719f82d3SEliot Blennerhassett boot_loader_read_mem32(pao, dsp, 1431719f82d3SEliot Blennerhassett address); 1432719f82d3SEliot Blennerhassett pcode++; 1433719f82d3SEliot Blennerhassett address += 4; 1434719f82d3SEliot Blennerhassett } 1435719f82d3SEliot Blennerhassett 1436719f82d3SEliot Blennerhassett } 1437719f82d3SEliot Blennerhassett if (err) { 1438719f82d3SEliot Blennerhassett hpi_dsp_code_close(&dsp_code); 1439719f82d3SEliot Blennerhassett return err; 1440719f82d3SEliot Blennerhassett } 1441719f82d3SEliot Blennerhassett 1442719f82d3SEliot Blennerhassett /* verify code */ 1443719f82d3SEliot Blennerhassett hpi_dsp_code_rewind(&dsp_code); 1444719f82d3SEliot Blennerhassett while (1) { 1445719f82d3SEliot Blennerhassett u32 length = 0; 1446719f82d3SEliot Blennerhassett u32 address = 0; 1447719f82d3SEliot Blennerhassett u32 type = 0; 1448719f82d3SEliot Blennerhassett u32 *pcode = NULL; 1449719f82d3SEliot Blennerhassett u32 data = 0; 1450719f82d3SEliot Blennerhassett 1451719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &length); 1452719f82d3SEliot Blennerhassett if (length == 0xFFFFFFFF) 1453719f82d3SEliot Blennerhassett break; /* end of code */ 1454719f82d3SEliot Blennerhassett 1455719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &address); 1456719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &type); 1457719f82d3SEliot Blennerhassett hpi_dsp_code_read_block(length, &dsp_code, &pcode); 1458719f82d3SEliot Blennerhassett 1459719f82d3SEliot Blennerhassett for (i = 0; i < (int)length; i++) { 1460719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp, 1461719f82d3SEliot Blennerhassett address); 1462719f82d3SEliot Blennerhassett if (data != *pcode) { 1463719f82d3SEliot Blennerhassett err = 0; 1464719f82d3SEliot Blennerhassett break; 1465719f82d3SEliot Blennerhassett } 1466719f82d3SEliot Blennerhassett pcode++; 1467719f82d3SEliot Blennerhassett address += 4; 1468719f82d3SEliot Blennerhassett } 1469719f82d3SEliot Blennerhassett if (err) 1470719f82d3SEliot Blennerhassett break; 1471719f82d3SEliot Blennerhassett } 1472719f82d3SEliot Blennerhassett hpi_dsp_code_close(&dsp_code); 1473719f82d3SEliot Blennerhassett if (err) 1474719f82d3SEliot Blennerhassett return err; 1475719f82d3SEliot Blennerhassett } 1476719f82d3SEliot Blennerhassett 1477719f82d3SEliot Blennerhassett /* After bootloading all DSPs, start DSP0 running 1478719f82d3SEliot Blennerhassett * The DSP0 code will handle starting and synchronizing with its slaves 1479719f82d3SEliot Blennerhassett */ 1480719f82d3SEliot Blennerhassett if (phw->p_interface_buffer) { 1481719f82d3SEliot Blennerhassett /* we need to tell the card the physical PCI address */ 1482719f82d3SEliot Blennerhassett u32 physicalPC_iaddress; 1483719f82d3SEliot Blennerhassett struct bus_master_interface *interface = 1484719f82d3SEliot Blennerhassett phw->p_interface_buffer; 1485719f82d3SEliot Blennerhassett u32 host_mailbox_address_on_dsp; 1486719f82d3SEliot Blennerhassett u32 physicalPC_iaddress_verify = 0; 1487719f82d3SEliot Blennerhassett int time_out = 10; 1488719f82d3SEliot Blennerhassett /* set ack so we know when DSP is ready to go */ 1489719f82d3SEliot Blennerhassett /* (dwDspAck will be changed to HIF_RESET) */ 1490719f82d3SEliot Blennerhassett interface->dsp_ack = H620_HIF_UNKNOWN; 1491719f82d3SEliot Blennerhassett wmb(); /* ensure ack is written before dsp writes back */ 1492719f82d3SEliot Blennerhassett 1493719f82d3SEliot Blennerhassett err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem, 1494719f82d3SEliot Blennerhassett &physicalPC_iaddress); 1495719f82d3SEliot Blennerhassett 1496719f82d3SEliot Blennerhassett /* locate the host mailbox on the DSP. */ 1497719f82d3SEliot Blennerhassett host_mailbox_address_on_dsp = 0x80000000; 1498719f82d3SEliot Blennerhassett while ((physicalPC_iaddress != physicalPC_iaddress_verify) 1499719f82d3SEliot Blennerhassett && time_out--) { 15003285ea10SEliot Blennerhassett boot_loader_write_mem32(pao, 0, 1501719f82d3SEliot Blennerhassett host_mailbox_address_on_dsp, 1502719f82d3SEliot Blennerhassett physicalPC_iaddress); 1503719f82d3SEliot Blennerhassett physicalPC_iaddress_verify = 1504719f82d3SEliot Blennerhassett boot_loader_read_mem32(pao, 0, 1505719f82d3SEliot Blennerhassett host_mailbox_address_on_dsp); 1506719f82d3SEliot Blennerhassett } 1507719f82d3SEliot Blennerhassett } 1508719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n"); 1509719f82d3SEliot Blennerhassett /* enable interrupts */ 1510719f82d3SEliot Blennerhassett temp = ioread32(phw->prHSR); 1511719f82d3SEliot Blennerhassett temp &= ~(u32)C6205_HSR_INTAM; 1512719f82d3SEliot Blennerhassett iowrite32(temp, phw->prHSR); 1513719f82d3SEliot Blennerhassett 1514719f82d3SEliot Blennerhassett /* start code running... */ 1515719f82d3SEliot Blennerhassett temp = ioread32(phw->prHDCR); 1516719f82d3SEliot Blennerhassett temp |= (u32)C6205_HDCR_DSPINT; 1517719f82d3SEliot Blennerhassett iowrite32(temp, phw->prHDCR); 1518719f82d3SEliot Blennerhassett 1519719f82d3SEliot Blennerhassett /* give the DSP 10ms to start up */ 1520719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(10000); 1521719f82d3SEliot Blennerhassett return err; 1522719f82d3SEliot Blennerhassett 1523719f82d3SEliot Blennerhassett } 1524719f82d3SEliot Blennerhassett 1525719f82d3SEliot Blennerhassett /*****************************************************************************/ 1526719f82d3SEliot Blennerhassett /* Bootloader utility functions */ 1527719f82d3SEliot Blennerhassett 1528719f82d3SEliot Blennerhassett static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, 1529719f82d3SEliot Blennerhassett u32 address) 1530719f82d3SEliot Blennerhassett { 1531719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1532719f82d3SEliot Blennerhassett u32 data = 0; 1533719f82d3SEliot Blennerhassett __iomem u32 *p_data; 1534719f82d3SEliot Blennerhassett 1535719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1536719f82d3SEliot Blennerhassett /* DSP 0 is always C6205 */ 1537719f82d3SEliot Blennerhassett if ((address >= 0x01800000) & (address < 0x02000000)) { 1538719f82d3SEliot Blennerhassett /* BAR1 register access */ 1539719f82d3SEliot Blennerhassett p_data = pao->pci.ap_mem_base[1] + 1540719f82d3SEliot Blennerhassett (address & 0x007fffff) / 1541719f82d3SEliot Blennerhassett sizeof(*pao->pci.ap_mem_base[1]); 1542719f82d3SEliot Blennerhassett /* HPI_DEBUG_LOG(WARNING, 1543719f82d3SEliot Blennerhassett "BAR1 access %08x\n", dwAddress); */ 1544719f82d3SEliot Blennerhassett } else { 1545719f82d3SEliot Blennerhassett u32 dw4M_page = address >> 22L; 1546719f82d3SEliot Blennerhassett if (dw4M_page != phw->dsp_page) { 1547719f82d3SEliot Blennerhassett phw->dsp_page = dw4M_page; 1548719f82d3SEliot Blennerhassett /* *INDENT OFF* */ 1549719f82d3SEliot Blennerhassett iowrite32(phw->dsp_page, phw->prDSPP); 1550719f82d3SEliot Blennerhassett /* *INDENT-ON* */ 1551719f82d3SEliot Blennerhassett } 1552719f82d3SEliot Blennerhassett address &= 0x3fffff; /* address within 4M page */ 1553719f82d3SEliot Blennerhassett /* BAR0 memory access */ 1554719f82d3SEliot Blennerhassett p_data = pao->pci.ap_mem_base[0] + 1555719f82d3SEliot Blennerhassett address / sizeof(u32); 1556719f82d3SEliot Blennerhassett } 1557719f82d3SEliot Blennerhassett data = ioread32(p_data); 1558719f82d3SEliot Blennerhassett } else if (dsp_index == 1) { 1559719f82d3SEliot Blennerhassett /* DSP 1 is a C6713 */ 1560719f82d3SEliot Blennerhassett u32 lsb; 1561719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address); 1562719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16); 1563719f82d3SEliot Blennerhassett lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR); 1564719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR); 1565719f82d3SEliot Blennerhassett data = (data << 16) | (lsb & 0xFFFF); 1566719f82d3SEliot Blennerhassett } 1567719f82d3SEliot Blennerhassett return data; 1568719f82d3SEliot Blennerhassett } 1569719f82d3SEliot Blennerhassett 15703285ea10SEliot Blennerhassett static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, 15713285ea10SEliot Blennerhassett int dsp_index, u32 address, u32 data) 1572719f82d3SEliot Blennerhassett { 1573719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 1574719f82d3SEliot Blennerhassett __iomem u32 *p_data; 1575719f82d3SEliot Blennerhassett /* u32 dwVerifyData=0; */ 1576719f82d3SEliot Blennerhassett 1577719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1578719f82d3SEliot Blennerhassett /* DSP 0 is always C6205 */ 1579719f82d3SEliot Blennerhassett if ((address >= 0x01800000) & (address < 0x02000000)) { 1580719f82d3SEliot Blennerhassett /* BAR1 - DSP register access using */ 1581719f82d3SEliot Blennerhassett /* Non-prefetchable PCI access */ 1582719f82d3SEliot Blennerhassett p_data = pao->pci.ap_mem_base[1] + 1583719f82d3SEliot Blennerhassett (address & 0x007fffff) / 1584719f82d3SEliot Blennerhassett sizeof(*pao->pci.ap_mem_base[1]); 1585719f82d3SEliot Blennerhassett } else { 1586719f82d3SEliot Blennerhassett /* BAR0 access - all of DSP memory using */ 1587719f82d3SEliot Blennerhassett /* pre-fetchable PCI access */ 1588719f82d3SEliot Blennerhassett u32 dw4M_page = address >> 22L; 1589719f82d3SEliot Blennerhassett if (dw4M_page != phw->dsp_page) { 1590719f82d3SEliot Blennerhassett phw->dsp_page = dw4M_page; 1591719f82d3SEliot Blennerhassett /* *INDENT-OFF* */ 1592719f82d3SEliot Blennerhassett iowrite32(phw->dsp_page, phw->prDSPP); 1593719f82d3SEliot Blennerhassett /* *INDENT-ON* */ 1594719f82d3SEliot Blennerhassett } 1595719f82d3SEliot Blennerhassett address &= 0x3fffff; /* address within 4M page */ 1596719f82d3SEliot Blennerhassett p_data = pao->pci.ap_mem_base[0] + 1597719f82d3SEliot Blennerhassett address / sizeof(u32); 1598719f82d3SEliot Blennerhassett } 1599719f82d3SEliot Blennerhassett iowrite32(data, p_data); 1600719f82d3SEliot Blennerhassett } else if (dsp_index == 1) { 1601719f82d3SEliot Blennerhassett /* DSP 1 is a C6713 */ 1602719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address); 1603719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16); 1604719f82d3SEliot Blennerhassett 1605719f82d3SEliot Blennerhassett /* dummy read every 4 words for 6205 advisory 1.4.4 */ 1606719f82d3SEliot Blennerhassett boot_loader_read_mem32(pao, 0, 0); 1607719f82d3SEliot Blennerhassett 1608719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data); 1609719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16); 1610719f82d3SEliot Blennerhassett 1611719f82d3SEliot Blennerhassett /* dummy read every 4 words for 6205 advisory 1.4.4 */ 1612719f82d3SEliot Blennerhassett boot_loader_read_mem32(pao, 0, 0); 16133285ea10SEliot Blennerhassett } 1614719f82d3SEliot Blennerhassett } 1615719f82d3SEliot Blennerhassett 1616719f82d3SEliot Blennerhassett static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) 1617719f82d3SEliot Blennerhassett { 1618719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1619719f82d3SEliot Blennerhassett u32 setting; 1620719f82d3SEliot Blennerhassett 1621719f82d3SEliot Blennerhassett /* DSP 0 is always C6205 */ 1622719f82d3SEliot Blennerhassett 1623719f82d3SEliot Blennerhassett /* Set the EMIF */ 1624719f82d3SEliot Blennerhassett /* memory map of C6205 */ 1625719f82d3SEliot Blennerhassett /* 00000000-0000FFFF 16Kx32 internal program */ 1626719f82d3SEliot Blennerhassett /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */ 1627719f82d3SEliot Blennerhassett 1628719f82d3SEliot Blennerhassett /* EMIF config */ 1629719f82d3SEliot Blennerhassett /*------------ */ 1630719f82d3SEliot Blennerhassett /* Global EMIF control */ 1631719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779); 1632719f82d3SEliot Blennerhassett #define WS_OFS 28 1633719f82d3SEliot Blennerhassett #define WST_OFS 22 1634719f82d3SEliot Blennerhassett #define WH_OFS 20 1635719f82d3SEliot Blennerhassett #define RS_OFS 16 1636719f82d3SEliot Blennerhassett #define RST_OFS 8 1637719f82d3SEliot Blennerhassett #define MTYPE_OFS 4 1638719f82d3SEliot Blennerhassett #define RH_OFS 0 1639719f82d3SEliot Blennerhassett 1640719f82d3SEliot Blennerhassett /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */ 1641719f82d3SEliot Blennerhassett setting = 0x00000030; 1642719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting); 1643719f82d3SEliot Blennerhassett if (setting != boot_loader_read_mem32(pao, dsp_index, 1644719f82d3SEliot Blennerhassett 0x01800008)) 16454e225e26SEliot Blennerhassett return HPI6205_ERROR_DSP_EMIF1; 1646719f82d3SEliot Blennerhassett 1647719f82d3SEliot Blennerhassett /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */ 1648719f82d3SEliot Blennerhassett /* which occupies D15..0. 6713 starts at 27MHz, so need */ 1649719f82d3SEliot Blennerhassett /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */ 1650719f82d3SEliot Blennerhassett /* WST should be 71, but 63 is max possible */ 1651719f82d3SEliot Blennerhassett setting = 1652719f82d3SEliot Blennerhassett (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) | 1653719f82d3SEliot Blennerhassett (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) | 1654719f82d3SEliot Blennerhassett (2L << MTYPE_OFS); 1655719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting); 1656719f82d3SEliot Blennerhassett if (setting != boot_loader_read_mem32(pao, dsp_index, 1657719f82d3SEliot Blennerhassett 0x01800004)) 16584e225e26SEliot Blennerhassett return HPI6205_ERROR_DSP_EMIF2; 1659719f82d3SEliot Blennerhassett 1660719f82d3SEliot Blennerhassett /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */ 1661719f82d3SEliot Blennerhassett /* which occupies D15..0. 6713 starts at 27MHz, so need */ 1662719f82d3SEliot Blennerhassett /* plenty of wait states */ 1663719f82d3SEliot Blennerhassett setting = 1664719f82d3SEliot Blennerhassett (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) | 1665719f82d3SEliot Blennerhassett (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) | 1666719f82d3SEliot Blennerhassett (2L << MTYPE_OFS); 1667719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting); 1668719f82d3SEliot Blennerhassett if (setting != boot_loader_read_mem32(pao, dsp_index, 1669719f82d3SEliot Blennerhassett 0x01800010)) 16704e225e26SEliot Blennerhassett return HPI6205_ERROR_DSP_EMIF3; 1671719f82d3SEliot Blennerhassett 1672719f82d3SEliot Blennerhassett /* EMIF CE3 setup - 32 bit async. */ 1673719f82d3SEliot Blennerhassett /* This is the PLD on the ASI5000 cards only */ 1674719f82d3SEliot Blennerhassett setting = 1675719f82d3SEliot Blennerhassett (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) | 1676719f82d3SEliot Blennerhassett (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) | 1677719f82d3SEliot Blennerhassett (2L << MTYPE_OFS); 1678719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting); 1679719f82d3SEliot Blennerhassett if (setting != boot_loader_read_mem32(pao, dsp_index, 1680719f82d3SEliot Blennerhassett 0x01800014)) 16814e225e26SEliot Blennerhassett return HPI6205_ERROR_DSP_EMIF4; 1682719f82d3SEliot Blennerhassett 1683719f82d3SEliot Blennerhassett /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */ 1684719f82d3SEliot Blennerhassett /* need to use this else DSP code crashes? */ 1685719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01800018, 1686719f82d3SEliot Blennerhassett 0x07117000); 1687719f82d3SEliot Blennerhassett 1688719f82d3SEliot Blennerhassett /* EMIF SDRAM Refresh Timing */ 1689719f82d3SEliot Blennerhassett /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */ 1690719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x0180001C, 1691719f82d3SEliot Blennerhassett 0x00000410); 1692719f82d3SEliot Blennerhassett 1693719f82d3SEliot Blennerhassett } else if (dsp_index == 1) { 1694719f82d3SEliot Blennerhassett /* test access to the C6713s HPI registers */ 1695719f82d3SEliot Blennerhassett u32 write_data = 0, read_data = 0, i = 0; 1696719f82d3SEliot Blennerhassett 1697719f82d3SEliot Blennerhassett /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */ 1698719f82d3SEliot Blennerhassett write_data = 1; 1699719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data); 1700719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data); 1701719f82d3SEliot Blennerhassett /* C67 HPI is on lower 16bits of 32bit EMIF */ 1702719f82d3SEliot Blennerhassett read_data = 1703719f82d3SEliot Blennerhassett 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR); 1704719f82d3SEliot Blennerhassett if (write_data != read_data) { 1705719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data, 1706719f82d3SEliot Blennerhassett read_data); 17073285ea10SEliot Blennerhassett return HPI6205_ERROR_C6713_HPIC; 1708719f82d3SEliot Blennerhassett } 1709719f82d3SEliot Blennerhassett /* HPIA - walking ones test */ 1710719f82d3SEliot Blennerhassett write_data = 1; 1711719f82d3SEliot Blennerhassett for (i = 0; i < 32; i++) { 1712719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAL_ADDR, 1713719f82d3SEliot Blennerhassett write_data); 1714719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, HPIAH_ADDR, 1715719f82d3SEliot Blennerhassett (write_data >> 16)); 1716719f82d3SEliot Blennerhassett read_data = 1717719f82d3SEliot Blennerhassett 0xFFFF & boot_loader_read_mem32(pao, 0, 1718719f82d3SEliot Blennerhassett HPIAL_ADDR); 1719719f82d3SEliot Blennerhassett read_data = 1720719f82d3SEliot Blennerhassett read_data | ((0xFFFF & 1721719f82d3SEliot Blennerhassett boot_loader_read_mem32(pao, 0, 1722719f82d3SEliot Blennerhassett HPIAH_ADDR)) 1723719f82d3SEliot Blennerhassett << 16); 1724719f82d3SEliot Blennerhassett if (read_data != write_data) { 1725719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n", 1726719f82d3SEliot Blennerhassett write_data, read_data); 17273285ea10SEliot Blennerhassett return HPI6205_ERROR_C6713_HPIA; 1728719f82d3SEliot Blennerhassett } 1729719f82d3SEliot Blennerhassett write_data = write_data << 1; 1730719f82d3SEliot Blennerhassett } 1731719f82d3SEliot Blennerhassett 1732719f82d3SEliot Blennerhassett /* setup C67x PLL 1733719f82d3SEliot Blennerhassett * ** C6713 datasheet says we cannot program PLL from HPI, 1734719f82d3SEliot Blennerhassett * and indeed if we try to set the PLL multiply from the HPI, 1735719f82d3SEliot Blennerhassett * the PLL does not seem to lock, so we enable the PLL and 1736719f82d3SEliot Blennerhassett * use the default multiply of x 7, which for a 27MHz clock 1737719f82d3SEliot Blennerhassett * gives a DSP speed of 189MHz 1738719f82d3SEliot Blennerhassett */ 1739719f82d3SEliot Blennerhassett /* bypass PLL */ 1740719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000); 1741719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1742719f82d3SEliot Blennerhassett /* EMIF = 189/3=63MHz */ 1743719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002); 1744719f82d3SEliot Blennerhassett /* peri = 189/2 */ 1745719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001); 1746719f82d3SEliot Blennerhassett /* cpu = 189/1 */ 1747719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000); 1748719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1749719f82d3SEliot Blennerhassett /* ** SGT test to take GPO3 high when we start the PLL */ 1750719f82d3SEliot Blennerhassett /* and low when the delay is completed */ 1751719f82d3SEliot Blennerhassett /* FSX0 <- '1' (GPO3) */ 1752719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A); 1753719f82d3SEliot Blennerhassett /* PLL not bypassed */ 1754719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001); 1755719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1756719f82d3SEliot Blennerhassett /* FSX0 <- '0' (GPO3) */ 1757719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02); 1758719f82d3SEliot Blennerhassett 1759719f82d3SEliot Blennerhassett /* 6205 EMIF CE1 resetup - 32 bit async. */ 1760719f82d3SEliot Blennerhassett /* Now 6713 #1 is running at 189MHz can reduce waitstates */ 1761719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */ 1762719f82d3SEliot Blennerhassett (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) | 1763719f82d3SEliot Blennerhassett (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) | 1764719f82d3SEliot Blennerhassett (2L << MTYPE_OFS)); 1765719f82d3SEliot Blennerhassett 1766719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1767719f82d3SEliot Blennerhassett 1768719f82d3SEliot Blennerhassett /* check that we can read one of the PLL registers */ 1769719f82d3SEliot Blennerhassett /* PLL should not be bypassed! */ 1770719f82d3SEliot Blennerhassett if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF) 1771719f82d3SEliot Blennerhassett != 0x0001) { 17723285ea10SEliot Blennerhassett return HPI6205_ERROR_C6713_PLL; 1773719f82d3SEliot Blennerhassett } 1774719f82d3SEliot Blennerhassett /* setup C67x EMIF (note this is the only use of 1775719f82d3SEliot Blennerhassett BAR1 via BootLoader_WriteMem32) */ 1776719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL, 1777719f82d3SEliot Blennerhassett 0x000034A8); 17781d595d2aSEliot Blennerhassett 17791d595d2aSEliot Blennerhassett /* EMIF CE0 setup - 2Mx32 Sync DRAM 17801d595d2aSEliot Blennerhassett 31..28 Wr setup 17811d595d2aSEliot Blennerhassett 27..22 Wr strobe 17821d595d2aSEliot Blennerhassett 21..20 Wr hold 17831d595d2aSEliot Blennerhassett 19..16 Rd setup 17841d595d2aSEliot Blennerhassett 15..14 - 17851d595d2aSEliot Blennerhassett 13..8 Rd strobe 17861d595d2aSEliot Blennerhassett 7..4 MTYPE 0011 Sync DRAM 32bits 17871d595d2aSEliot Blennerhassett 3 Wr hold MSB 17881d595d2aSEliot Blennerhassett 2..0 Rd hold 17891d595d2aSEliot Blennerhassett */ 1790719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0, 1791719f82d3SEliot Blennerhassett 0x00000030); 17921d595d2aSEliot Blennerhassett 17931d595d2aSEliot Blennerhassett /* EMIF SDRAM Extension 17941d595d2aSEliot Blennerhassett 0x00 17951d595d2aSEliot Blennerhassett 31-21 0000b 0000b 000b 17961d595d2aSEliot Blennerhassett 20 WR2RD = 2cycles-1 = 1b 17971d595d2aSEliot Blennerhassett 17981d595d2aSEliot Blennerhassett 19-18 WR2DEAC = 3cycle-1 = 10b 17991d595d2aSEliot Blennerhassett 17 WR2WR = 2cycle-1 = 1b 18001d595d2aSEliot Blennerhassett 16-15 R2WDQM = 4cycle-1 = 11b 18011d595d2aSEliot Blennerhassett 14-12 RD2WR = 6cycles-1 = 101b 18021d595d2aSEliot Blennerhassett 18031d595d2aSEliot Blennerhassett 11-10 RD2DEAC = 4cycle-1 = 11b 18041d595d2aSEliot Blennerhassett 9 RD2RD = 2cycle-1 = 1b 18051d595d2aSEliot Blennerhassett 8-7 THZP = 3cycle-1 = 10b 18061d595d2aSEliot Blennerhassett 6-5 TWR = 2cycle-1 = 01b (tWR = 17ns) 18071d595d2aSEliot Blennerhassett 4 TRRD = 2cycle = 0b (tRRD = 14ns) 18081d595d2aSEliot Blennerhassett 3-1 TRAS = 5cycle-1 = 100b (Tras=42ns) 18091d595d2aSEliot Blennerhassett 1 CAS latency = 3cyc = 1b 18101d595d2aSEliot Blennerhassett (for Micron 2M32-7 operating at 100MHz) 18111d595d2aSEliot Blennerhassett */ 1812719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT, 1813719f82d3SEliot Blennerhassett 0x001BDF29); 18141d595d2aSEliot Blennerhassett 18151d595d2aSEliot Blennerhassett /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank) 18161d595d2aSEliot Blennerhassett 31 - 0b - 18171d595d2aSEliot Blennerhassett 30 SDBSZ 1b 4 bank 18181d595d2aSEliot Blennerhassett 29..28 SDRSZ 00b 11 row address pins 18191d595d2aSEliot Blennerhassett 18201d595d2aSEliot Blennerhassett 27..26 SDCSZ 01b 8 column address pins 18211d595d2aSEliot Blennerhassett 25 RFEN 1b refersh enabled 18221d595d2aSEliot Blennerhassett 24 INIT 1b init SDRAM! 18231d595d2aSEliot Blennerhassett 18241d595d2aSEliot Blennerhassett 23..20 TRCD 0001b (Trcd/Tcyc)-1 = (20/10)-1 = 1 18251d595d2aSEliot Blennerhassett 18261d595d2aSEliot Blennerhassett 19..16 TRP 0001b (Trp/Tcyc)-1 = (20/10)-1 = 1 18271d595d2aSEliot Blennerhassett 18281d595d2aSEliot Blennerhassett 15..12 TRC 0110b (Trc/Tcyc)-1 = (70/10)-1 = 6 18291d595d2aSEliot Blennerhassett 18301d595d2aSEliot Blennerhassett 11..0 - 0000b 0000b 0000b 18311d595d2aSEliot Blennerhassett */ 1832719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL, 18331d595d2aSEliot Blennerhassett 0x47116000); 18341d595d2aSEliot Blennerhassett 18351d595d2aSEliot Blennerhassett /* SDRAM refresh timing 18361d595d2aSEliot Blennerhassett Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A 18371d595d2aSEliot Blennerhassett */ 1838719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 1839719f82d3SEliot Blennerhassett C6713_EMIF_SDRAMTIMING, 0x00000410); 1840719f82d3SEliot Blennerhassett 1841719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(1000); 1842719f82d3SEliot Blennerhassett } else if (dsp_index == 2) { 1843719f82d3SEliot Blennerhassett /* DSP 2 is a C6713 */ 18443285ea10SEliot Blennerhassett } 1845719f82d3SEliot Blennerhassett 18463285ea10SEliot Blennerhassett return 0; 1847719f82d3SEliot Blennerhassett } 1848719f82d3SEliot Blennerhassett 1849719f82d3SEliot Blennerhassett static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, 1850719f82d3SEliot Blennerhassett u32 start_address, u32 length) 1851719f82d3SEliot Blennerhassett { 1852719f82d3SEliot Blennerhassett u32 i = 0, j = 0; 1853719f82d3SEliot Blennerhassett u32 test_addr = 0; 1854719f82d3SEliot Blennerhassett u32 test_data = 0, data = 0; 1855719f82d3SEliot Blennerhassett 1856719f82d3SEliot Blennerhassett length = 1000; 1857719f82d3SEliot Blennerhassett 1858719f82d3SEliot Blennerhassett /* for 1st word, test each bit in the 32bit word, */ 1859719f82d3SEliot Blennerhassett /* dwLength specifies number of 32bit words to test */ 1860719f82d3SEliot Blennerhassett /*for(i=0; i<dwLength; i++) */ 1861719f82d3SEliot Blennerhassett i = 0; 1862719f82d3SEliot Blennerhassett { 1863719f82d3SEliot Blennerhassett test_addr = start_address + i * 4; 1864719f82d3SEliot Blennerhassett test_data = 0x00000001; 1865719f82d3SEliot Blennerhassett for (j = 0; j < 32; j++) { 1866719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, test_addr, 1867719f82d3SEliot Blennerhassett test_data); 1868719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp_index, 1869719f82d3SEliot Blennerhassett test_addr); 1870719f82d3SEliot Blennerhassett if (data != test_data) { 1871719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, 18723285ea10SEliot Blennerhassett "Memtest error details " 1873719f82d3SEliot Blennerhassett "%08x %08x %08x %i\n", test_addr, 1874719f82d3SEliot Blennerhassett test_data, data, dsp_index); 1875719f82d3SEliot Blennerhassett return 1; /* error */ 1876719f82d3SEliot Blennerhassett } 1877719f82d3SEliot Blennerhassett test_data = test_data << 1; 1878719f82d3SEliot Blennerhassett } /* for(j) */ 1879719f82d3SEliot Blennerhassett } /* for(i) */ 1880719f82d3SEliot Blennerhassett 1881719f82d3SEliot Blennerhassett /* for the next 100 locations test each location, leaving it as zero */ 1882719f82d3SEliot Blennerhassett /* write a zero to the next word in memory before we read */ 1883719f82d3SEliot Blennerhassett /* the previous write to make sure every memory location is unique */ 1884719f82d3SEliot Blennerhassett for (i = 0; i < 100; i++) { 1885719f82d3SEliot Blennerhassett test_addr = start_address + i * 4; 1886719f82d3SEliot Blennerhassett test_data = 0xA5A55A5A; 1887719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, test_addr, test_data); 1888719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0); 1889719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp_index, test_addr); 1890719f82d3SEliot Blennerhassett if (data != test_data) { 1891719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, 18923285ea10SEliot Blennerhassett "Memtest error details " 1893719f82d3SEliot Blennerhassett "%08x %08x %08x %i\n", test_addr, test_data, 1894719f82d3SEliot Blennerhassett data, dsp_index); 1895719f82d3SEliot Blennerhassett return 1; /* error */ 1896719f82d3SEliot Blennerhassett } 1897719f82d3SEliot Blennerhassett /* leave location as zero */ 1898719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0); 1899719f82d3SEliot Blennerhassett } 1900719f82d3SEliot Blennerhassett 1901719f82d3SEliot Blennerhassett /* zero out entire memory block */ 1902719f82d3SEliot Blennerhassett for (i = 0; i < length; i++) { 1903719f82d3SEliot Blennerhassett test_addr = start_address + i * 4; 1904719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0); 1905719f82d3SEliot Blennerhassett } 1906719f82d3SEliot Blennerhassett return 0; 1907719f82d3SEliot Blennerhassett } 1908719f82d3SEliot Blennerhassett 1909719f82d3SEliot Blennerhassett static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao, 1910719f82d3SEliot Blennerhassett int dsp_index) 1911719f82d3SEliot Blennerhassett { 1912719f82d3SEliot Blennerhassett int err = 0; 1913719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1914719f82d3SEliot Blennerhassett /* DSP 0 is a C6205 */ 1915719f82d3SEliot Blennerhassett /* 64K prog mem */ 1916719f82d3SEliot Blennerhassett err = boot_loader_test_memory(pao, dsp_index, 0x00000000, 1917719f82d3SEliot Blennerhassett 0x10000); 1918719f82d3SEliot Blennerhassett if (!err) 1919719f82d3SEliot Blennerhassett /* 64K data mem */ 1920719f82d3SEliot Blennerhassett err = boot_loader_test_memory(pao, dsp_index, 1921719f82d3SEliot Blennerhassett 0x80000000, 0x10000); 19223285ea10SEliot Blennerhassett } else if (dsp_index == 1) { 19233285ea10SEliot Blennerhassett /* DSP 1 is a C6713 */ 1924719f82d3SEliot Blennerhassett /* 192K internal mem */ 1925719f82d3SEliot Blennerhassett err = boot_loader_test_memory(pao, dsp_index, 0x00000000, 1926719f82d3SEliot Blennerhassett 0x30000); 1927719f82d3SEliot Blennerhassett if (!err) 1928719f82d3SEliot Blennerhassett /* 64K internal mem / L2 cache */ 1929719f82d3SEliot Blennerhassett err = boot_loader_test_memory(pao, dsp_index, 1930719f82d3SEliot Blennerhassett 0x00030000, 0x10000); 19313285ea10SEliot Blennerhassett } 1932719f82d3SEliot Blennerhassett 1933719f82d3SEliot Blennerhassett if (err) 19343285ea10SEliot Blennerhassett return HPI6205_ERROR_DSP_INTMEM; 1935719f82d3SEliot Blennerhassett else 1936719f82d3SEliot Blennerhassett return 0; 1937719f82d3SEliot Blennerhassett } 1938719f82d3SEliot Blennerhassett 1939719f82d3SEliot Blennerhassett static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao, 1940719f82d3SEliot Blennerhassett int dsp_index) 1941719f82d3SEliot Blennerhassett { 1942719f82d3SEliot Blennerhassett u32 dRAM_start_address = 0; 1943719f82d3SEliot Blennerhassett u32 dRAM_size = 0; 1944719f82d3SEliot Blennerhassett 1945719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1946719f82d3SEliot Blennerhassett /* only test for SDRAM if an ASI5000 card */ 19473285ea10SEliot Blennerhassett if (pao->pci.pci_dev->subsystem_device == 0x5000) { 1948719f82d3SEliot Blennerhassett /* DSP 0 is always C6205 */ 1949719f82d3SEliot Blennerhassett dRAM_start_address = 0x00400000; 1950719f82d3SEliot Blennerhassett dRAM_size = 0x200000; 1951719f82d3SEliot Blennerhassett /*dwDRAMinc=1024; */ 1952719f82d3SEliot Blennerhassett } else 1953719f82d3SEliot Blennerhassett return 0; 19543285ea10SEliot Blennerhassett } else if (dsp_index == 1) { 1955719f82d3SEliot Blennerhassett /* DSP 1 is a C6713 */ 1956719f82d3SEliot Blennerhassett dRAM_start_address = 0x80000000; 1957719f82d3SEliot Blennerhassett dRAM_size = 0x200000; 1958719f82d3SEliot Blennerhassett /*dwDRAMinc=1024; */ 19593285ea10SEliot Blennerhassett } 1960719f82d3SEliot Blennerhassett 1961719f82d3SEliot Blennerhassett if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address, 1962719f82d3SEliot Blennerhassett dRAM_size)) 19633285ea10SEliot Blennerhassett return HPI6205_ERROR_DSP_EXTMEM; 1964719f82d3SEliot Blennerhassett return 0; 1965719f82d3SEliot Blennerhassett } 1966719f82d3SEliot Blennerhassett 1967719f82d3SEliot Blennerhassett static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index) 1968719f82d3SEliot Blennerhassett { 1969719f82d3SEliot Blennerhassett u32 data = 0; 1970719f82d3SEliot Blennerhassett if (dsp_index == 0) { 1971719f82d3SEliot Blennerhassett /* only test for DSP0 PLD on ASI5000 card */ 19723285ea10SEliot Blennerhassett if (pao->pci.pci_dev->subsystem_device == 0x5000) { 1973719f82d3SEliot Blennerhassett /* PLD is located at CE3=0x03000000 */ 1974719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp_index, 1975719f82d3SEliot Blennerhassett 0x03000008); 1976719f82d3SEliot Blennerhassett if ((data & 0xF) != 0x5) 19773285ea10SEliot Blennerhassett return HPI6205_ERROR_DSP_PLD; 1978719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp_index, 1979719f82d3SEliot Blennerhassett 0x0300000C); 1980719f82d3SEliot Blennerhassett if ((data & 0xF) != 0xA) 19813285ea10SEliot Blennerhassett return HPI6205_ERROR_DSP_PLD; 1982719f82d3SEliot Blennerhassett } 1983719f82d3SEliot Blennerhassett } else if (dsp_index == 1) { 1984719f82d3SEliot Blennerhassett /* DSP 1 is a C6713 */ 19853285ea10SEliot Blennerhassett if (pao->pci.pci_dev->subsystem_device == 0x8700) { 1986719f82d3SEliot Blennerhassett /* PLD is located at CE1=0x90000000 */ 1987719f82d3SEliot Blennerhassett data = boot_loader_read_mem32(pao, dsp_index, 1988719f82d3SEliot Blennerhassett 0x90000010); 1989719f82d3SEliot Blennerhassett if ((data & 0xFF) != 0xAA) 19903285ea10SEliot Blennerhassett return HPI6205_ERROR_DSP_PLD; 1991719f82d3SEliot Blennerhassett /* 8713 - LED on */ 1992719f82d3SEliot Blennerhassett boot_loader_write_mem32(pao, dsp_index, 0x90000000, 1993719f82d3SEliot Blennerhassett 0x02); 1994719f82d3SEliot Blennerhassett } 1995719f82d3SEliot Blennerhassett } 1996719f82d3SEliot Blennerhassett return 0; 1997719f82d3SEliot Blennerhassett } 1998719f82d3SEliot Blennerhassett 1999719f82d3SEliot Blennerhassett /** Transfer data to or from DSP 2000719f82d3SEliot Blennerhassett nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA 2001719f82d3SEliot Blennerhassett */ 2002719f82d3SEliot Blennerhassett static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data, 2003719f82d3SEliot Blennerhassett u32 data_size, int operation) 2004719f82d3SEliot Blennerhassett { 2005719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 2006719f82d3SEliot Blennerhassett u32 data_transferred = 0; 2007719f82d3SEliot Blennerhassett u16 err = 0; 2008719f82d3SEliot Blennerhassett u32 temp2; 2009719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 2010719f82d3SEliot Blennerhassett 2011719f82d3SEliot Blennerhassett if (!p_data) 2012deb21a23SEliot Blennerhassett return HPI_ERROR_INVALID_DATA_POINTER; 2013719f82d3SEliot Blennerhassett 2014719f82d3SEliot Blennerhassett data_size &= ~3L; /* round data_size down to nearest 4 bytes */ 2015719f82d3SEliot Blennerhassett 2016719f82d3SEliot Blennerhassett /* make sure state is IDLE */ 2017719f82d3SEliot Blennerhassett if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) 2018719f82d3SEliot Blennerhassett return HPI_ERROR_DSP_HARDWARE; 2019719f82d3SEliot Blennerhassett 2020719f82d3SEliot Blennerhassett while (data_transferred < data_size) { 2021719f82d3SEliot Blennerhassett u32 this_copy = data_size - data_transferred; 2022719f82d3SEliot Blennerhassett 2023719f82d3SEliot Blennerhassett if (this_copy > HPI6205_SIZEOF_DATA) 2024719f82d3SEliot Blennerhassett this_copy = HPI6205_SIZEOF_DATA; 2025719f82d3SEliot Blennerhassett 2026719f82d3SEliot Blennerhassett if (operation == H620_HIF_SEND_DATA) 2027719f82d3SEliot Blennerhassett memcpy((void *)&interface->u.b_data[0], 2028719f82d3SEliot Blennerhassett &p_data[data_transferred], this_copy); 2029719f82d3SEliot Blennerhassett 2030719f82d3SEliot Blennerhassett interface->transfer_size_in_bytes = this_copy; 2031719f82d3SEliot Blennerhassett 2032719f82d3SEliot Blennerhassett /* DSP must change this back to nOperation */ 2033719f82d3SEliot Blennerhassett interface->dsp_ack = H620_HIF_IDLE; 2034719f82d3SEliot Blennerhassett send_dsp_command(phw, operation); 2035719f82d3SEliot Blennerhassett 2036719f82d3SEliot Blennerhassett temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT); 2037719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n", 2038719f82d3SEliot Blennerhassett HPI6205_TIMEOUT - temp2, this_copy); 2039719f82d3SEliot Blennerhassett 2040719f82d3SEliot Blennerhassett if (!temp2) { 2041719f82d3SEliot Blennerhassett /* timed out */ 2042719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 20433285ea10SEliot Blennerhassett "Timed out waiting for " "state %d got %d\n", 2044719f82d3SEliot Blennerhassett operation, interface->dsp_ack); 2045719f82d3SEliot Blennerhassett 2046719f82d3SEliot Blennerhassett break; 2047719f82d3SEliot Blennerhassett } 2048719f82d3SEliot Blennerhassett if (operation == H620_HIF_GET_DATA) 2049719f82d3SEliot Blennerhassett memcpy(&p_data[data_transferred], 2050719f82d3SEliot Blennerhassett (void *)&interface->u.b_data[0], this_copy); 2051719f82d3SEliot Blennerhassett 2052719f82d3SEliot Blennerhassett data_transferred += this_copy; 2053719f82d3SEliot Blennerhassett } 2054719f82d3SEliot Blennerhassett if (interface->dsp_ack != operation) 2055719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n", 2056719f82d3SEliot Blennerhassett interface->dsp_ack, operation); 2057719f82d3SEliot Blennerhassett /* err=HPI_ERROR_DSP_HARDWARE; */ 2058719f82d3SEliot Blennerhassett 2059719f82d3SEliot Blennerhassett send_dsp_command(phw, H620_HIF_IDLE); 2060719f82d3SEliot Blennerhassett 2061719f82d3SEliot Blennerhassett return err; 2062719f82d3SEliot Blennerhassett } 2063719f82d3SEliot Blennerhassett 2064719f82d3SEliot Blennerhassett /* wait for up to timeout_us microseconds for the DSP 2065719f82d3SEliot Blennerhassett to signal state by DMA into dwDspAck 2066719f82d3SEliot Blennerhassett */ 2067719f82d3SEliot Blennerhassett static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us) 2068719f82d3SEliot Blennerhassett { 2069719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 2070719f82d3SEliot Blennerhassett int t = timeout_us / 4; 2071719f82d3SEliot Blennerhassett 2072719f82d3SEliot Blennerhassett rmb(); /* ensure interface->dsp_ack is up to date */ 2073719f82d3SEliot Blennerhassett while ((interface->dsp_ack != state) && --t) { 2074719f82d3SEliot Blennerhassett hpios_delay_micro_seconds(4); 2075719f82d3SEliot Blennerhassett rmb(); /* DSP changes dsp_ack by DMA */ 2076719f82d3SEliot Blennerhassett } 2077719f82d3SEliot Blennerhassett 2078719f82d3SEliot Blennerhassett /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */ 2079719f82d3SEliot Blennerhassett return t * 4; 2080719f82d3SEliot Blennerhassett } 2081719f82d3SEliot Blennerhassett 2082719f82d3SEliot Blennerhassett /* set the busmaster interface to cmd, then interrupt the DSP */ 2083719f82d3SEliot Blennerhassett static void send_dsp_command(struct hpi_hw_obj *phw, int cmd) 2084719f82d3SEliot Blennerhassett { 2085719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 2086719f82d3SEliot Blennerhassett u32 r; 2087719f82d3SEliot Blennerhassett 2088719f82d3SEliot Blennerhassett interface->host_cmd = cmd; 2089719f82d3SEliot Blennerhassett wmb(); /* DSP gets state by DMA, make sure it is written to memory */ 2090719f82d3SEliot Blennerhassett /* before we interrupt the DSP */ 2091719f82d3SEliot Blennerhassett r = ioread32(phw->prHDCR); 2092719f82d3SEliot Blennerhassett r |= (u32)C6205_HDCR_DSPINT; 2093719f82d3SEliot Blennerhassett iowrite32(r, phw->prHDCR); 2094719f82d3SEliot Blennerhassett r &= ~(u32)C6205_HDCR_DSPINT; 2095719f82d3SEliot Blennerhassett iowrite32(r, phw->prHDCR); 2096719f82d3SEliot Blennerhassett } 2097719f82d3SEliot Blennerhassett 2098719f82d3SEliot Blennerhassett static unsigned int message_count; 2099719f82d3SEliot Blennerhassett 2100719f82d3SEliot Blennerhassett static u16 message_response_sequence(struct hpi_adapter_obj *pao, 2101719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr) 2102719f82d3SEliot Blennerhassett { 2103719f82d3SEliot Blennerhassett u32 time_out, time_out2; 2104719f82d3SEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv; 2105719f82d3SEliot Blennerhassett struct bus_master_interface *interface = phw->p_interface_buffer; 2106719f82d3SEliot Blennerhassett u16 err = 0; 2107719f82d3SEliot Blennerhassett 2108719f82d3SEliot Blennerhassett message_count++; 2109c6c2c9abSEliot Blennerhassett if (phm->size > sizeof(interface->u.message_buffer)) { 2110deb21a23SEliot Blennerhassett phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; 2111c6c2c9abSEliot Blennerhassett phr->specific_error = sizeof(interface->u.message_buffer); 21123285ea10SEliot Blennerhassett phr->size = sizeof(struct hpi_response_header); 21133285ea10SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 2114a2800300STakashi Iwai "message len %d too big for buffer %zd \n", phm->size, 2115c6c2c9abSEliot Blennerhassett sizeof(interface->u.message_buffer)); 21163285ea10SEliot Blennerhassett return 0; 21173285ea10SEliot Blennerhassett } 21183285ea10SEliot Blennerhassett 2119*f9a376c3SEliot Blennerhassett /* Assume buffer of type struct bus_master_interface_62 2120719f82d3SEliot Blennerhassett is allocated "noncacheable" */ 2121719f82d3SEliot Blennerhassett 2122719f82d3SEliot Blennerhassett if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { 2123719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n"); 21243285ea10SEliot Blennerhassett return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; 2125719f82d3SEliot Blennerhassett } 21263285ea10SEliot Blennerhassett 21273285ea10SEliot Blennerhassett memcpy(&interface->u.message_buffer, phm, phm->size); 2128719f82d3SEliot Blennerhassett /* signal we want a response */ 2129719f82d3SEliot Blennerhassett send_dsp_command(phw, H620_HIF_GET_RESP); 2130719f82d3SEliot Blennerhassett 2131719f82d3SEliot Blennerhassett time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT); 2132719f82d3SEliot Blennerhassett 21333285ea10SEliot Blennerhassett if (!time_out2) { 2134719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 21353285ea10SEliot Blennerhassett "(%u) Timed out waiting for " "GET_RESP state [%x]\n", 2136719f82d3SEliot Blennerhassett message_count, interface->dsp_ack); 2137719f82d3SEliot Blennerhassett } else { 2138719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, 2139719f82d3SEliot Blennerhassett "(%u) transition to GET_RESP after %u\n", 2140719f82d3SEliot Blennerhassett message_count, HPI6205_TIMEOUT - time_out2); 2141719f82d3SEliot Blennerhassett } 2142719f82d3SEliot Blennerhassett /* spin waiting on HIF interrupt flag (end of msg process) */ 2143719f82d3SEliot Blennerhassett time_out = HPI6205_TIMEOUT; 2144719f82d3SEliot Blennerhassett 2145719f82d3SEliot Blennerhassett /* read the result */ 21463285ea10SEliot Blennerhassett if (time_out) { 2147c6c2c9abSEliot Blennerhassett if (interface->u.response_buffer.response.size <= phr->size) 21483285ea10SEliot Blennerhassett memcpy(phr, &interface->u.response_buffer, 2149c6c2c9abSEliot Blennerhassett interface->u.response_buffer.response.size); 21503285ea10SEliot Blennerhassett else { 21513285ea10SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, 21523285ea10SEliot Blennerhassett "response len %d too big for buffer %d\n", 2153c6c2c9abSEliot Blennerhassett interface->u.response_buffer.response.size, 2154c6c2c9abSEliot Blennerhassett phr->size); 21553285ea10SEliot Blennerhassett memcpy(phr, &interface->u.response_buffer, 21563285ea10SEliot Blennerhassett sizeof(struct hpi_response_header)); 21573285ea10SEliot Blennerhassett phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; 21583285ea10SEliot Blennerhassett phr->specific_error = 2159c6c2c9abSEliot Blennerhassett interface->u.response_buffer.response.size; 21603285ea10SEliot Blennerhassett phr->size = sizeof(struct hpi_response_header); 21613285ea10SEliot Blennerhassett } 21623285ea10SEliot Blennerhassett } 2163719f82d3SEliot Blennerhassett /* set interface back to idle */ 2164719f82d3SEliot Blennerhassett send_dsp_command(phw, H620_HIF_IDLE); 2165719f82d3SEliot Blennerhassett 21663285ea10SEliot Blennerhassett if (!time_out || !time_out2) { 2167719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "something timed out!\n"); 21683285ea10SEliot Blennerhassett return HPI6205_ERROR_MSG_RESP_TIMEOUT; 2169719f82d3SEliot Blennerhassett } 2170719f82d3SEliot Blennerhassett /* special case for adapter close - */ 2171719f82d3SEliot Blennerhassett /* wait for the DSP to indicate it is idle */ 2172719f82d3SEliot Blennerhassett if (phm->function == HPI_ADAPTER_CLOSE) { 2173719f82d3SEliot Blennerhassett if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { 2174719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, 21753285ea10SEliot Blennerhassett "Timeout waiting for idle " 2176719f82d3SEliot Blennerhassett "(on adapter_close)\n"); 21773285ea10SEliot Blennerhassett return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; 2178719f82d3SEliot Blennerhassett } 2179719f82d3SEliot Blennerhassett } 2180719f82d3SEliot Blennerhassett err = hpi_validate_response(phm, phr); 2181719f82d3SEliot Blennerhassett return err; 2182719f82d3SEliot Blennerhassett } 2183719f82d3SEliot Blennerhassett 2184719f82d3SEliot Blennerhassett static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, 2185719f82d3SEliot Blennerhassett struct hpi_response *phr) 2186719f82d3SEliot Blennerhassett { 2187719f82d3SEliot Blennerhassett 2188719f82d3SEliot Blennerhassett u16 err = 0; 2189719f82d3SEliot Blennerhassett 2190719f82d3SEliot Blennerhassett hpios_dsplock_lock(pao); 2191719f82d3SEliot Blennerhassett 2192719f82d3SEliot Blennerhassett err = message_response_sequence(pao, phm, phr); 2193719f82d3SEliot Blennerhassett 2194719f82d3SEliot Blennerhassett /* maybe an error response */ 2195719f82d3SEliot Blennerhassett if (err) { 2196719f82d3SEliot Blennerhassett /* something failed in the HPI/DSP interface */ 21970a00044dSEliot Blennerhassett if (err >= HPI_ERROR_BACKEND_BASE) { 21980a00044dSEliot Blennerhassett phr->error = HPI_ERROR_DSP_COMMUNICATION; 21990a00044dSEliot Blennerhassett phr->specific_error = err; 22000a00044dSEliot Blennerhassett } else { 2201719f82d3SEliot Blennerhassett phr->error = err; 22020a00044dSEliot Blennerhassett } 22030a00044dSEliot Blennerhassett 2204719f82d3SEliot Blennerhassett pao->dsp_crashed++; 2205719f82d3SEliot Blennerhassett 2206719f82d3SEliot Blennerhassett /* just the header of the response is valid */ 2207719f82d3SEliot Blennerhassett phr->size = sizeof(struct hpi_response_header); 2208719f82d3SEliot Blennerhassett goto err; 2209719f82d3SEliot Blennerhassett } else 2210719f82d3SEliot Blennerhassett pao->dsp_crashed = 0; 2211719f82d3SEliot Blennerhassett 2212719f82d3SEliot Blennerhassett if (phr->error != 0) /* something failed in the DSP */ 2213719f82d3SEliot Blennerhassett goto err; 2214719f82d3SEliot Blennerhassett 2215719f82d3SEliot Blennerhassett switch (phm->function) { 2216719f82d3SEliot Blennerhassett case HPI_OSTREAM_WRITE: 2217719f82d3SEliot Blennerhassett case HPI_ISTREAM_ANC_WRITE: 2218719f82d3SEliot Blennerhassett err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data, 2219719f82d3SEliot Blennerhassett phm->u.d.u.data.data_size, H620_HIF_SEND_DATA); 2220719f82d3SEliot Blennerhassett break; 2221719f82d3SEliot Blennerhassett 2222719f82d3SEliot Blennerhassett case HPI_ISTREAM_READ: 2223719f82d3SEliot Blennerhassett case HPI_OSTREAM_ANC_READ: 2224719f82d3SEliot Blennerhassett err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data, 2225719f82d3SEliot Blennerhassett phm->u.d.u.data.data_size, H620_HIF_GET_DATA); 2226719f82d3SEliot Blennerhassett break; 2227719f82d3SEliot Blennerhassett 2228719f82d3SEliot Blennerhassett } 2229719f82d3SEliot Blennerhassett phr->error = err; 2230719f82d3SEliot Blennerhassett 2231719f82d3SEliot Blennerhassett err: 2232719f82d3SEliot Blennerhassett hpios_dsplock_unlock(pao); 2233719f82d3SEliot Blennerhassett 2234719f82d3SEliot Blennerhassett return; 2235719f82d3SEliot Blennerhassett } 2236