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