Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /******************************************************************************
0003 
0004     AudioScience HPI driver
0005     Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
0006 
0007 
0008  Hardware Programming Interface (HPI) for AudioScience ASI6200 series adapters.
0009  These PCI bus adapters are based on the TI C6711 DSP.
0010 
0011  Exported functions:
0012  void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
0013 
0014  #defines
0015  HIDE_PCI_ASSERTS to show the PCI asserts
0016  PROFILE_DSP2 get profile data from DSP2 if present (instead of DSP 1)
0017 
0018 (C) Copyright AudioScience Inc. 1998-2003
0019 *******************************************************************************/
0020 #define SOURCEFILE_NAME "hpi6000.c"
0021 
0022 #include "hpi_internal.h"
0023 #include "hpimsginit.h"
0024 #include "hpidebug.h"
0025 #include "hpi6000.h"
0026 #include "hpidspcd.h"
0027 #include "hpicmn.h"
0028 
0029 #define HPI_HIF_BASE (0x00000200)   /* start of C67xx internal RAM */
0030 #define HPI_HIF_ADDR(member) \
0031     (HPI_HIF_BASE + offsetof(struct hpi_hif_6000, member))
0032 #define HPI_HIF_ERROR_MASK      0x4000
0033 
0034 /* HPI6000 specific error codes */
0035 #define HPI6000_ERROR_BASE 900  /* not actually used anywhere */
0036 
0037 /* operational/messaging errors */
0038 #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT             901
0039 #define HPI6000_ERROR_RESP_GET_LEN                      902
0040 #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK             903
0041 #define HPI6000_ERROR_MSG_GET_ADR                       904
0042 #define HPI6000_ERROR_RESP_GET_ADR                      905
0043 #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32             906
0044 #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32              907
0045 
0046 #define HPI6000_ERROR_CONTROL_CACHE_PARAMS              909
0047 
0048 #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT            911
0049 #define HPI6000_ERROR_SEND_DATA_ACK                     912
0050 #define HPI6000_ERROR_SEND_DATA_ADR                     913
0051 #define HPI6000_ERROR_SEND_DATA_TIMEOUT                 914
0052 #define HPI6000_ERROR_SEND_DATA_CMD                     915
0053 #define HPI6000_ERROR_SEND_DATA_WRITE                   916
0054 #define HPI6000_ERROR_SEND_DATA_IDLECMD                 917
0055 
0056 #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT             921
0057 #define HPI6000_ERROR_GET_DATA_ACK                      922
0058 #define HPI6000_ERROR_GET_DATA_CMD                      923
0059 #define HPI6000_ERROR_GET_DATA_READ                     924
0060 #define HPI6000_ERROR_GET_DATA_IDLECMD                  925
0061 
0062 #define HPI6000_ERROR_CONTROL_CACHE_ADDRLEN             951
0063 #define HPI6000_ERROR_CONTROL_CACHE_READ                952
0064 #define HPI6000_ERROR_CONTROL_CACHE_FLUSH               953
0065 
0066 #define HPI6000_ERROR_MSG_RESP_GETRESPCMD               961
0067 #define HPI6000_ERROR_MSG_RESP_IDLECMD                  962
0068 
0069 /* Initialisation/bootload errors */
0070 #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID               930
0071 
0072 /* can't access PCI2040 */
0073 #define HPI6000_ERROR_INIT_PCI2040                      931
0074 /* can't access DSP HPI i/f */
0075 #define HPI6000_ERROR_INIT_DSPHPI                       932
0076 /* can't access internal DSP memory */
0077 #define HPI6000_ERROR_INIT_DSPINTMEM                    933
0078 /* can't access SDRAM - test#1 */
0079 #define HPI6000_ERROR_INIT_SDRAM1                       934
0080 /* can't access SDRAM - test#2 */
0081 #define HPI6000_ERROR_INIT_SDRAM2                       935
0082 
0083 #define HPI6000_ERROR_INIT_VERIFY                       938
0084 
0085 #define HPI6000_ERROR_INIT_NOACK                        939
0086 
0087 #define HPI6000_ERROR_INIT_PLDTEST1                     941
0088 #define HPI6000_ERROR_INIT_PLDTEST2                     942
0089 
0090 /* local defines */
0091 
0092 #define HIDE_PCI_ASSERTS
0093 #define PROFILE_DSP2
0094 
0095 /* for PCI2040 i/f chip */
0096 /* HPI CSR registers */
0097 /* word offsets from CSR base */
0098 /* use when io addresses defined as u32 * */
0099 
0100 #define INTERRUPT_EVENT_SET     0
0101 #define INTERRUPT_EVENT_CLEAR   1
0102 #define INTERRUPT_MASK_SET      2
0103 #define INTERRUPT_MASK_CLEAR    3
0104 #define HPI_ERROR_REPORT        4
0105 #define HPI_RESET               5
0106 #define HPI_DATA_WIDTH          6
0107 
0108 #define MAX_DSPS 2
0109 /* HPI registers, spaced 8K bytes = 2K words apart */
0110 #define DSP_SPACING             0x800
0111 
0112 #define CONTROL                 0x0000
0113 #define ADDRESS                 0x0200
0114 #define DATA_AUTOINC            0x0400
0115 #define DATA                    0x0600
0116 
0117 #define TIMEOUT 500000
0118 
0119 struct dsp_obj {
0120     __iomem u32 *prHPI_control;
0121     __iomem u32 *prHPI_address;
0122     __iomem u32 *prHPI_data;
0123     __iomem u32 *prHPI_data_auto_inc;
0124     char c_dsp_rev;     /*A, B */
0125     u32 control_cache_address_on_dsp;
0126     u32 control_cache_length_on_dsp;
0127     struct hpi_adapter_obj *pa_parent_adapter;
0128 };
0129 
0130 struct hpi_hw_obj {
0131     __iomem u32 *dw2040_HPICSR;
0132     __iomem u32 *dw2040_HPIDSP;
0133 
0134     u16 num_dsp;
0135     struct dsp_obj ado[MAX_DSPS];
0136 
0137     u32 message_buffer_address_on_dsp;
0138     u32 response_buffer_address_on_dsp;
0139     u32 pCI2040HPI_error_count;
0140 
0141     struct hpi_control_cache_single control_cache[HPI_NMIXER_CONTROLS];
0142     struct hpi_control_cache *p_cache;
0143 };
0144 
0145 static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
0146     u16 dsp_index, u32 hpi_address, u32 *source, u32 count);
0147 static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
0148     u16 dsp_index, u32 hpi_address, u32 *dest, u32 count);
0149 
0150 static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
0151     u32 *pos_error_code);
0152 static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
0153     u16 read_or_write);
0154 #define H6READ 1
0155 #define H6WRITE 0
0156 
0157 static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
0158     struct hpi_message *phm);
0159 static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
0160     u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr);
0161 
0162 static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
0163     struct hpi_response *phr);
0164 
0165 static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
0166     u32 ack_value);
0167 
0168 static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
0169     u16 dsp_index, u32 host_cmd);
0170 
0171 static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo);
0172 
0173 static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
0174     struct hpi_message *phm, struct hpi_response *phr);
0175 
0176 static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
0177     struct hpi_message *phm, struct hpi_response *phr);
0178 
0179 static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data);
0180 
0181 static u32 hpi_read_word(struct dsp_obj *pdo, u32 address);
0182 
0183 static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
0184     u32 length);
0185 
0186 static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
0187     u32 length);
0188 
0189 static void subsys_create_adapter(struct hpi_message *phm,
0190     struct hpi_response *phr);
0191 
0192 static void adapter_delete(struct hpi_adapter_obj *pao,
0193     struct hpi_message *phm, struct hpi_response *phr);
0194 
0195 static void adapter_get_asserts(struct hpi_adapter_obj *pao,
0196     struct hpi_message *phm, struct hpi_response *phr);
0197 
0198 static short create_adapter_obj(struct hpi_adapter_obj *pao,
0199     u32 *pos_error_code);
0200 
0201 static void delete_adapter_obj(struct hpi_adapter_obj *pao);
0202 
0203 /* local globals */
0204 
0205 static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */
0206 static u16 gw_pci_write_asserts;    /* used to count PCI2040 errors */
0207 
0208 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
0209 {
0210     switch (phm->function) {
0211     case HPI_SUBSYS_CREATE_ADAPTER:
0212         subsys_create_adapter(phm, phr);
0213         break;
0214     default:
0215         phr->error = HPI_ERROR_INVALID_FUNC;
0216         break;
0217     }
0218 }
0219 
0220 static void control_message(struct hpi_adapter_obj *pao,
0221     struct hpi_message *phm, struct hpi_response *phr)
0222 {
0223     struct hpi_hw_obj *phw = pao->priv;
0224 
0225     switch (phm->function) {
0226     case HPI_CONTROL_GET_STATE:
0227         if (pao->has_control_cache) {
0228             u16 err;
0229             err = hpi6000_update_control_cache(pao, phm);
0230 
0231             if (err) {
0232                 if (err >= HPI_ERROR_BACKEND_BASE) {
0233                     phr->error =
0234                         HPI_ERROR_CONTROL_CACHING;
0235                     phr->specific_error = err;
0236                 } else {
0237                     phr->error = err;
0238                 }
0239                 break;
0240             }
0241 
0242             if (hpi_check_control_cache(phw->p_cache, phm, phr))
0243                 break;
0244         }
0245         hw_message(pao, phm, phr);
0246         break;
0247     case HPI_CONTROL_SET_STATE:
0248         hw_message(pao, phm, phr);
0249         hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, phr);
0250         break;
0251 
0252     case HPI_CONTROL_GET_INFO:
0253     default:
0254         hw_message(pao, phm, phr);
0255         break;
0256     }
0257 }
0258 
0259 static void adapter_message(struct hpi_adapter_obj *pao,
0260     struct hpi_message *phm, struct hpi_response *phr)
0261 {
0262     switch (phm->function) {
0263     case HPI_ADAPTER_GET_ASSERT:
0264         adapter_get_asserts(pao, phm, phr);
0265         break;
0266 
0267     case HPI_ADAPTER_DELETE:
0268         adapter_delete(pao, phm, phr);
0269         break;
0270 
0271     default:
0272         hw_message(pao, phm, phr);
0273         break;
0274     }
0275 }
0276 
0277 static void outstream_message(struct hpi_adapter_obj *pao,
0278     struct hpi_message *phm, struct hpi_response *phr)
0279 {
0280     switch (phm->function) {
0281     case HPI_OSTREAM_HOSTBUFFER_ALLOC:
0282     case HPI_OSTREAM_HOSTBUFFER_FREE:
0283         /* Don't let these messages go to the HW function because
0284          * they're called without locking the spinlock.
0285          * For the HPI6000 adapters the HW would return
0286          * HPI_ERROR_INVALID_FUNC anyway.
0287          */
0288         phr->error = HPI_ERROR_INVALID_FUNC;
0289         break;
0290     default:
0291         hw_message(pao, phm, phr);
0292         return;
0293     }
0294 }
0295 
0296 static void instream_message(struct hpi_adapter_obj *pao,
0297     struct hpi_message *phm, struct hpi_response *phr)
0298 {
0299 
0300     switch (phm->function) {
0301     case HPI_ISTREAM_HOSTBUFFER_ALLOC:
0302     case HPI_ISTREAM_HOSTBUFFER_FREE:
0303         /* Don't let these messages go to the HW function because
0304          * they're called without locking the spinlock.
0305          * For the HPI6000 adapters the HW would return
0306          * HPI_ERROR_INVALID_FUNC anyway.
0307          */
0308         phr->error = HPI_ERROR_INVALID_FUNC;
0309         break;
0310     default:
0311         hw_message(pao, phm, phr);
0312         return;
0313     }
0314 }
0315 
0316 /************************************************************************/
0317 /** HPI_6000()
0318  * Entry point from HPIMAN
0319  * All calls to the HPI start here
0320  */
0321 void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
0322 {
0323     struct hpi_adapter_obj *pao = NULL;
0324 
0325     if (phm->object != HPI_OBJ_SUBSYSTEM) {
0326         pao = hpi_find_adapter(phm->adapter_index);
0327         if (!pao) {
0328             hpi_init_response(phr, phm->object, phm->function,
0329                 HPI_ERROR_BAD_ADAPTER_NUMBER);
0330             HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n",
0331                 phm->adapter_index);
0332             return;
0333         }
0334 
0335         /* Don't even try to communicate with crashed DSP */
0336         if (pao->dsp_crashed >= 10) {
0337             hpi_init_response(phr, phm->object, phm->function,
0338                 HPI_ERROR_DSP_HARDWARE);
0339             HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n",
0340                 phm->adapter_index);
0341             return;
0342         }
0343     }
0344     /* Init default response including the size field */
0345     if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
0346         hpi_init_response(phr, phm->object, phm->function,
0347             HPI_ERROR_PROCESSING_MESSAGE);
0348 
0349     switch (phm->type) {
0350     case HPI_TYPE_REQUEST:
0351         switch (phm->object) {
0352         case HPI_OBJ_SUBSYSTEM:
0353             subsys_message(phm, phr);
0354             break;
0355 
0356         case HPI_OBJ_ADAPTER:
0357             phr->size =
0358                 sizeof(struct hpi_response_header) +
0359                 sizeof(struct hpi_adapter_res);
0360             adapter_message(pao, phm, phr);
0361             break;
0362 
0363         case HPI_OBJ_CONTROL:
0364             control_message(pao, phm, phr);
0365             break;
0366 
0367         case HPI_OBJ_OSTREAM:
0368             outstream_message(pao, phm, phr);
0369             break;
0370 
0371         case HPI_OBJ_ISTREAM:
0372             instream_message(pao, phm, phr);
0373             break;
0374 
0375         default:
0376             hw_message(pao, phm, phr);
0377             break;
0378         }
0379         break;
0380 
0381     default:
0382         phr->error = HPI_ERROR_INVALID_TYPE;
0383         break;
0384     }
0385 }
0386 
0387 /************************************************************************/
0388 /* SUBSYSTEM */
0389 
0390 /* create an adapter object and initialise it based on resource information
0391  * passed in the message
0392  * NOTE - you cannot use this function AND the FindAdapters function at the
0393  * same time, the application must use only one of them to get the adapters
0394  */
0395 static void subsys_create_adapter(struct hpi_message *phm,
0396     struct hpi_response *phr)
0397 {
0398     /* create temp adapter obj, because we don't know what index yet */
0399     struct hpi_adapter_obj ao;
0400     struct hpi_adapter_obj *pao;
0401     u32 os_error_code;
0402     u16 err = 0;
0403     u32 dsp_index = 0;
0404 
0405     HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
0406 
0407     memset(&ao, 0, sizeof(ao));
0408 
0409     ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
0410     if (!ao.priv) {
0411         HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n");
0412         phr->error = HPI_ERROR_MEMORY_ALLOC;
0413         return;
0414     }
0415 
0416     /* create the adapter object based on the resource information */
0417     ao.pci = *phm->u.s.resource.r.pci;
0418 
0419     err = create_adapter_obj(&ao, &os_error_code);
0420     if (err) {
0421         delete_adapter_obj(&ao);
0422         if (err >= HPI_ERROR_BACKEND_BASE) {
0423             phr->error = HPI_ERROR_DSP_BOOTLOAD;
0424             phr->specific_error = err;
0425         } else {
0426             phr->error = err;
0427         }
0428 
0429         phr->u.s.data = os_error_code;
0430         return;
0431     }
0432     /* need to update paParentAdapter */
0433     pao = hpi_find_adapter(ao.index);
0434     if (!pao) {
0435         /* We just added this adapter, why can't we find it!? */
0436         HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
0437         phr->error = HPI_ERROR_BAD_ADAPTER;
0438         return;
0439     }
0440 
0441     for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
0442         struct hpi_hw_obj *phw = pao->priv;
0443         phw->ado[dsp_index].pa_parent_adapter = pao;
0444     }
0445 
0446     phr->u.s.adapter_type = ao.type;
0447     phr->u.s.adapter_index = ao.index;
0448     phr->error = 0;
0449 }
0450 
0451 static void adapter_delete(struct hpi_adapter_obj *pao,
0452     struct hpi_message *phm, struct hpi_response *phr)
0453 {
0454     delete_adapter_obj(pao);
0455     hpi_delete_adapter(pao);
0456     phr->error = 0;
0457 }
0458 
0459 /* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
0460 static short create_adapter_obj(struct hpi_adapter_obj *pao,
0461     u32 *pos_error_code)
0462 {
0463     short boot_error = 0;
0464     u32 dsp_index = 0;
0465     u32 control_cache_size = 0;
0466     u32 control_cache_count = 0;
0467     struct hpi_hw_obj *phw = pao->priv;
0468 
0469     /* The PCI2040 has the following address map */
0470     /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
0471     /* BAR1 - 32K = HPI registers on DSP */
0472     phw->dw2040_HPICSR = pao->pci.ap_mem_base[0];
0473     phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1];
0474     HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR,
0475         phw->dw2040_HPIDSP);
0476 
0477     /* set addresses for the possible DSP HPI interfaces */
0478     for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
0479         phw->ado[dsp_index].prHPI_control =
0480             phw->dw2040_HPIDSP + (CONTROL +
0481             DSP_SPACING * dsp_index);
0482 
0483         phw->ado[dsp_index].prHPI_address =
0484             phw->dw2040_HPIDSP + (ADDRESS +
0485             DSP_SPACING * dsp_index);
0486         phw->ado[dsp_index].prHPI_data =
0487             phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index);
0488 
0489         phw->ado[dsp_index].prHPI_data_auto_inc =
0490             phw->dw2040_HPIDSP + (DATA_AUTOINC +
0491             DSP_SPACING * dsp_index);
0492 
0493         HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
0494             phw->ado[dsp_index].prHPI_control,
0495             phw->ado[dsp_index].prHPI_address,
0496             phw->ado[dsp_index].prHPI_data,
0497             phw->ado[dsp_index].prHPI_data_auto_inc);
0498 
0499         phw->ado[dsp_index].pa_parent_adapter = pao;
0500     }
0501 
0502     phw->pCI2040HPI_error_count = 0;
0503     pao->has_control_cache = 0;
0504 
0505     /* Set the default number of DSPs on this card */
0506     /* This is (conditionally) adjusted after bootloading */
0507     /* of the first DSP in the bootload section. */
0508     phw->num_dsp = 1;
0509 
0510     boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code);
0511     if (boot_error)
0512         return boot_error;
0513 
0514     HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
0515 
0516     phw->message_buffer_address_on_dsp = 0L;
0517     phw->response_buffer_address_on_dsp = 0L;
0518 
0519     /* get info about the adapter by asking the adapter */
0520     /* send a HPI_ADAPTER_GET_INFO message */
0521     {
0522         struct hpi_message hm;
0523         struct hpi_response hr0;    /* response from DSP 0 */
0524         struct hpi_response hr1;    /* response from DSP 1 */
0525         u16 error = 0;
0526 
0527         HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
0528         memset(&hm, 0, sizeof(hm));
0529         hm.type = HPI_TYPE_REQUEST;
0530         hm.size = sizeof(struct hpi_message);
0531         hm.object = HPI_OBJ_ADAPTER;
0532         hm.function = HPI_ADAPTER_GET_INFO;
0533         hm.adapter_index = 0;
0534         memset(&hr0, 0, sizeof(hr0));
0535         memset(&hr1, 0, sizeof(hr1));
0536         hr0.size = sizeof(hr0);
0537         hr1.size = sizeof(hr1);
0538 
0539         error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
0540         if (hr0.error) {
0541             HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
0542             return hr0.error;
0543         }
0544         if (phw->num_dsp == 2) {
0545             error = hpi6000_message_response_sequence(pao, 1, &hm,
0546                 &hr1);
0547             if (error)
0548                 return error;
0549         }
0550         pao->type = hr0.u.ax.info.adapter_type;
0551         pao->index = hr0.u.ax.info.adapter_index;
0552     }
0553 
0554     memset(&phw->control_cache[0], 0,
0555         sizeof(struct hpi_control_cache_single) *
0556         HPI_NMIXER_CONTROLS);
0557     /* Read the control cache length to figure out if it is turned on */
0558     control_cache_size =
0559         hpi_read_word(&phw->ado[0],
0560         HPI_HIF_ADDR(control_cache_size_in_bytes));
0561     if (control_cache_size) {
0562         control_cache_count =
0563             hpi_read_word(&phw->ado[0],
0564             HPI_HIF_ADDR(control_cache_count));
0565 
0566         phw->p_cache =
0567             hpi_alloc_control_cache(control_cache_count,
0568             control_cache_size, (unsigned char *)
0569             &phw->control_cache[0]
0570             );
0571         if (phw->p_cache)
0572             pao->has_control_cache = 1;
0573     }
0574 
0575     HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type,
0576         pao->index);
0577 
0578     if (phw->p_cache)
0579         phw->p_cache->adap_idx = pao->index;
0580 
0581     return hpi_add_adapter(pao);
0582 }
0583 
0584 static void delete_adapter_obj(struct hpi_adapter_obj *pao)
0585 {
0586     struct hpi_hw_obj *phw = pao->priv;
0587 
0588     if (pao->has_control_cache)
0589         hpi_free_control_cache(phw->p_cache);
0590 
0591     /* reset DSPs on adapter */
0592     iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET);
0593 
0594     kfree(phw);
0595 }
0596 
0597 /************************************************************************/
0598 /* ADAPTER */
0599 
0600 static void adapter_get_asserts(struct hpi_adapter_obj *pao,
0601     struct hpi_message *phm, struct hpi_response *phr)
0602 {
0603 #ifndef HIDE_PCI_ASSERTS
0604     /* if we have PCI2040 asserts then collect them */
0605     if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
0606         phr->u.ax.assert.p1 =
0607             gw_pci_read_asserts * 100 + gw_pci_write_asserts;
0608         phr->u.ax.assert.p2 = 0;
0609         phr->u.ax.assert.count = 1; /* assert count */
0610         phr->u.ax.assert.dsp_index = -1;    /* "dsp index" */
0611         strcpy(phr->u.ax.assert.sz_message, "PCI2040 error");
0612         phr->u.ax.assert.dsp_msg_addr = 0;
0613         gw_pci_read_asserts = 0;
0614         gw_pci_write_asserts = 0;
0615         phr->error = 0;
0616     } else
0617 #endif
0618         hw_message(pao, phm, phr);  /*get DSP asserts */
0619 
0620     return;
0621 }
0622 
0623 /************************************************************************/
0624 /* LOW-LEVEL */
0625 
0626 static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
0627     u32 *pos_error_code)
0628 {
0629     struct hpi_hw_obj *phw = pao->priv;
0630     short error;
0631     u32 timeout;
0632     u32 read = 0;
0633     u32 i = 0;
0634     u32 data = 0;
0635     u32 j = 0;
0636     u32 test_addr = 0x80000000;
0637     u32 test_data = 0x00000001;
0638     u32 dw2040_reset = 0;
0639     u32 dsp_index = 0;
0640     u32 endian = 0;
0641     u32 adapter_info = 0;
0642     u32 delay = 0;
0643 
0644     struct dsp_code dsp_code;
0645     u16 boot_load_family = 0;
0646 
0647     /* NOTE don't use wAdapterType in this routine. It is not setup yet */
0648 
0649     switch (pao->pci.pci_dev->subsystem_device) {
0650     case 0x5100:
0651     case 0x5110:    /* ASI5100 revB or higher with C6711D */
0652     case 0x5200:    /* ASI5200 PCIe version of ASI5100 */
0653     case 0x6100:
0654     case 0x6200:
0655         boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
0656         break;
0657     default:
0658         return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
0659     }
0660 
0661     /* reset all DSPs, indicate two DSPs are present
0662      * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode
0663      */
0664     endian = 0;
0665     dw2040_reset = 0x0003000F;
0666     iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
0667 
0668     /* read back register to make sure PCI2040 chip is functioning
0669      * note that bits 4..15 are read-only and so should always return zero,
0670      * even though we wrote 1 to them
0671      */
0672     hpios_delay_micro_seconds(1000);
0673     delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
0674 
0675     if (delay != dw2040_reset) {
0676         HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
0677             delay);
0678         return HPI6000_ERROR_INIT_PCI2040;
0679     }
0680 
0681     /* Indicate that DSP#0,1 is a C6X */
0682     iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH);
0683     /* set Bit30 and 29 - which will prevent Target aborts from being
0684      * issued upon HPI or GP error
0685      */
0686     iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET);
0687 
0688     /* isolate DSP HAD8 line from PCI2040 so that
0689      * Little endian can be set by pullup
0690      */
0691     dw2040_reset = dw2040_reset & (~(endian << 3));
0692     iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
0693 
0694     phw->ado[0].c_dsp_rev = 'B';    /* revB */
0695     phw->ado[1].c_dsp_rev = 'B';    /* revB */
0696 
0697     /*Take both DSPs out of reset, setting HAD8 to the correct Endian */
0698     dw2040_reset = dw2040_reset & (~0x00000001);    /* start DSP 0 */
0699     iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
0700     dw2040_reset = dw2040_reset & (~0x00000002);    /* start DSP 1 */
0701     iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
0702 
0703     /* set HAD8 back to PCI2040, now that DSP set to little endian mode */
0704     dw2040_reset = dw2040_reset & (~0x00000008);
0705     iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
0706     /*delay to allow DSP to get going */
0707     hpios_delay_micro_seconds(100);
0708 
0709     /* loop through all DSPs, downloading DSP code */
0710     for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
0711         struct dsp_obj *pdo = &phw->ado[dsp_index];
0712 
0713         /* configure DSP so that we download code into the SRAM */
0714         /* set control reg for little endian, HWOB=1 */
0715         iowrite32(0x00010001, pdo->prHPI_control);
0716 
0717         /* test access to the HPI address register (HPIA) */
0718         test_data = 0x00000001;
0719         for (j = 0; j < 32; j++) {
0720             iowrite32(test_data, pdo->prHPI_address);
0721             data = ioread32(pdo->prHPI_address);
0722             if (data != test_data) {
0723                 HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n",
0724                     test_data, data, dsp_index);
0725                 return HPI6000_ERROR_INIT_DSPHPI;
0726             }
0727             test_data = test_data << 1;
0728         }
0729 
0730 /* if C6713 the setup PLL to generate 225MHz from 25MHz.
0731 * Since the PLLDIV1 read is sometimes wrong, even on a C6713,
0732 * we're going to do this unconditionally
0733 */
0734 /* PLLDIV1 should have a value of 8000 after reset */
0735 /*
0736     if (HpiReadWord(pdo,0x01B7C118) == 0x8000)
0737 */
0738         {
0739             /* C6713 datasheet says we cannot program PLL from HPI,
0740              * and indeed if we try to set the PLL multiply from the
0741              * HPI, the PLL does not seem to lock,
0742              * so we enable the PLL and use the default of x 7
0743              */
0744             /* bypass PLL */
0745             hpi_write_word(pdo, 0x01B7C100, 0x0000);
0746             hpios_delay_micro_seconds(100);
0747 
0748             /*  ** use default of PLL  x7 ** */
0749             /* EMIF = 225/3=75MHz */
0750             hpi_write_word(pdo, 0x01B7C120, 0x8002);
0751             hpios_delay_micro_seconds(100);
0752 
0753             /* peri = 225/2 */
0754             hpi_write_word(pdo, 0x01B7C11C, 0x8001);
0755             hpios_delay_micro_seconds(100);
0756 
0757             /* cpu  = 225/1 */
0758             hpi_write_word(pdo, 0x01B7C118, 0x8000);
0759 
0760             /* ~2ms delay */
0761             hpios_delay_micro_seconds(2000);
0762 
0763             /* PLL not bypassed */
0764             hpi_write_word(pdo, 0x01B7C100, 0x0001);
0765             /* ~2ms delay */
0766             hpios_delay_micro_seconds(2000);
0767         }
0768 
0769         /* test r/w to internal DSP memory
0770          * C6711 has L2 cache mapped to 0x0 when reset
0771          *
0772          *  revB - because of bug 3.0.1 last HPI read
0773          * (before HPI address issued) must be non-autoinc
0774          */
0775         /* test each bit in the 32bit word */
0776         for (i = 0; i < 100; i++) {
0777             test_addr = 0x00000000;
0778             test_data = 0x00000001;
0779             for (j = 0; j < 32; j++) {
0780                 hpi_write_word(pdo, test_addr + i, test_data);
0781                 data = hpi_read_word(pdo, test_addr + i);
0782                 if (data != test_data) {
0783                     HPI_DEBUG_LOG(ERROR,
0784                         "DSP mem %x %x %x %x\n",
0785                         test_addr + i, test_data,
0786                         data, dsp_index);
0787 
0788                     return HPI6000_ERROR_INIT_DSPINTMEM;
0789                 }
0790                 test_data = test_data << 1;
0791             }
0792         }
0793 
0794         /* memory map of ASI6200
0795            00000000-0000FFFF    16Kx32 internal program
0796            01800000-019FFFFF    Internal peripheral
0797            80000000-807FFFFF    CE0 2Mx32 SDRAM running @ 100MHz
0798            90000000-9000FFFF    CE1 Async peripherals:
0799 
0800            EMIF config
0801            ------------
0802            Global EMIF control
0803            0 -
0804            1 -
0805            2 -
0806            3 CLK2EN = 1   CLKOUT2 enabled
0807            4 CLK1EN = 0   CLKOUT1 disabled
0808            5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT
0809            6 -
0810            7 NOHOLD = 1   external HOLD disabled
0811            8 HOLDA = 0    HOLDA output is low
0812            9 HOLD = 0             HOLD input is low
0813            10 ARDY = 1    ARDY input is high
0814            11 BUSREQ = 0   BUSREQ output is low
0815            12,13 Reserved = 1
0816          */
0817         hpi_write_word(pdo, 0x01800000, 0x34A8);
0818 
0819         /* EMIF CE0 setup - 2Mx32 Sync DRAM
0820            31..28       Wr setup
0821            27..22       Wr strobe
0822            21..20       Wr hold
0823            19..16       Rd setup
0824            15..14       -
0825            13..8        Rd strobe
0826            7..4         MTYPE   0011            Sync DRAM 32bits
0827            3            Wr hold MSB
0828            2..0         Rd hold
0829          */
0830         hpi_write_word(pdo, 0x01800008, 0x00000030);
0831 
0832         /* EMIF SDRAM Extension
0833            31-21        0
0834            20           WR2RD = 0
0835            19-18        WR2DEAC = 1
0836            17           WR2WR = 0
0837            16-15        R2WDQM = 2
0838            14-12        RD2WR = 4
0839            11-10        RD2DEAC = 1
0840            9            RD2RD = 1
0841            8-7          THZP = 10b
0842            6-5          TWR  = 2-1 = 01b (tWR = 10ns)
0843            4            TRRD = 0b = 2 ECLK (tRRD = 14ns)
0844            3-1          TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK)
0845            1            CAS latency = 3 ECLK
0846            (for Micron 2M32-7 operating at 100Mhz)
0847          */
0848 
0849         /* need to use this else DSP code crashes */
0850         hpi_write_word(pdo, 0x01800020, 0x001BDF29);
0851 
0852         /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
0853            31           -               -
0854            30           SDBSZ   1               4 bank
0855            29..28       SDRSZ   00              11 row address pins
0856            27..26       SDCSZ   01              8 column address pins
0857            25           RFEN    1               refersh enabled
0858            24           INIT    1               init SDRAM
0859            23..20       TRCD    0001
0860            19..16       TRP             0001
0861            15..12       TRC             0110
0862            11..0        -               -
0863          */
0864         /*      need to use this else DSP code crashes */
0865         hpi_write_word(pdo, 0x01800018, 0x47117000);
0866 
0867         /* EMIF SDRAM Refresh Timing */
0868         hpi_write_word(pdo, 0x0180001C, 0x00000410);
0869 
0870         /*MIF CE1 setup - Async peripherals
0871            @100MHz bus speed, each cycle is 10ns,
0872            31..28       Wr setup  = 1
0873            27..22       Wr strobe = 3                   30ns
0874            21..20       Wr hold = 1
0875            19..16       Rd setup =1
0876            15..14       Ta = 2
0877            13..8        Rd strobe = 3                   30ns
0878            7..4         MTYPE   0010            Async 32bits
0879            3            Wr hold MSB =0
0880            2..0         Rd hold = 1
0881          */
0882         {
0883             u32 cE1 =
0884                 (1L << 28) | (3L << 22) | (1L << 20) | (1L <<
0885                 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L;
0886             hpi_write_word(pdo, 0x01800004, cE1);
0887         }
0888 
0889         /* delay a little to allow SDRAM and DSP to "get going" */
0890         hpios_delay_micro_seconds(1000);
0891 
0892         /* test access to SDRAM */
0893         {
0894             test_addr = 0x80000000;
0895             test_data = 0x00000001;
0896             /* test each bit in the 32bit word */
0897             for (j = 0; j < 32; j++) {
0898                 hpi_write_word(pdo, test_addr, test_data);
0899                 data = hpi_read_word(pdo, test_addr);
0900                 if (data != test_data) {
0901                     HPI_DEBUG_LOG(ERROR,
0902                         "DSP dram %x %x %x %x\n",
0903                         test_addr, test_data, data,
0904                         dsp_index);
0905 
0906                     return HPI6000_ERROR_INIT_SDRAM1;
0907                 }
0908                 test_data = test_data << 1;
0909             }
0910             /* test every Nth address in the DRAM */
0911 #define DRAM_SIZE_WORDS 0x200000    /*2_mx32 */
0912 #define DRAM_INC 1024
0913             test_addr = 0x80000000;
0914             test_data = 0x0;
0915             for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
0916                 hpi_write_word(pdo, test_addr + i, test_data);
0917                 test_data++;
0918             }
0919             test_addr = 0x80000000;
0920             test_data = 0x0;
0921             for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
0922                 data = hpi_read_word(pdo, test_addr + i);
0923                 if (data != test_data) {
0924                     HPI_DEBUG_LOG(ERROR,
0925                         "DSP dram %x %x %x %x\n",
0926                         test_addr + i, test_data,
0927                         data, dsp_index);
0928                     return HPI6000_ERROR_INIT_SDRAM2;
0929                 }
0930                 test_data++;
0931             }
0932 
0933         }
0934 
0935         /* write the DSP code down into the DSPs memory */
0936         error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev,
0937             &dsp_code, pos_error_code);
0938 
0939         if (error)
0940             return error;
0941 
0942         while (1) {
0943             u32 length;
0944             u32 address;
0945             u32 type;
0946             u32 *pcode;
0947 
0948             error = hpi_dsp_code_read_word(&dsp_code, &length);
0949             if (error)
0950                 break;
0951             if (length == 0xFFFFFFFF)
0952                 break;  /* end of code */
0953 
0954             error = hpi_dsp_code_read_word(&dsp_code, &address);
0955             if (error)
0956                 break;
0957             error = hpi_dsp_code_read_word(&dsp_code, &type);
0958             if (error)
0959                 break;
0960             error = hpi_dsp_code_read_block(length, &dsp_code,
0961                 &pcode);
0962             if (error)
0963                 break;
0964             error = hpi6000_dsp_block_write32(pao, (u16)dsp_index,
0965                 address, pcode, length);
0966             if (error)
0967                 break;
0968         }
0969 
0970         if (error) {
0971             hpi_dsp_code_close(&dsp_code);
0972             return error;
0973         }
0974         /* verify that code was written correctly */
0975         /* this time through, assume no errors in DSP code file/array */
0976         hpi_dsp_code_rewind(&dsp_code);
0977         while (1) {
0978             u32 length;
0979             u32 address;
0980             u32 type;
0981             u32 *pcode;
0982 
0983             hpi_dsp_code_read_word(&dsp_code, &length);
0984             if (length == 0xFFFFFFFF)
0985                 break;  /* end of code */
0986 
0987             hpi_dsp_code_read_word(&dsp_code, &address);
0988             hpi_dsp_code_read_word(&dsp_code, &type);
0989             hpi_dsp_code_read_block(length, &dsp_code, &pcode);
0990 
0991             for (i = 0; i < length; i++) {
0992                 data = hpi_read_word(pdo, address);
0993                 if (data != *pcode) {
0994                     error = HPI6000_ERROR_INIT_VERIFY;
0995                     HPI_DEBUG_LOG(ERROR,
0996                         "DSP verify %x %x %x %x\n",
0997                         address, *pcode, data,
0998                         dsp_index);
0999                     break;
1000                 }
1001                 pcode++;
1002                 address += 4;
1003             }
1004             if (error)
1005                 break;
1006         }
1007         hpi_dsp_code_close(&dsp_code);
1008         if (error)
1009             return error;
1010 
1011         /* zero out the hostmailbox */
1012         {
1013             u32 address = HPI_HIF_ADDR(host_cmd);
1014             for (i = 0; i < 4; i++) {
1015                 hpi_write_word(pdo, address, 0);
1016                 address += 4;
1017             }
1018         }
1019         /* write the DSP number into the hostmailbox */
1020         /* structure before starting the DSP */
1021         hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index);
1022 
1023         /* write the DSP adapter Info into the */
1024         /* hostmailbox before starting the DSP */
1025         if (dsp_index > 0)
1026             hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info),
1027                 adapter_info);
1028 
1029         /* step 3. Start code by sending interrupt */
1030         iowrite32(0x00030003, pdo->prHPI_control);
1031         hpios_delay_micro_seconds(10000);
1032 
1033         /* wait for a non-zero value in hostcmd -
1034          * indicating initialization is complete
1035          *
1036          * Init could take a while if DSP checks SDRAM memory
1037          * Was 200000. Increased to 2000000 for ASI8801 so we
1038          * don't get 938 errors.
1039          */
1040         timeout = 2000000;
1041         while (timeout) {
1042             do {
1043                 read = hpi_read_word(pdo,
1044                     HPI_HIF_ADDR(host_cmd));
1045             } while (--timeout
1046                 && hpi6000_check_PCI2040_error_flag(pao,
1047                     H6READ));
1048 
1049             if (read)
1050                 break;
1051             /* The following is a workaround for bug #94:
1052              * Bluescreen on install and subsequent boots on a
1053              * DELL PowerEdge 600SC PC with 1.8GHz P4 and
1054              * ServerWorks chipset. Without this delay the system
1055              * locks up with a bluescreen (NOT GPF or pagefault).
1056              */
1057             else
1058                 hpios_delay_micro_seconds(10000);
1059         }
1060         if (timeout == 0)
1061             return HPI6000_ERROR_INIT_NOACK;
1062 
1063         /* read the DSP adapter Info from the */
1064         /* hostmailbox structure after starting the DSP */
1065         if (dsp_index == 0) {
1066             /*u32 dwTestData=0; */
1067             u32 mask = 0;
1068 
1069             adapter_info =
1070                 hpi_read_word(pdo,
1071                 HPI_HIF_ADDR(adapter_info));
1072             if (HPI_ADAPTER_FAMILY_ASI
1073                 (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER
1074                     (adapter_info)) ==
1075                 HPI_ADAPTER_FAMILY_ASI(0x6200))
1076                 /* all 6200 cards have this many DSPs */
1077                 phw->num_dsp = 2;
1078 
1079             /* test that the PLD is programmed */
1080             /* and we can read/write 24bits */
1081 #define PLD_BASE_ADDRESS 0x90000000L    /*for ASI6100/6200/8800 */
1082 
1083             switch (boot_load_family) {
1084             case HPI_ADAPTER_FAMILY_ASI(0x6200):
1085                 /* ASI6100/6200 has 24bit path to FPGA */
1086                 mask = 0xFFFFFF00L;
1087                 /* ASI5100 uses AX6 code, */
1088                 /* but has no PLD r/w register to test */
1089                 if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
1090                         subsystem_device) ==
1091                     HPI_ADAPTER_FAMILY_ASI(0x5100))
1092                     mask = 0x00000000L;
1093                 /* ASI5200 uses AX6 code, */
1094                 /* but has no PLD r/w register to test */
1095                 if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
1096                         subsystem_device) ==
1097                     HPI_ADAPTER_FAMILY_ASI(0x5200))
1098                     mask = 0x00000000L;
1099                 break;
1100             case HPI_ADAPTER_FAMILY_ASI(0x8800):
1101                 /* ASI8800 has 16bit path to FPGA */
1102                 mask = 0xFFFF0000L;
1103                 break;
1104             }
1105             test_data = 0xAAAAAA00L & mask;
1106             /* write to 24 bit Debug register (D31-D8) */
1107             hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1108             read = hpi_read_word(pdo,
1109                 PLD_BASE_ADDRESS + 4L) & mask;
1110             if (read != test_data) {
1111                 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1112                     read);
1113                 return HPI6000_ERROR_INIT_PLDTEST1;
1114             }
1115             test_data = 0x55555500L & mask;
1116             hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1117             read = hpi_read_word(pdo,
1118                 PLD_BASE_ADDRESS + 4L) & mask;
1119             if (read != test_data) {
1120                 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1121                     read);
1122                 return HPI6000_ERROR_INIT_PLDTEST2;
1123             }
1124         }
1125     }   /* for numDSP */
1126     return 0;
1127 }
1128 
1129 #define PCI_TIMEOUT 100
1130 
1131 static int hpi_set_address(struct dsp_obj *pdo, u32 address)
1132 {
1133     u32 timeout = PCI_TIMEOUT;
1134 
1135     do {
1136         iowrite32(address, pdo->prHPI_address);
1137     } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter,
1138             H6WRITE)
1139         && --timeout);
1140 
1141     if (timeout)
1142         return 0;
1143 
1144     return 1;
1145 }
1146 
1147 /* write one word to the HPI port */
1148 static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data)
1149 {
1150     if (hpi_set_address(pdo, address))
1151         return;
1152     iowrite32(data, pdo->prHPI_data);
1153 }
1154 
1155 /* read one word from the HPI port */
1156 static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
1157 {
1158     u32 data = 0;
1159 
1160     if (hpi_set_address(pdo, address))
1161         return 0;   /*? No way to return error */
1162 
1163     /* take care of errata in revB DSP (2.0.1) */
1164     data = ioread32(pdo->prHPI_data);
1165     return data;
1166 }
1167 
1168 /* write a block of 32bit words to the DSP HPI port using auto-inc mode */
1169 static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1170     u32 length)
1171 {
1172     u16 length16 = length - 1;
1173 
1174     if (length == 0)
1175         return;
1176 
1177     if (hpi_set_address(pdo, address))
1178         return;
1179 
1180     iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1181 
1182     /* take care of errata in revB DSP (2.0.1) */
1183     /* must end with non auto-inc */
1184     iowrite32(*(pdata + length - 1), pdo->prHPI_data);
1185 }
1186 
1187 /** read a block of 32bit words from the DSP HPI port using auto-inc mode
1188  */
1189 static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1190     u32 length)
1191 {
1192     u16 length16 = length - 1;
1193 
1194     if (length == 0)
1195         return;
1196 
1197     if (hpi_set_address(pdo, address))
1198         return;
1199 
1200     ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1201 
1202     /* take care of errata in revB DSP (2.0.1) */
1203     /* must end with non auto-inc */
1204     *(pdata + length - 1) = ioread32(pdo->prHPI_data);
1205 }
1206 
1207 static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
1208     u16 dsp_index, u32 hpi_address, u32 *source, u32 count)
1209 {
1210     struct hpi_hw_obj *phw = pao->priv;
1211     struct dsp_obj *pdo = &phw->ado[dsp_index];
1212     u32 time_out = PCI_TIMEOUT;
1213     int c6711_burst_size = 128;
1214     u32 local_hpi_address = hpi_address;
1215     int local_count = count;
1216     int xfer_size;
1217     u32 *pdata = source;
1218 
1219     while (local_count) {
1220         if (local_count > c6711_burst_size)
1221             xfer_size = c6711_burst_size;
1222         else
1223             xfer_size = local_count;
1224 
1225         time_out = PCI_TIMEOUT;
1226         do {
1227             hpi_write_block(pdo, local_hpi_address, pdata,
1228                 xfer_size);
1229         } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1230             && --time_out);
1231 
1232         if (!time_out)
1233             break;
1234         pdata += xfer_size;
1235         local_hpi_address += sizeof(u32) * xfer_size;
1236         local_count -= xfer_size;
1237     }
1238 
1239     if (time_out)
1240         return 0;
1241     else
1242         return 1;
1243 }
1244 
1245 static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
1246     u16 dsp_index, u32 hpi_address, u32 *dest, u32 count)
1247 {
1248     struct hpi_hw_obj *phw = pao->priv;
1249     struct dsp_obj *pdo = &phw->ado[dsp_index];
1250     u32 time_out = PCI_TIMEOUT;
1251     int c6711_burst_size = 16;
1252     u32 local_hpi_address = hpi_address;
1253     int local_count = count;
1254     int xfer_size;
1255     u32 *pdata = dest;
1256     u32 loop_count = 0;
1257 
1258     while (local_count) {
1259         if (local_count > c6711_burst_size)
1260             xfer_size = c6711_burst_size;
1261         else
1262             xfer_size = local_count;
1263 
1264         time_out = PCI_TIMEOUT;
1265         do {
1266             hpi_read_block(pdo, local_hpi_address, pdata,
1267                 xfer_size);
1268         } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1269             && --time_out);
1270         if (!time_out)
1271             break;
1272 
1273         pdata += xfer_size;
1274         local_hpi_address += sizeof(u32) * xfer_size;
1275         local_count -= xfer_size;
1276         loop_count++;
1277     }
1278 
1279     if (time_out)
1280         return 0;
1281     else
1282         return 1;
1283 }
1284 
1285 static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
1286     u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr)
1287 {
1288     struct hpi_hw_obj *phw = pao->priv;
1289     struct dsp_obj *pdo = &phw->ado[dsp_index];
1290     u32 timeout;
1291     u16 ack;
1292     u32 address;
1293     u32 length;
1294     u32 *p_data;
1295     u16 error = 0;
1296 
1297     ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1298     if (ack & HPI_HIF_ERROR_MASK) {
1299         pao->dsp_crashed++;
1300         return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT;
1301     }
1302     pao->dsp_crashed = 0;
1303 
1304     /* get the message address and size */
1305     if (phw->message_buffer_address_on_dsp == 0) {
1306         timeout = TIMEOUT;
1307         do {
1308             address =
1309                 hpi_read_word(pdo,
1310                 HPI_HIF_ADDR(message_buffer_address));
1311             phw->message_buffer_address_on_dsp = address;
1312         } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1313             && --timeout);
1314         if (!timeout)
1315             return HPI6000_ERROR_MSG_GET_ADR;
1316     } else
1317         address = phw->message_buffer_address_on_dsp;
1318 
1319     length = phm->size;
1320 
1321     /* send the message */
1322     p_data = (u32 *)phm;
1323     if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
1324             (u16)length / 4))
1325         return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32;
1326 
1327     if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP))
1328         return HPI6000_ERROR_MSG_RESP_GETRESPCMD;
1329     hpi6000_send_dsp_interrupt(pdo);
1330 
1331     ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP);
1332     if (ack & HPI_HIF_ERROR_MASK)
1333         return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
1334 
1335     /* get the response address */
1336     if (phw->response_buffer_address_on_dsp == 0) {
1337         timeout = TIMEOUT;
1338         do {
1339             address =
1340                 hpi_read_word(pdo,
1341                 HPI_HIF_ADDR(response_buffer_address));
1342         } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1343             && --timeout);
1344         phw->response_buffer_address_on_dsp = address;
1345 
1346         if (!timeout)
1347             return HPI6000_ERROR_RESP_GET_ADR;
1348     } else
1349         address = phw->response_buffer_address_on_dsp;
1350 
1351     /* read the length of the response back from the DSP */
1352     timeout = TIMEOUT;
1353     do {
1354         length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1355     } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1356     if (!timeout)
1357         return HPI6000_ERROR_RESP_GET_LEN;
1358 
1359     if (length > phr->size)
1360         return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
1361 
1362     /* get the response */
1363     p_data = (u32 *)phr;
1364     if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
1365             (u16)length / 4))
1366         return HPI6000_ERROR_MSG_RESP_BLOCKREAD32;
1367 
1368     /* set i/f back to idle */
1369     if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1370         return HPI6000_ERROR_MSG_RESP_IDLECMD;
1371     hpi6000_send_dsp_interrupt(pdo);
1372 
1373     error = hpi_validate_response(phm, phr);
1374     return error;
1375 }
1376 
1377 /* have to set up the below defines to match stuff in the MAP file */
1378 
1379 #define MSG_ADDRESS (HPI_HIF_BASE+0x18)
1380 #define MSG_LENGTH 11
1381 #define RESP_ADDRESS (HPI_HIF_BASE+0x44)
1382 #define RESP_LENGTH 16
1383 #define QUEUE_START  (HPI_HIF_BASE+0x88)
1384 #define QUEUE_SIZE 0x8000
1385 
1386 static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords)
1387 {
1388 /*#define CHECKING       // comment this line in to enable checking */
1389 #ifdef CHECKING
1390     if (address < (u32)MSG_ADDRESS)
1391         return 0;
1392     if (address > (u32)(QUEUE_START + QUEUE_SIZE))
1393         return 0;
1394     if ((address + (length_in_dwords << 2)) >
1395         (u32)(QUEUE_START + QUEUE_SIZE))
1396         return 0;
1397 #else
1398     (void)address;
1399     (void)length_in_dwords;
1400     return 1;
1401 #endif
1402 }
1403 
1404 static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1405     struct hpi_message *phm, struct hpi_response *phr)
1406 {
1407     struct hpi_hw_obj *phw = pao->priv;
1408     struct dsp_obj *pdo = &phw->ado[dsp_index];
1409     u32 data_sent = 0;
1410     u16 ack;
1411     u32 length, address;
1412     u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1413     u16 time_out = 8;
1414 
1415     (void)phr;
1416 
1417     /* round dwDataSize down to nearest 4 bytes */
1418     while ((data_sent < (phm->u.d.u.data.data_size & ~3L))
1419         && --time_out) {
1420         ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1421         if (ack & HPI_HIF_ERROR_MASK)
1422             return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT;
1423 
1424         if (hpi6000_send_host_command(pao, dsp_index,
1425                 HPI_HIF_SEND_DATA))
1426             return HPI6000_ERROR_SEND_DATA_CMD;
1427 
1428         hpi6000_send_dsp_interrupt(pdo);
1429 
1430         ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA);
1431 
1432         if (ack & HPI_HIF_ERROR_MASK)
1433             return HPI6000_ERROR_SEND_DATA_ACK;
1434 
1435         do {
1436             /* get the address and size */
1437             address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1438             /* DSP returns number of DWORDS */
1439             length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1440         } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1441 
1442         if (!hpi6000_send_data_check_adr(address, length))
1443             return HPI6000_ERROR_SEND_DATA_ADR;
1444 
1445         /* send the data. break data into 512 DWORD blocks (2K bytes)
1446          * and send using block write. 2Kbytes is the max as this is the
1447          * memory window given to the HPI data register by the PCI2040
1448          */
1449 
1450         {
1451             u32 len = length;
1452             u32 blk_len = 512;
1453             while (len) {
1454                 if (len < blk_len)
1455                     blk_len = len;
1456                 if (hpi6000_dsp_block_write32(pao, dsp_index,
1457                         address, p_data, blk_len))
1458                     return HPI6000_ERROR_SEND_DATA_WRITE;
1459                 address += blk_len * 4;
1460                 p_data += blk_len;
1461                 len -= blk_len;
1462             }
1463         }
1464 
1465         if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1466             return HPI6000_ERROR_SEND_DATA_IDLECMD;
1467 
1468         hpi6000_send_dsp_interrupt(pdo);
1469 
1470         data_sent += length * 4;
1471     }
1472     if (!time_out)
1473         return HPI6000_ERROR_SEND_DATA_TIMEOUT;
1474     return 0;
1475 }
1476 
1477 static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1478     struct hpi_message *phm, struct hpi_response *phr)
1479 {
1480     struct hpi_hw_obj *phw = pao->priv;
1481     struct dsp_obj *pdo = &phw->ado[dsp_index];
1482     u32 data_got = 0;
1483     u16 ack;
1484     u32 length, address;
1485     u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1486 
1487     (void)phr;  /* this parameter not used! */
1488 
1489     /* round dwDataSize down to nearest 4 bytes */
1490     while (data_got < (phm->u.d.u.data.data_size & ~3L)) {
1491         ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1492         if (ack & HPI_HIF_ERROR_MASK)
1493             return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT;
1494 
1495         if (hpi6000_send_host_command(pao, dsp_index,
1496                 HPI_HIF_GET_DATA))
1497             return HPI6000_ERROR_GET_DATA_CMD;
1498         hpi6000_send_dsp_interrupt(pdo);
1499 
1500         ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA);
1501 
1502         if (ack & HPI_HIF_ERROR_MASK)
1503             return HPI6000_ERROR_GET_DATA_ACK;
1504 
1505         /* get the address and size */
1506         do {
1507             address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1508             length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1509         } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1510 
1511         /* read the data */
1512         {
1513             u32 len = length;
1514             u32 blk_len = 512;
1515             while (len) {
1516                 if (len < blk_len)
1517                     blk_len = len;
1518                 if (hpi6000_dsp_block_read32(pao, dsp_index,
1519                         address, p_data, blk_len))
1520                     return HPI6000_ERROR_GET_DATA_READ;
1521                 address += blk_len * 4;
1522                 p_data += blk_len;
1523                 len -= blk_len;
1524             }
1525         }
1526 
1527         if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1528             return HPI6000_ERROR_GET_DATA_IDLECMD;
1529         hpi6000_send_dsp_interrupt(pdo);
1530 
1531         data_got += length * 4;
1532     }
1533     return 0;
1534 }
1535 
1536 static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo)
1537 {
1538     iowrite32(0x00030003, pdo->prHPI_control);  /* DSPINT */
1539 }
1540 
1541 static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
1542     u16 dsp_index, u32 host_cmd)
1543 {
1544     struct hpi_hw_obj *phw = pao->priv;
1545     struct dsp_obj *pdo = &phw->ado[dsp_index];
1546     u32 timeout = TIMEOUT;
1547 
1548     /* set command */
1549     do {
1550         hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd);
1551         /* flush the FIFO */
1552         hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1553     } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout);
1554 
1555     /* reset the interrupt bit */
1556     iowrite32(0x00040004, pdo->prHPI_control);
1557 
1558     if (timeout)
1559         return 0;
1560     else
1561         return 1;
1562 }
1563 
1564 /* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */
1565 static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
1566     u16 read_or_write)
1567 {
1568     u32 hPI_error;
1569 
1570     struct hpi_hw_obj *phw = pao->priv;
1571 
1572     /* read the error bits from the PCI2040 */
1573     hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1574     if (hPI_error) {
1575         /* reset the error flag */
1576         iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1577         phw->pCI2040HPI_error_count++;
1578         if (read_or_write == 1)
1579             gw_pci_read_asserts++;     /************* inc global */
1580         else
1581             gw_pci_write_asserts++;
1582         return 1;
1583     } else
1584         return 0;
1585 }
1586 
1587 static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
1588     u32 ack_value)
1589 {
1590     struct hpi_hw_obj *phw = pao->priv;
1591     struct dsp_obj *pdo = &phw->ado[dsp_index];
1592     u32 ack = 0L;
1593     u32 timeout;
1594     u32 hPIC = 0L;
1595 
1596     /* wait for host interrupt to signal ack is ready */
1597     timeout = TIMEOUT;
1598     while (--timeout) {
1599         hPIC = ioread32(pdo->prHPI_control);
1600         if (hPIC & 0x04)    /* 0x04 = HINT from DSP */
1601             break;
1602     }
1603     if (timeout == 0)
1604         return HPI_HIF_ERROR_MASK;
1605 
1606     /* wait for dwAckValue */
1607     timeout = TIMEOUT;
1608     while (--timeout) {
1609         /* read the ack mailbox */
1610         ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack));
1611         if (ack == ack_value)
1612             break;
1613         if ((ack & HPI_HIF_ERROR_MASK)
1614             && !hpi6000_check_PCI2040_error_flag(pao, H6READ))
1615             break;
1616         /*for (i=0;i<1000;i++) */
1617         /*      dwPause=i+1; */
1618     }
1619     if (ack & HPI_HIF_ERROR_MASK)
1620         /* indicates bad read from DSP -
1621            typically 0xffffff is read for some reason */
1622         ack = HPI_HIF_ERROR_MASK;
1623 
1624     if (timeout == 0)
1625         ack = HPI_HIF_ERROR_MASK;
1626     return (short)ack;
1627 }
1628 
1629 static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
1630     struct hpi_message *phm)
1631 {
1632     const u16 dsp_index = 0;
1633     struct hpi_hw_obj *phw = pao->priv;
1634     struct dsp_obj *pdo = &phw->ado[dsp_index];
1635     u32 timeout;
1636     u32 cache_dirty_flag;
1637     u16 err;
1638 
1639     hpios_dsplock_lock(pao);
1640 
1641     timeout = TIMEOUT;
1642     do {
1643         cache_dirty_flag =
1644             hpi_read_word((struct dsp_obj *)pdo,
1645             HPI_HIF_ADDR(control_cache_is_dirty));
1646     } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1647     if (!timeout) {
1648         err = HPI6000_ERROR_CONTROL_CACHE_PARAMS;
1649         goto unlock;
1650     }
1651 
1652     if (cache_dirty_flag) {
1653         /* read the cached controls */
1654         u32 address;
1655         u32 length;
1656 
1657         timeout = TIMEOUT;
1658         if (pdo->control_cache_address_on_dsp == 0) {
1659             do {
1660                 address =
1661                     hpi_read_word((struct dsp_obj *)pdo,
1662                     HPI_HIF_ADDR(control_cache_address));
1663 
1664                 length = hpi_read_word((struct dsp_obj *)pdo,
1665                     HPI_HIF_ADDR
1666                     (control_cache_size_in_bytes));
1667             } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1668                 && --timeout);
1669             if (!timeout) {
1670                 err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN;
1671                 goto unlock;
1672             }
1673             pdo->control_cache_address_on_dsp = address;
1674             pdo->control_cache_length_on_dsp = length;
1675         } else {
1676             address = pdo->control_cache_address_on_dsp;
1677             length = pdo->control_cache_length_on_dsp;
1678         }
1679 
1680         if (hpi6000_dsp_block_read32(pao, dsp_index, address,
1681                 (u32 *)&phw->control_cache[0],
1682                 length / sizeof(u32))) {
1683             err = HPI6000_ERROR_CONTROL_CACHE_READ;
1684             goto unlock;
1685         }
1686         do {
1687             hpi_write_word((struct dsp_obj *)pdo,
1688                 HPI_HIF_ADDR(control_cache_is_dirty), 0);
1689             /* flush the FIFO */
1690             hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1691         } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1692             && --timeout);
1693         if (!timeout) {
1694             err = HPI6000_ERROR_CONTROL_CACHE_FLUSH;
1695             goto unlock;
1696         }
1697 
1698     }
1699     err = 0;
1700 
1701 unlock:
1702     hpios_dsplock_unlock(pao);
1703     return err;
1704 }
1705 
1706 /** Get dsp index for multi DSP adapters only */
1707 static u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm)
1708 {
1709     u16 ret = 0;
1710     switch (phm->object) {
1711     case HPI_OBJ_ISTREAM:
1712         if (phm->obj_index < 2)
1713             ret = 1;
1714         break;
1715     case HPI_OBJ_PROFILE:
1716         ret = phm->obj_index;
1717         break;
1718     default:
1719         break;
1720     }
1721     return ret;
1722 }
1723 
1724 /** Complete transaction with DSP
1725 
1726 Send message, get response, send or get stream data if any.
1727 */
1728 static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
1729     struct hpi_response *phr)
1730 {
1731     u16 error = 0;
1732     u16 dsp_index = 0;
1733     struct hpi_hw_obj *phw = pao->priv;
1734     u16 num_dsp = phw->num_dsp;
1735 
1736     if (num_dsp < 2)
1737         dsp_index = 0;
1738     else {
1739         dsp_index = get_dsp_index(pao, phm);
1740 
1741         /* is this  checked on the DSP anyway? */
1742         if ((phm->function == HPI_ISTREAM_GROUP_ADD)
1743             || (phm->function == HPI_OSTREAM_GROUP_ADD)) {
1744             struct hpi_message hm;
1745             u16 add_index;
1746             hm.obj_index = phm->u.d.u.stream.stream_index;
1747             hm.object = phm->u.d.u.stream.object_type;
1748             add_index = get_dsp_index(pao, &hm);
1749             if (add_index != dsp_index) {
1750                 phr->error = HPI_ERROR_NO_INTERDSP_GROUPS;
1751                 return;
1752             }
1753         }
1754     }
1755 
1756     hpios_dsplock_lock(pao);
1757     error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
1758 
1759     if (error)  /* something failed in the HPI/DSP interface */
1760         goto err;
1761 
1762     if (phr->error) /* something failed in the DSP */
1763         goto out;
1764 
1765     switch (phm->function) {
1766     case HPI_OSTREAM_WRITE:
1767     case HPI_ISTREAM_ANC_WRITE:
1768         error = hpi6000_send_data(pao, dsp_index, phm, phr);
1769         break;
1770     case HPI_ISTREAM_READ:
1771     case HPI_OSTREAM_ANC_READ:
1772         error = hpi6000_get_data(pao, dsp_index, phm, phr);
1773         break;
1774     case HPI_ADAPTER_GET_ASSERT:
1775         phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */
1776         if (num_dsp == 2) {
1777             if (!phr->u.ax.assert.count) {
1778                 /* no assert from dsp 0, check dsp 1 */
1779                 error = hpi6000_message_response_sequence(pao,
1780                     1, phm, phr);
1781                 phr->u.ax.assert.dsp_index = 1;
1782             }
1783         }
1784     }
1785 
1786 err:
1787     if (error) {
1788         if (error >= HPI_ERROR_BACKEND_BASE) {
1789             phr->error = HPI_ERROR_DSP_COMMUNICATION;
1790             phr->specific_error = error;
1791         } else {
1792             phr->error = error;
1793         }
1794 
1795         /* just the header of the response is valid */
1796         phr->size = sizeof(struct hpi_response_header);
1797     }
1798 out:
1799     hpios_dsplock_unlock(pao);
1800     return;
1801 }