18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/******************************************************************************
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci    AudioScience HPI driver
58c2ecf20Sopenharmony_ci    Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci Hardware Programming Interface (HPI) for AudioScience
98c2ecf20Sopenharmony_ci ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters.
108c2ecf20Sopenharmony_ci These PCI and PCIe bus adapters are based on a
118c2ecf20Sopenharmony_ci TMS320C6205 PCI bus mastering DSP,
128c2ecf20Sopenharmony_ci and (except ASI50xx) TI TMS320C6xxx floating point DSP
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci Exported function:
158c2ecf20Sopenharmony_ci void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci(C) Copyright AudioScience Inc. 1998-2010
188c2ecf20Sopenharmony_ci*******************************************************************************/
198c2ecf20Sopenharmony_ci#define SOURCEFILE_NAME "hpi6205.c"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include "hpi_internal.h"
228c2ecf20Sopenharmony_ci#include "hpimsginit.h"
238c2ecf20Sopenharmony_ci#include "hpidebug.h"
248c2ecf20Sopenharmony_ci#include "hpi6205.h"
258c2ecf20Sopenharmony_ci#include "hpidspcd.h"
268c2ecf20Sopenharmony_ci#include "hpicmn.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*****************************************************************************/
298c2ecf20Sopenharmony_ci/* HPI6205 specific error codes */
308c2ecf20Sopenharmony_ci#define HPI6205_ERROR_BASE 1000	/* not actually used anywhere */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* operational/messaging errors */
338c2ecf20Sopenharmony_ci#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT     1015
348c2ecf20Sopenharmony_ci#define HPI6205_ERROR_MSG_RESP_TIMEOUT          1016
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* initialization/bootload errors */
378c2ecf20Sopenharmony_ci#define HPI6205_ERROR_6205_NO_IRQ       1002
388c2ecf20Sopenharmony_ci#define HPI6205_ERROR_6205_INIT_FAILED  1003
398c2ecf20Sopenharmony_ci#define HPI6205_ERROR_6205_REG          1006
408c2ecf20Sopenharmony_ci#define HPI6205_ERROR_6205_DSPPAGE      1007
418c2ecf20Sopenharmony_ci#define HPI6205_ERROR_C6713_HPIC        1009
428c2ecf20Sopenharmony_ci#define HPI6205_ERROR_C6713_HPIA        1010
438c2ecf20Sopenharmony_ci#define HPI6205_ERROR_C6713_PLL         1011
448c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_INTMEM        1012
458c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_EXTMEM        1013
468c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_PLD           1014
478c2ecf20Sopenharmony_ci#define HPI6205_ERROR_6205_EEPROM       1017
488c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_EMIF1         1018
498c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_EMIF2         1019
508c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_EMIF3         1020
518c2ecf20Sopenharmony_ci#define HPI6205_ERROR_DSP_EMIF4         1021
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*****************************************************************************/
548c2ecf20Sopenharmony_ci/* for C6205 PCI i/f */
558c2ecf20Sopenharmony_ci/* Host Status Register (HSR) bitfields */
568c2ecf20Sopenharmony_ci#define C6205_HSR_INTSRC        0x01
578c2ecf20Sopenharmony_ci#define C6205_HSR_INTAVAL       0x02
588c2ecf20Sopenharmony_ci#define C6205_HSR_INTAM         0x04
598c2ecf20Sopenharmony_ci#define C6205_HSR_CFGERR        0x08
608c2ecf20Sopenharmony_ci#define C6205_HSR_EEREAD        0x10
618c2ecf20Sopenharmony_ci/* Host-to-DSP Control Register (HDCR) bitfields */
628c2ecf20Sopenharmony_ci#define C6205_HDCR_WARMRESET    0x01
638c2ecf20Sopenharmony_ci#define C6205_HDCR_DSPINT       0x02
648c2ecf20Sopenharmony_ci#define C6205_HDCR_PCIBOOT      0x04
658c2ecf20Sopenharmony_ci/* DSP Page Register (DSPP) bitfields, */
668c2ecf20Sopenharmony_ci/* defines 4 Mbyte page that BAR0 points to */
678c2ecf20Sopenharmony_ci#define C6205_DSPP_MAP1         0x400
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP.
708c2ecf20Sopenharmony_ci * BAR1 maps to non-prefetchable 8 Mbyte memory block
718c2ecf20Sopenharmony_ci * of DSP memory mapped registers (starting at 0x01800000).
728c2ecf20Sopenharmony_ci * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this
738c2ecf20Sopenharmony_ci * needs to be added to the BAR1 base address set in the PCI config reg
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_ci#define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L)
768c2ecf20Sopenharmony_ci#define C6205_BAR1_HSR  (C6205_BAR1_PCI_IO_OFFSET)
778c2ecf20Sopenharmony_ci#define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4)
788c2ecf20Sopenharmony_ci#define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8)
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/* used to control LED (revA) and reset C6713 (revB) */
818c2ecf20Sopenharmony_ci#define C6205_BAR0_TIMER1_CTL (0x01980000L)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/* For first 6713 in CE1 space, using DA17,16,2 */
848c2ecf20Sopenharmony_ci#define HPICL_ADDR      0x01400000L
858c2ecf20Sopenharmony_ci#define HPICH_ADDR      0x01400004L
868c2ecf20Sopenharmony_ci#define HPIAL_ADDR      0x01410000L
878c2ecf20Sopenharmony_ci#define HPIAH_ADDR      0x01410004L
888c2ecf20Sopenharmony_ci#define HPIDIL_ADDR     0x01420000L
898c2ecf20Sopenharmony_ci#define HPIDIH_ADDR     0x01420004L
908c2ecf20Sopenharmony_ci#define HPIDL_ADDR      0x01430000L
918c2ecf20Sopenharmony_ci#define HPIDH_ADDR      0x01430004L
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci#define C6713_EMIF_GCTL         0x01800000
948c2ecf20Sopenharmony_ci#define C6713_EMIF_CE1          0x01800004
958c2ecf20Sopenharmony_ci#define C6713_EMIF_CE0          0x01800008
968c2ecf20Sopenharmony_ci#define C6713_EMIF_CE2          0x01800010
978c2ecf20Sopenharmony_ci#define C6713_EMIF_CE3          0x01800014
988c2ecf20Sopenharmony_ci#define C6713_EMIF_SDRAMCTL     0x01800018
998c2ecf20Sopenharmony_ci#define C6713_EMIF_SDRAMTIMING  0x0180001C
1008c2ecf20Sopenharmony_ci#define C6713_EMIF_SDRAMEXT     0x01800020
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistruct hpi_hw_obj {
1038c2ecf20Sopenharmony_ci	/* PCI registers */
1048c2ecf20Sopenharmony_ci	__iomem u32 *prHSR;
1058c2ecf20Sopenharmony_ci	__iomem u32 *prHDCR;
1068c2ecf20Sopenharmony_ci	__iomem u32 *prDSPP;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	u32 dsp_page;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	struct consistent_dma_area h_locked_mem;
1118c2ecf20Sopenharmony_ci	struct bus_master_interface *p_interface_buffer;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	u16 flag_outstream_just_reset[HPI_MAX_STREAMS];
1148c2ecf20Sopenharmony_ci	/* a non-NULL handle means there is an HPI allocated buffer */
1158c2ecf20Sopenharmony_ci	struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS];
1168c2ecf20Sopenharmony_ci	struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS];
1178c2ecf20Sopenharmony_ci	/* non-zero size means a buffer exists, may be external */
1188c2ecf20Sopenharmony_ci	u32 instream_host_buffer_size[HPI_MAX_STREAMS];
1198c2ecf20Sopenharmony_ci	u32 outstream_host_buffer_size[HPI_MAX_STREAMS];
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	struct consistent_dma_area h_control_cache;
1228c2ecf20Sopenharmony_ci	struct hpi_control_cache *p_cache;
1238c2ecf20Sopenharmony_ci};
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci/*****************************************************************************/
1268c2ecf20Sopenharmony_ci/* local prototypes */
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci#define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write)
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic void send_dsp_command(struct hpi_hw_obj *phw, int cmd);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1358c2ecf20Sopenharmony_ci	u32 *pos_error_code);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic u16 message_response_sequence(struct hpi_adapter_obj *pao,
1388c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
1418c2ecf20Sopenharmony_ci	struct hpi_response *phr);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#define HPI6205_TIMEOUT 1000000
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic void subsys_create_adapter(struct hpi_message *phm,
1468c2ecf20Sopenharmony_ci	struct hpi_response *phr);
1478c2ecf20Sopenharmony_cistatic void adapter_delete(struct hpi_adapter_obj *pao,
1488c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic u16 create_adapter_obj(struct hpi_adapter_obj *pao,
1518c2ecf20Sopenharmony_ci	u32 *pos_error_code);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic void delete_adapter_obj(struct hpi_adapter_obj *pao);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao,
1568c2ecf20Sopenharmony_ci	u32 message);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1598c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1628c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
1658c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1668c2ecf20Sopenharmony_cistatic void outstream_write(struct hpi_adapter_obj *pao,
1678c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic void outstream_get_info(struct hpi_adapter_obj *pao,
1708c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic void outstream_start(struct hpi_adapter_obj *pao,
1738c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic void outstream_open(struct hpi_adapter_obj *pao,
1768c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic void outstream_reset(struct hpi_adapter_obj *pao,
1798c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1828c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1858c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic void instream_host_buffer_free(struct hpi_adapter_obj *pao,
1888c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic void instream_read(struct hpi_adapter_obj *pao,
1918c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic void instream_get_info(struct hpi_adapter_obj *pao,
1948c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic void instream_start(struct hpi_adapter_obj *pao,
1978c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
2008c2ecf20Sopenharmony_ci	u32 address);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
2038c2ecf20Sopenharmony_ci	int dsp_index, u32 address, u32 data);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic u16 boot_loader_config_emif(struct hpi_adapter_obj *pao,
2068c2ecf20Sopenharmony_ci	int dsp_index);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
2098c2ecf20Sopenharmony_ci	u32 address, u32 length);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
2128c2ecf20Sopenharmony_ci	int dsp_index);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
2158c2ecf20Sopenharmony_ci	int dsp_index);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/*****************************************************************************/
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic void subsys_message(struct hpi_adapter_obj *pao,
2228c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	switch (phm->function) {
2258c2ecf20Sopenharmony_ci	case HPI_SUBSYS_CREATE_ADAPTER:
2268c2ecf20Sopenharmony_ci		subsys_create_adapter(phm, phr);
2278c2ecf20Sopenharmony_ci		break;
2288c2ecf20Sopenharmony_ci	default:
2298c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_FUNC;
2308c2ecf20Sopenharmony_ci		break;
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic void control_message(struct hpi_adapter_obj *pao,
2358c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
2398c2ecf20Sopenharmony_ci	u16 pending_cache_error = 0;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	switch (phm->function) {
2428c2ecf20Sopenharmony_ci	case HPI_CONTROL_GET_STATE:
2438c2ecf20Sopenharmony_ci		if (pao->has_control_cache) {
2448c2ecf20Sopenharmony_ci			rmb();	/* make sure we see updates DMAed from DSP */
2458c2ecf20Sopenharmony_ci			if (hpi_check_control_cache(phw->p_cache, phm, phr)) {
2468c2ecf20Sopenharmony_ci				break;
2478c2ecf20Sopenharmony_ci			} else if (phm->u.c.attribute == HPI_METER_PEAK) {
2488c2ecf20Sopenharmony_ci				pending_cache_error =
2498c2ecf20Sopenharmony_ci					HPI_ERROR_CONTROL_CACHING;
2508c2ecf20Sopenharmony_ci			}
2518c2ecf20Sopenharmony_ci		}
2528c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
2538c2ecf20Sopenharmony_ci		if (pending_cache_error && !phr->error)
2548c2ecf20Sopenharmony_ci			phr->error = pending_cache_error;
2558c2ecf20Sopenharmony_ci		break;
2568c2ecf20Sopenharmony_ci	case HPI_CONTROL_GET_INFO:
2578c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
2588c2ecf20Sopenharmony_ci		break;
2598c2ecf20Sopenharmony_ci	case HPI_CONTROL_SET_STATE:
2608c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
2618c2ecf20Sopenharmony_ci		if (pao->has_control_cache)
2628c2ecf20Sopenharmony_ci			hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm,
2638c2ecf20Sopenharmony_ci				phr);
2648c2ecf20Sopenharmony_ci		break;
2658c2ecf20Sopenharmony_ci	default:
2668c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_FUNC;
2678c2ecf20Sopenharmony_ci		break;
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic void adapter_message(struct hpi_adapter_obj *pao,
2728c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	switch (phm->function) {
2758c2ecf20Sopenharmony_ci	case HPI_ADAPTER_DELETE:
2768c2ecf20Sopenharmony_ci		adapter_delete(pao, phm, phr);
2778c2ecf20Sopenharmony_ci		break;
2788c2ecf20Sopenharmony_ci	default:
2798c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
2808c2ecf20Sopenharmony_ci		break;
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic void outstream_message(struct hpi_adapter_obj *pao,
2858c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (phm->obj_index >= HPI_MAX_STREAMS) {
2898c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
2908c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(WARNING,
2918c2ecf20Sopenharmony_ci			"Message referencing invalid stream %d "
2928c2ecf20Sopenharmony_ci			"on adapter index %d\n", phm->obj_index,
2938c2ecf20Sopenharmony_ci			phm->adapter_index);
2948c2ecf20Sopenharmony_ci		return;
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	switch (phm->function) {
2988c2ecf20Sopenharmony_ci	case HPI_OSTREAM_WRITE:
2998c2ecf20Sopenharmony_ci		outstream_write(pao, phm, phr);
3008c2ecf20Sopenharmony_ci		break;
3018c2ecf20Sopenharmony_ci	case HPI_OSTREAM_GET_INFO:
3028c2ecf20Sopenharmony_ci		outstream_get_info(pao, phm, phr);
3038c2ecf20Sopenharmony_ci		break;
3048c2ecf20Sopenharmony_ci	case HPI_OSTREAM_HOSTBUFFER_ALLOC:
3058c2ecf20Sopenharmony_ci		outstream_host_buffer_allocate(pao, phm, phr);
3068c2ecf20Sopenharmony_ci		break;
3078c2ecf20Sopenharmony_ci	case HPI_OSTREAM_HOSTBUFFER_GET_INFO:
3088c2ecf20Sopenharmony_ci		outstream_host_buffer_get_info(pao, phm, phr);
3098c2ecf20Sopenharmony_ci		break;
3108c2ecf20Sopenharmony_ci	case HPI_OSTREAM_HOSTBUFFER_FREE:
3118c2ecf20Sopenharmony_ci		outstream_host_buffer_free(pao, phm, phr);
3128c2ecf20Sopenharmony_ci		break;
3138c2ecf20Sopenharmony_ci	case HPI_OSTREAM_START:
3148c2ecf20Sopenharmony_ci		outstream_start(pao, phm, phr);
3158c2ecf20Sopenharmony_ci		break;
3168c2ecf20Sopenharmony_ci	case HPI_OSTREAM_OPEN:
3178c2ecf20Sopenharmony_ci		outstream_open(pao, phm, phr);
3188c2ecf20Sopenharmony_ci		break;
3198c2ecf20Sopenharmony_ci	case HPI_OSTREAM_RESET:
3208c2ecf20Sopenharmony_ci		outstream_reset(pao, phm, phr);
3218c2ecf20Sopenharmony_ci		break;
3228c2ecf20Sopenharmony_ci	default:
3238c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
3248c2ecf20Sopenharmony_ci		break;
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic void instream_message(struct hpi_adapter_obj *pao,
3298c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (phm->obj_index >= HPI_MAX_STREAMS) {
3338c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
3348c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(WARNING,
3358c2ecf20Sopenharmony_ci			"Message referencing invalid stream %d "
3368c2ecf20Sopenharmony_ci			"on adapter index %d\n", phm->obj_index,
3378c2ecf20Sopenharmony_ci			phm->adapter_index);
3388c2ecf20Sopenharmony_ci		return;
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	switch (phm->function) {
3428c2ecf20Sopenharmony_ci	case HPI_ISTREAM_READ:
3438c2ecf20Sopenharmony_ci		instream_read(pao, phm, phr);
3448c2ecf20Sopenharmony_ci		break;
3458c2ecf20Sopenharmony_ci	case HPI_ISTREAM_GET_INFO:
3468c2ecf20Sopenharmony_ci		instream_get_info(pao, phm, phr);
3478c2ecf20Sopenharmony_ci		break;
3488c2ecf20Sopenharmony_ci	case HPI_ISTREAM_HOSTBUFFER_ALLOC:
3498c2ecf20Sopenharmony_ci		instream_host_buffer_allocate(pao, phm, phr);
3508c2ecf20Sopenharmony_ci		break;
3518c2ecf20Sopenharmony_ci	case HPI_ISTREAM_HOSTBUFFER_GET_INFO:
3528c2ecf20Sopenharmony_ci		instream_host_buffer_get_info(pao, phm, phr);
3538c2ecf20Sopenharmony_ci		break;
3548c2ecf20Sopenharmony_ci	case HPI_ISTREAM_HOSTBUFFER_FREE:
3558c2ecf20Sopenharmony_ci		instream_host_buffer_free(pao, phm, phr);
3568c2ecf20Sopenharmony_ci		break;
3578c2ecf20Sopenharmony_ci	case HPI_ISTREAM_START:
3588c2ecf20Sopenharmony_ci		instream_start(pao, phm, phr);
3598c2ecf20Sopenharmony_ci		break;
3608c2ecf20Sopenharmony_ci	default:
3618c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
3628c2ecf20Sopenharmony_ci		break;
3638c2ecf20Sopenharmony_ci	}
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci/*****************************************************************************/
3678c2ecf20Sopenharmony_ci/** Entry point to this HPI backend
3688c2ecf20Sopenharmony_ci * All calls to the HPI start here
3698c2ecf20Sopenharmony_ci */
3708c2ecf20Sopenharmony_cistatic
3718c2ecf20Sopenharmony_civoid _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
3728c2ecf20Sopenharmony_ci	struct hpi_response *phr)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	if (pao && (pao->dsp_crashed >= 10)
3758c2ecf20Sopenharmony_ci		&& (phm->function != HPI_ADAPTER_DEBUG_READ)) {
3768c2ecf20Sopenharmony_ci		/* allow last resort debug read even after crash */
3778c2ecf20Sopenharmony_ci		hpi_init_response(phr, phm->object, phm->function,
3788c2ecf20Sopenharmony_ci			HPI_ERROR_DSP_HARDWARE);
3798c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object,
3808c2ecf20Sopenharmony_ci			phm->function);
3818c2ecf20Sopenharmony_ci		return;
3828c2ecf20Sopenharmony_ci	}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	/* Init default response  */
3858c2ecf20Sopenharmony_ci	if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
3868c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_PROCESSING_MESSAGE;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(VERBOSE, "start of switch\n");
3898c2ecf20Sopenharmony_ci	switch (phm->type) {
3908c2ecf20Sopenharmony_ci	case HPI_TYPE_REQUEST:
3918c2ecf20Sopenharmony_ci		switch (phm->object) {
3928c2ecf20Sopenharmony_ci		case HPI_OBJ_SUBSYSTEM:
3938c2ecf20Sopenharmony_ci			subsys_message(pao, phm, phr);
3948c2ecf20Sopenharmony_ci			break;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		case HPI_OBJ_ADAPTER:
3978c2ecf20Sopenharmony_ci			adapter_message(pao, phm, phr);
3988c2ecf20Sopenharmony_ci			break;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci		case HPI_OBJ_CONTROL:
4018c2ecf20Sopenharmony_ci			control_message(pao, phm, phr);
4028c2ecf20Sopenharmony_ci			break;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		case HPI_OBJ_OSTREAM:
4058c2ecf20Sopenharmony_ci			outstream_message(pao, phm, phr);
4068c2ecf20Sopenharmony_ci			break;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		case HPI_OBJ_ISTREAM:
4098c2ecf20Sopenharmony_ci			instream_message(pao, phm, phr);
4108c2ecf20Sopenharmony_ci			break;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci		default:
4138c2ecf20Sopenharmony_ci			hw_message(pao, phm, phr);
4148c2ecf20Sopenharmony_ci			break;
4158c2ecf20Sopenharmony_ci		}
4168c2ecf20Sopenharmony_ci		break;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	default:
4198c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_TYPE;
4208c2ecf20Sopenharmony_ci		break;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_civoid HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	struct hpi_adapter_obj *pao = NULL;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	if (phm->object != HPI_OBJ_SUBSYSTEM) {
4298c2ecf20Sopenharmony_ci		/* normal messages must have valid adapter index */
4308c2ecf20Sopenharmony_ci		pao = hpi_find_adapter(phm->adapter_index);
4318c2ecf20Sopenharmony_ci	} else {
4328c2ecf20Sopenharmony_ci		/* subsys messages don't address an adapter */
4338c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
4348c2ecf20Sopenharmony_ci		return;
4358c2ecf20Sopenharmony_ci	}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (pao)
4388c2ecf20Sopenharmony_ci		_HPI_6205(pao, phm, phr);
4398c2ecf20Sopenharmony_ci	else
4408c2ecf20Sopenharmony_ci		hpi_init_response(phr, phm->object, phm->function,
4418c2ecf20Sopenharmony_ci			HPI_ERROR_BAD_ADAPTER_NUMBER);
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci/*****************************************************************************/
4458c2ecf20Sopenharmony_ci/* SUBSYSTEM */
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci/** Create an adapter object and initialise it based on resource information
4488c2ecf20Sopenharmony_ci * passed in in the message
4498c2ecf20Sopenharmony_ci * *** NOTE - you cannot use this function AND the FindAdapters function at the
4508c2ecf20Sopenharmony_ci * same time, the application must use only one of them to get the adapters ***
4518c2ecf20Sopenharmony_ci */
4528c2ecf20Sopenharmony_cistatic void subsys_create_adapter(struct hpi_message *phm,
4538c2ecf20Sopenharmony_ci	struct hpi_response *phr)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	/* create temp adapter obj, because we don't know what index yet */
4568c2ecf20Sopenharmony_ci	struct hpi_adapter_obj ao;
4578c2ecf20Sopenharmony_ci	u32 os_error_code;
4588c2ecf20Sopenharmony_ci	u16 err;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n");
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	memset(&ao, 0, sizeof(ao));
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
4658c2ecf20Sopenharmony_ci	if (!ao.priv) {
4668c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n");
4678c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_MEMORY_ALLOC;
4688c2ecf20Sopenharmony_ci		return;
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	ao.pci = *phm->u.s.resource.r.pci;
4728c2ecf20Sopenharmony_ci	err = create_adapter_obj(&ao, &os_error_code);
4738c2ecf20Sopenharmony_ci	if (err) {
4748c2ecf20Sopenharmony_ci		delete_adapter_obj(&ao);
4758c2ecf20Sopenharmony_ci		if (err >= HPI_ERROR_BACKEND_BASE) {
4768c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_DSP_BOOTLOAD;
4778c2ecf20Sopenharmony_ci			phr->specific_error = err;
4788c2ecf20Sopenharmony_ci		} else {
4798c2ecf20Sopenharmony_ci			phr->error = err;
4808c2ecf20Sopenharmony_ci		}
4818c2ecf20Sopenharmony_ci		phr->u.s.data = os_error_code;
4828c2ecf20Sopenharmony_ci		return;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	phr->u.s.adapter_type = ao.type;
4868c2ecf20Sopenharmony_ci	phr->u.s.adapter_index = ao.index;
4878c2ecf20Sopenharmony_ci	phr->error = 0;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci/** delete an adapter - required by WDM driver */
4918c2ecf20Sopenharmony_cistatic void adapter_delete(struct hpi_adapter_obj *pao,
4928c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	if (!pao) {
4978c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
4988c2ecf20Sopenharmony_ci		return;
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci	phw = pao->priv;
5018c2ecf20Sopenharmony_ci	/* reset adapter h/w */
5028c2ecf20Sopenharmony_ci	/* Reset C6713 #1 */
5038c2ecf20Sopenharmony_ci	boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
5048c2ecf20Sopenharmony_ci	/* reset C6205 */
5058c2ecf20Sopenharmony_ci	iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	delete_adapter_obj(pao);
5088c2ecf20Sopenharmony_ci	hpi_delete_adapter(pao);
5098c2ecf20Sopenharmony_ci	phr->error = 0;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/** Create adapter object
5138c2ecf20Sopenharmony_ci  allocate buffers, bootload DSPs, initialise control cache
5148c2ecf20Sopenharmony_ci*/
5158c2ecf20Sopenharmony_cistatic u16 create_adapter_obj(struct hpi_adapter_obj *pao,
5168c2ecf20Sopenharmony_ci	u32 *pos_error_code)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
5198c2ecf20Sopenharmony_ci	struct bus_master_interface *interface;
5208c2ecf20Sopenharmony_ci	u32 phys_addr;
5218c2ecf20Sopenharmony_ci	int i;
5228c2ecf20Sopenharmony_ci	u16 err;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	/* init error reporting */
5258c2ecf20Sopenharmony_ci	pao->dsp_crashed = 0;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	for (i = 0; i < HPI_MAX_STREAMS; i++)
5288c2ecf20Sopenharmony_ci		phw->flag_outstream_just_reset[i] = 1;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	/* The C6205 memory area 1 is 8Mbyte window into DSP registers */
5318c2ecf20Sopenharmony_ci	phw->prHSR =
5328c2ecf20Sopenharmony_ci		pao->pci.ap_mem_base[1] +
5338c2ecf20Sopenharmony_ci		C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);
5348c2ecf20Sopenharmony_ci	phw->prHDCR =
5358c2ecf20Sopenharmony_ci		pao->pci.ap_mem_base[1] +
5368c2ecf20Sopenharmony_ci		C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);
5378c2ecf20Sopenharmony_ci	phw->prDSPP =
5388c2ecf20Sopenharmony_ci		pao->pci.ap_mem_base[1] +
5398c2ecf20Sopenharmony_ci		C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	pao->has_control_cache = 0;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (hpios_locked_mem_alloc(&phw->h_locked_mem,
5448c2ecf20Sopenharmony_ci			sizeof(struct bus_master_interface),
5458c2ecf20Sopenharmony_ci			pao->pci.pci_dev))
5468c2ecf20Sopenharmony_ci		phw->p_interface_buffer = NULL;
5478c2ecf20Sopenharmony_ci	else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
5488c2ecf20Sopenharmony_ci			(void *)&phw->p_interface_buffer))
5498c2ecf20Sopenharmony_ci		phw->p_interface_buffer = NULL;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",
5528c2ecf20Sopenharmony_ci		phw->p_interface_buffer);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	if (phw->p_interface_buffer) {
5558c2ecf20Sopenharmony_ci		memset((void *)phw->p_interface_buffer, 0,
5568c2ecf20Sopenharmony_ci			sizeof(struct bus_master_interface));
5578c2ecf20Sopenharmony_ci		phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;
5588c2ecf20Sopenharmony_ci	}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	err = adapter_boot_load_dsp(pao, pos_error_code);
5618c2ecf20Sopenharmony_ci	if (err) {
5628c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "DSP code load failed\n");
5638c2ecf20Sopenharmony_ci		/* no need to clean up as SubSysCreateAdapter */
5648c2ecf20Sopenharmony_ci		/* calls DeleteAdapter on error. */
5658c2ecf20Sopenharmony_ci		return err;
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* allow boot load even if mem alloc wont work */
5708c2ecf20Sopenharmony_ci	if (!phw->p_interface_buffer)
5718c2ecf20Sopenharmony_ci		return HPI_ERROR_MEMORY_ALLOC;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	interface = phw->p_interface_buffer;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/* make sure the DSP has started ok */
5768c2ecf20Sopenharmony_ci	if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
5778c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
5788c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_INIT_FAILED;
5798c2ecf20Sopenharmony_ci	}
5808c2ecf20Sopenharmony_ci	/* Note that *pao, *phw are zeroed after allocation,
5818c2ecf20Sopenharmony_ci	 * so pointers and flags are NULL by default.
5828c2ecf20Sopenharmony_ci	 * Allocate bus mastering control cache buffer and tell the DSP about it
5838c2ecf20Sopenharmony_ci	 */
5848c2ecf20Sopenharmony_ci	if (interface->control_cache.number_of_controls) {
5858c2ecf20Sopenharmony_ci		u8 *p_control_cache_virtual;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci		err = hpios_locked_mem_alloc(&phw->h_control_cache,
5888c2ecf20Sopenharmony_ci			interface->control_cache.size_in_bytes,
5898c2ecf20Sopenharmony_ci			pao->pci.pci_dev);
5908c2ecf20Sopenharmony_ci		if (!err)
5918c2ecf20Sopenharmony_ci			err = hpios_locked_mem_get_virt_addr(&phw->
5928c2ecf20Sopenharmony_ci				h_control_cache,
5938c2ecf20Sopenharmony_ci				(void *)&p_control_cache_virtual);
5948c2ecf20Sopenharmony_ci		if (!err) {
5958c2ecf20Sopenharmony_ci			memset(p_control_cache_virtual, 0,
5968c2ecf20Sopenharmony_ci				interface->control_cache.size_in_bytes);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci			phw->p_cache =
5998c2ecf20Sopenharmony_ci				hpi_alloc_control_cache(interface->
6008c2ecf20Sopenharmony_ci				control_cache.number_of_controls,
6018c2ecf20Sopenharmony_ci				interface->control_cache.size_in_bytes,
6028c2ecf20Sopenharmony_ci				p_control_cache_virtual);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci			if (!phw->p_cache)
6058c2ecf20Sopenharmony_ci				err = HPI_ERROR_MEMORY_ALLOC;
6068c2ecf20Sopenharmony_ci		}
6078c2ecf20Sopenharmony_ci		if (!err) {
6088c2ecf20Sopenharmony_ci			err = hpios_locked_mem_get_phys_addr(&phw->
6098c2ecf20Sopenharmony_ci				h_control_cache, &phys_addr);
6108c2ecf20Sopenharmony_ci			interface->control_cache.physical_address32 =
6118c2ecf20Sopenharmony_ci				phys_addr;
6128c2ecf20Sopenharmony_ci		}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci		if (!err)
6158c2ecf20Sopenharmony_ci			pao->has_control_cache = 1;
6168c2ecf20Sopenharmony_ci		else {
6178c2ecf20Sopenharmony_ci			if (hpios_locked_mem_valid(&phw->h_control_cache))
6188c2ecf20Sopenharmony_ci				hpios_locked_mem_free(&phw->h_control_cache);
6198c2ecf20Sopenharmony_ci			pao->has_control_cache = 0;
6208c2ecf20Sopenharmony_ci		}
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci	send_dsp_command(phw, H620_HIF_IDLE);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	{
6258c2ecf20Sopenharmony_ci		struct hpi_message hm;
6268c2ecf20Sopenharmony_ci		struct hpi_response hr;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
6298c2ecf20Sopenharmony_ci		memset(&hm, 0, sizeof(hm));
6308c2ecf20Sopenharmony_ci		/* wAdapterIndex == version == 0 */
6318c2ecf20Sopenharmony_ci		hm.type = HPI_TYPE_REQUEST;
6328c2ecf20Sopenharmony_ci		hm.size = sizeof(hm);
6338c2ecf20Sopenharmony_ci		hm.object = HPI_OBJ_ADAPTER;
6348c2ecf20Sopenharmony_ci		hm.function = HPI_ADAPTER_GET_INFO;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci		memset(&hr, 0, sizeof(hr));
6378c2ecf20Sopenharmony_ci		hr.size = sizeof(hr);
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci		err = message_response_sequence(pao, &hm, &hr);
6408c2ecf20Sopenharmony_ci		if (err) {
6418c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
6428c2ecf20Sopenharmony_ci				err);
6438c2ecf20Sopenharmony_ci			return err;
6448c2ecf20Sopenharmony_ci		}
6458c2ecf20Sopenharmony_ci		if (hr.error)
6468c2ecf20Sopenharmony_ci			return hr.error;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci		pao->type = hr.u.ax.info.adapter_type;
6498c2ecf20Sopenharmony_ci		pao->index = hr.u.ax.info.adapter_index;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE,
6528c2ecf20Sopenharmony_ci			"got adapter info type %x index %d serial %d\n",
6538c2ecf20Sopenharmony_ci			hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,
6548c2ecf20Sopenharmony_ci			hr.u.ax.info.serial_number);
6558c2ecf20Sopenharmony_ci	}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	if (phw->p_cache)
6588c2ecf20Sopenharmony_ci		phw->p_cache->adap_idx = pao->index;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	pao->irq_query_and_clear = adapter_irq_query_and_clear;
6638c2ecf20Sopenharmony_ci	pao->instream_host_buffer_status =
6648c2ecf20Sopenharmony_ci		phw->p_interface_buffer->instream_host_buffer_status;
6658c2ecf20Sopenharmony_ci	pao->outstream_host_buffer_status =
6668c2ecf20Sopenharmony_ci		phw->p_interface_buffer->outstream_host_buffer_status;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	return hpi_add_adapter(pao);
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci/** Free memory areas allocated by adapter
6728c2ecf20Sopenharmony_ci * this routine is called from AdapterDelete,
6738c2ecf20Sopenharmony_ci  * and SubSysCreateAdapter if duplicate index
6748c2ecf20Sopenharmony_ci*/
6758c2ecf20Sopenharmony_cistatic void delete_adapter_obj(struct hpi_adapter_obj *pao)
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
6788c2ecf20Sopenharmony_ci	int i;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	if (hpios_locked_mem_valid(&phw->h_control_cache)) {
6818c2ecf20Sopenharmony_ci		hpios_locked_mem_free(&phw->h_control_cache);
6828c2ecf20Sopenharmony_ci		hpi_free_control_cache(phw->p_cache);
6838c2ecf20Sopenharmony_ci	}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	if (hpios_locked_mem_valid(&phw->h_locked_mem)) {
6868c2ecf20Sopenharmony_ci		hpios_locked_mem_free(&phw->h_locked_mem);
6878c2ecf20Sopenharmony_ci		phw->p_interface_buffer = NULL;
6888c2ecf20Sopenharmony_ci	}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	for (i = 0; i < HPI_MAX_STREAMS; i++)
6918c2ecf20Sopenharmony_ci		if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {
6928c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->instream_host_buffers[i]);
6938c2ecf20Sopenharmony_ci			/*?phw->InStreamHostBuffers[i] = NULL; */
6948c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[i] = 0;
6958c2ecf20Sopenharmony_ci		}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	for (i = 0; i < HPI_MAX_STREAMS; i++)
6988c2ecf20Sopenharmony_ci		if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {
6998c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->outstream_host_buffers
7008c2ecf20Sopenharmony_ci				[i]);
7018c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[i] = 0;
7028c2ecf20Sopenharmony_ci		}
7038c2ecf20Sopenharmony_ci	kfree(phw);
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci/*****************************************************************************/
7078c2ecf20Sopenharmony_ci/* Adapter functions */
7088c2ecf20Sopenharmony_cistatic int adapter_irq_query_and_clear(struct hpi_adapter_obj *pao,
7098c2ecf20Sopenharmony_ci	u32 message)
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
7128c2ecf20Sopenharmony_ci	u32 hsr = 0;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	hsr = ioread32(phw->prHSR);
7158c2ecf20Sopenharmony_ci	if (hsr & C6205_HSR_INTSRC) {
7168c2ecf20Sopenharmony_ci		/* reset the interrupt from the DSP */
7178c2ecf20Sopenharmony_ci		iowrite32(C6205_HSR_INTSRC, phw->prHSR);
7188c2ecf20Sopenharmony_ci		return HPI_IRQ_MIXER;
7198c2ecf20Sopenharmony_ci	}
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	return HPI_IRQ_NONE;
7228c2ecf20Sopenharmony_ci}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci/*****************************************************************************/
7258c2ecf20Sopenharmony_ci/* OutStream Host buffer functions */
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci/** Allocate or attach buffer for busmastering
7288c2ecf20Sopenharmony_ci*/
7298c2ecf20Sopenharmony_cistatic void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
7308c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
7318c2ecf20Sopenharmony_ci{
7328c2ecf20Sopenharmony_ci	u16 err = 0;
7338c2ecf20Sopenharmony_ci	u32 command = phm->u.d.u.buffer.command;
7348c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
7358c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	if (command == HPI_BUFFER_CMD_EXTERNAL
7408c2ecf20Sopenharmony_ci		|| command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
7418c2ecf20Sopenharmony_ci		/* ALLOC phase, allocate a buffer with power of 2 size,
7428c2ecf20Sopenharmony_ci		   get its bus address for PCI bus mastering
7438c2ecf20Sopenharmony_ci		 */
7448c2ecf20Sopenharmony_ci		phm->u.d.u.buffer.buffer_size =
7458c2ecf20Sopenharmony_ci			roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
7468c2ecf20Sopenharmony_ci		/* return old size and allocated size,
7478c2ecf20Sopenharmony_ci		   so caller can detect change */
7488c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.data_available =
7498c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[phm->obj_index];
7508c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.buffer_size =
7518c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci		if (phw->outstream_host_buffer_size[phm->obj_index] ==
7548c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size) {
7558c2ecf20Sopenharmony_ci			/* Same size, no action required */
7568c2ecf20Sopenharmony_ci			return;
7578c2ecf20Sopenharmony_ci		}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci		if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
7608c2ecf20Sopenharmony_ci					obj_index]))
7618c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->outstream_host_buffers
7628c2ecf20Sopenharmony_ci				[phm->obj_index]);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci		err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
7658c2ecf20Sopenharmony_ci			[phm->obj_index], phm->u.d.u.buffer.buffer_size,
7668c2ecf20Sopenharmony_ci			pao->pci.pci_dev);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci		if (err) {
7698c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_DATASIZE;
7708c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[phm->obj_index] = 0;
7718c2ecf20Sopenharmony_ci			return;
7728c2ecf20Sopenharmony_ci		}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		err = hpios_locked_mem_get_phys_addr
7758c2ecf20Sopenharmony_ci			(&phw->outstream_host_buffers[phm->obj_index],
7768c2ecf20Sopenharmony_ci			&phm->u.d.u.buffer.pci_address);
7778c2ecf20Sopenharmony_ci		/* get the phys addr into msg for single call alloc caller
7788c2ecf20Sopenharmony_ci		 * needs to do this for split alloc (or use the same message)
7798c2ecf20Sopenharmony_ci		 * return the phy address for split alloc in the respose too
7808c2ecf20Sopenharmony_ci		 */
7818c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.auxiliary_data_available =
7828c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.pci_address;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci		if (err) {
7858c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->outstream_host_buffers
7868c2ecf20Sopenharmony_ci				[phm->obj_index]);
7878c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[phm->obj_index] = 0;
7888c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_MEMORY_ALLOC;
7898c2ecf20Sopenharmony_ci			return;
7908c2ecf20Sopenharmony_ci		}
7918c2ecf20Sopenharmony_ci	}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	if (command == HPI_BUFFER_CMD_EXTERNAL
7948c2ecf20Sopenharmony_ci		|| command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
7958c2ecf20Sopenharmony_ci		/* GRANT phase.  Set up the BBM status, tell the DSP about
7968c2ecf20Sopenharmony_ci		   the buffer so it can start using BBM.
7978c2ecf20Sopenharmony_ci		 */
7988c2ecf20Sopenharmony_ci		struct hpi_hostbuffer_status *status;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci		if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
8018c2ecf20Sopenharmony_ci				buffer_size - 1)) {
8028c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR,
8038c2ecf20Sopenharmony_ci				"Buffer size must be 2^N not %d\n",
8048c2ecf20Sopenharmony_ci				phm->u.d.u.buffer.buffer_size);
8058c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_DATASIZE;
8068c2ecf20Sopenharmony_ci			return;
8078c2ecf20Sopenharmony_ci		}
8088c2ecf20Sopenharmony_ci		phw->outstream_host_buffer_size[phm->obj_index] =
8098c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size;
8108c2ecf20Sopenharmony_ci		status = &interface->outstream_host_buffer_status[phm->
8118c2ecf20Sopenharmony_ci			obj_index];
8128c2ecf20Sopenharmony_ci		status->samples_processed = 0;
8138c2ecf20Sopenharmony_ci		status->stream_state = HPI_STATE_STOPPED;
8148c2ecf20Sopenharmony_ci		status->dsp_index = 0;
8158c2ecf20Sopenharmony_ci		status->host_index = status->dsp_index;
8168c2ecf20Sopenharmony_ci		status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
8178c2ecf20Sopenharmony_ci		status->auxiliary_data_available = 0;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci		if (phr->error
8228c2ecf20Sopenharmony_ci			&& hpios_locked_mem_valid(&phw->
8238c2ecf20Sopenharmony_ci				outstream_host_buffers[phm->obj_index])) {
8248c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->outstream_host_buffers
8258c2ecf20Sopenharmony_ci				[phm->obj_index]);
8268c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[phm->obj_index] = 0;
8278c2ecf20Sopenharmony_ci		}
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_cistatic void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
8328c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
8338c2ecf20Sopenharmony_ci{
8348c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
8358c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
8368c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
8378c2ecf20Sopenharmony_ci	u8 *p_bbm_data;
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
8408c2ecf20Sopenharmony_ci				obj_index])) {
8418c2ecf20Sopenharmony_ci		if (hpios_locked_mem_get_virt_addr(&phw->
8428c2ecf20Sopenharmony_ci				outstream_host_buffers[phm->obj_index],
8438c2ecf20Sopenharmony_ci				(void *)&p_bbm_data)) {
8448c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_OPERATION;
8458c2ecf20Sopenharmony_ci			return;
8468c2ecf20Sopenharmony_ci		}
8478c2ecf20Sopenharmony_ci		status = &interface->outstream_host_buffer_status[phm->
8488c2ecf20Sopenharmony_ci			obj_index];
8498c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_OSTREAM,
8508c2ecf20Sopenharmony_ci			HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);
8518c2ecf20Sopenharmony_ci		phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
8528c2ecf20Sopenharmony_ci		phr->u.d.u.hostbuffer_info.p_status = status;
8538c2ecf20Sopenharmony_ci	} else {
8548c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_OSTREAM,
8558c2ecf20Sopenharmony_ci			HPI_OSTREAM_HOSTBUFFER_GET_INFO,
8568c2ecf20Sopenharmony_ci			HPI_ERROR_INVALID_OPERATION);
8578c2ecf20Sopenharmony_ci	}
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
8618c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
8648c2ecf20Sopenharmony_ci	u32 command = phm->u.d.u.buffer.command;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (phw->outstream_host_buffer_size[phm->obj_index]) {
8678c2ecf20Sopenharmony_ci		if (command == HPI_BUFFER_CMD_EXTERNAL
8688c2ecf20Sopenharmony_ci			|| command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
8698c2ecf20Sopenharmony_ci			phw->outstream_host_buffer_size[phm->obj_index] = 0;
8708c2ecf20Sopenharmony_ci			hw_message(pao, phm, phr);
8718c2ecf20Sopenharmony_ci			/* Tell adapter to stop using the host buffer. */
8728c2ecf20Sopenharmony_ci		}
8738c2ecf20Sopenharmony_ci		if (command == HPI_BUFFER_CMD_EXTERNAL
8748c2ecf20Sopenharmony_ci			|| command == HPI_BUFFER_CMD_INTERNAL_FREE)
8758c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->outstream_host_buffers
8768c2ecf20Sopenharmony_ci				[phm->obj_index]);
8778c2ecf20Sopenharmony_ci	}
8788c2ecf20Sopenharmony_ci	/* Should HPI_ERROR_INVALID_OPERATION be returned
8798c2ecf20Sopenharmony_ci	   if no host buffer is allocated? */
8808c2ecf20Sopenharmony_ci	else
8818c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_OSTREAM,
8828c2ecf20Sopenharmony_ci			HPI_OSTREAM_HOSTBUFFER_FREE, 0);
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_cistatic u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	return status->size_in_bytes - (status->host_index -
8898c2ecf20Sopenharmony_ci		status->dsp_index);
8908c2ecf20Sopenharmony_ci}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_cistatic void outstream_write(struct hpi_adapter_obj *pao,
8938c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
8968c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
8978c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
8988c2ecf20Sopenharmony_ci	u32 space_available;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	if (!phw->outstream_host_buffer_size[phm->obj_index]) {
9018c2ecf20Sopenharmony_ci		/* there  is no BBM buffer, write via message */
9028c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
9038c2ecf20Sopenharmony_ci		return;
9048c2ecf20Sopenharmony_ci	}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
9078c2ecf20Sopenharmony_ci	status = &interface->outstream_host_buffer_status[phm->obj_index];
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	space_available = outstream_get_space_available(status);
9108c2ecf20Sopenharmony_ci	if (space_available < phm->u.d.u.data.data_size) {
9118c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_DATASIZE;
9128c2ecf20Sopenharmony_ci		return;
9138c2ecf20Sopenharmony_ci	}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	/* HostBuffers is used to indicate host buffer is internally allocated.
9168c2ecf20Sopenharmony_ci	   otherwise, assumed external, data written externally */
9178c2ecf20Sopenharmony_ci	if (phm->u.d.u.data.pb_data
9188c2ecf20Sopenharmony_ci		&& hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
9198c2ecf20Sopenharmony_ci				obj_index])) {
9208c2ecf20Sopenharmony_ci		u8 *p_bbm_data;
9218c2ecf20Sopenharmony_ci		u32 l_first_write;
9228c2ecf20Sopenharmony_ci		u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci		if (hpios_locked_mem_get_virt_addr(&phw->
9258c2ecf20Sopenharmony_ci				outstream_host_buffers[phm->obj_index],
9268c2ecf20Sopenharmony_ci				(void *)&p_bbm_data)) {
9278c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_OPERATION;
9288c2ecf20Sopenharmony_ci			return;
9298c2ecf20Sopenharmony_ci		}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci		/* either all data,
9328c2ecf20Sopenharmony_ci		   or enough to fit from current to end of BBM buffer */
9338c2ecf20Sopenharmony_ci		l_first_write =
9348c2ecf20Sopenharmony_ci			min(phm->u.d.u.data.data_size,
9358c2ecf20Sopenharmony_ci			status->size_in_bytes -
9368c2ecf20Sopenharmony_ci			(status->host_index & (status->size_in_bytes - 1)));
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		memcpy(p_bbm_data +
9398c2ecf20Sopenharmony_ci			(status->host_index & (status->size_in_bytes - 1)),
9408c2ecf20Sopenharmony_ci			p_app_data, l_first_write);
9418c2ecf20Sopenharmony_ci		/* remaining data if any */
9428c2ecf20Sopenharmony_ci		memcpy(p_bbm_data, p_app_data + l_first_write,
9438c2ecf20Sopenharmony_ci			phm->u.d.u.data.data_size - l_first_write);
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	/*
9478c2ecf20Sopenharmony_ci	 * This version relies on the DSP code triggering an OStream buffer
9488c2ecf20Sopenharmony_ci	 * update immediately following a SET_FORMAT call. The host has
9498c2ecf20Sopenharmony_ci	 * already written data into the BBM buffer, but the DSP won't know
9508c2ecf20Sopenharmony_ci	 * about it until dwHostIndex is adjusted.
9518c2ecf20Sopenharmony_ci	 */
9528c2ecf20Sopenharmony_ci	if (phw->flag_outstream_just_reset[phm->obj_index]) {
9538c2ecf20Sopenharmony_ci		/* Format can only change after reset. Must tell DSP. */
9548c2ecf20Sopenharmony_ci		u16 function = phm->function;
9558c2ecf20Sopenharmony_ci		phw->flag_outstream_just_reset[phm->obj_index] = 0;
9568c2ecf20Sopenharmony_ci		phm->function = HPI_OSTREAM_SET_FORMAT;
9578c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);	/* send the format to the DSP */
9588c2ecf20Sopenharmony_ci		phm->function = function;
9598c2ecf20Sopenharmony_ci		if (phr->error)
9608c2ecf20Sopenharmony_ci			return;
9618c2ecf20Sopenharmony_ci	}
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	status->host_index += phm->u.d.u.data.data_size;
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_cistatic void outstream_get_info(struct hpi_adapter_obj *pao,
9678c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
9708c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
9718c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	if (!phw->outstream_host_buffer_size[phm->obj_index]) {
9748c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
9758c2ecf20Sopenharmony_ci		return;
9768c2ecf20Sopenharmony_ci	}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	status = &interface->outstream_host_buffer_status[phm->obj_index];
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.state = (u16)status->stream_state;
9838c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.samples_transferred =
9848c2ecf20Sopenharmony_ci		status->samples_processed;
9858c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
9868c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.data_available =
9878c2ecf20Sopenharmony_ci		status->size_in_bytes - outstream_get_space_available(status);
9888c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.auxiliary_data_available =
9898c2ecf20Sopenharmony_ci		status->auxiliary_data_available;
9908c2ecf20Sopenharmony_ci}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_cistatic void outstream_start(struct hpi_adapter_obj *pao,
9938c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
9948c2ecf20Sopenharmony_ci{
9958c2ecf20Sopenharmony_ci	hw_message(pao, phm, phr);
9968c2ecf20Sopenharmony_ci}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic void outstream_reset(struct hpi_adapter_obj *pao,
9998c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
10008c2ecf20Sopenharmony_ci{
10018c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
10028c2ecf20Sopenharmony_ci	phw->flag_outstream_just_reset[phm->obj_index] = 1;
10038c2ecf20Sopenharmony_ci	hw_message(pao, phm, phr);
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_cistatic void outstream_open(struct hpi_adapter_obj *pao,
10078c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	outstream_reset(pao, phm, phr);
10108c2ecf20Sopenharmony_ci}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci/*****************************************************************************/
10138c2ecf20Sopenharmony_ci/* InStream Host buffer functions */
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_cistatic void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
10168c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	u16 err = 0;
10198c2ecf20Sopenharmony_ci	u32 command = phm->u.d.u.buffer.command;
10208c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
10218c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	if (command == HPI_BUFFER_CMD_EXTERNAL
10268c2ecf20Sopenharmony_ci		|| command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci		phm->u.d.u.buffer.buffer_size =
10298c2ecf20Sopenharmony_ci			roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
10308c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.data_available =
10318c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[phm->obj_index];
10328c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.buffer_size =
10338c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size;
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci		if (phw->instream_host_buffer_size[phm->obj_index] ==
10368c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size) {
10378c2ecf20Sopenharmony_ci			/* Same size, no action required */
10388c2ecf20Sopenharmony_ci			return;
10398c2ecf20Sopenharmony_ci		}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
10428c2ecf20Sopenharmony_ci					obj_index]))
10438c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->instream_host_buffers
10448c2ecf20Sopenharmony_ci				[phm->obj_index]);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci		err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
10478c2ecf20Sopenharmony_ci				obj_index], phm->u.d.u.buffer.buffer_size,
10488c2ecf20Sopenharmony_ci			pao->pci.pci_dev);
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		if (err) {
10518c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_DATASIZE;
10528c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[phm->obj_index] = 0;
10538c2ecf20Sopenharmony_ci			return;
10548c2ecf20Sopenharmony_ci		}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci		err = hpios_locked_mem_get_phys_addr
10578c2ecf20Sopenharmony_ci			(&phw->instream_host_buffers[phm->obj_index],
10588c2ecf20Sopenharmony_ci			&phm->u.d.u.buffer.pci_address);
10598c2ecf20Sopenharmony_ci		/* get the phys addr into msg for single call alloc. Caller
10608c2ecf20Sopenharmony_ci		   needs to do this for split alloc so return the phy address */
10618c2ecf20Sopenharmony_ci		phr->u.d.u.stream_info.auxiliary_data_available =
10628c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.pci_address;
10638c2ecf20Sopenharmony_ci		if (err) {
10648c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->instream_host_buffers
10658c2ecf20Sopenharmony_ci				[phm->obj_index]);
10668c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[phm->obj_index] = 0;
10678c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_MEMORY_ALLOC;
10688c2ecf20Sopenharmony_ci			return;
10698c2ecf20Sopenharmony_ci		}
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	if (command == HPI_BUFFER_CMD_EXTERNAL
10738c2ecf20Sopenharmony_ci		|| command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
10748c2ecf20Sopenharmony_ci		struct hpi_hostbuffer_status *status;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
10778c2ecf20Sopenharmony_ci				buffer_size - 1)) {
10788c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR,
10798c2ecf20Sopenharmony_ci				"Buffer size must be 2^N not %d\n",
10808c2ecf20Sopenharmony_ci				phm->u.d.u.buffer.buffer_size);
10818c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_DATASIZE;
10828c2ecf20Sopenharmony_ci			return;
10838c2ecf20Sopenharmony_ci		}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci		phw->instream_host_buffer_size[phm->obj_index] =
10868c2ecf20Sopenharmony_ci			phm->u.d.u.buffer.buffer_size;
10878c2ecf20Sopenharmony_ci		status = &interface->instream_host_buffer_status[phm->
10888c2ecf20Sopenharmony_ci			obj_index];
10898c2ecf20Sopenharmony_ci		status->samples_processed = 0;
10908c2ecf20Sopenharmony_ci		status->stream_state = HPI_STATE_STOPPED;
10918c2ecf20Sopenharmony_ci		status->dsp_index = 0;
10928c2ecf20Sopenharmony_ci		status->host_index = status->dsp_index;
10938c2ecf20Sopenharmony_ci		status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
10948c2ecf20Sopenharmony_ci		status->auxiliary_data_available = 0;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci		if (phr->error
10998c2ecf20Sopenharmony_ci			&& hpios_locked_mem_valid(&phw->
11008c2ecf20Sopenharmony_ci				instream_host_buffers[phm->obj_index])) {
11018c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->instream_host_buffers
11028c2ecf20Sopenharmony_ci				[phm->obj_index]);
11038c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[phm->obj_index] = 0;
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci}
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_cistatic void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
11098c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
11128c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
11138c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
11148c2ecf20Sopenharmony_ci	u8 *p_bbm_data;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
11178c2ecf20Sopenharmony_ci				obj_index])) {
11188c2ecf20Sopenharmony_ci		if (hpios_locked_mem_get_virt_addr(&phw->
11198c2ecf20Sopenharmony_ci				instream_host_buffers[phm->obj_index],
11208c2ecf20Sopenharmony_ci				(void *)&p_bbm_data)) {
11218c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_OPERATION;
11228c2ecf20Sopenharmony_ci			return;
11238c2ecf20Sopenharmony_ci		}
11248c2ecf20Sopenharmony_ci		status = &interface->instream_host_buffer_status[phm->
11258c2ecf20Sopenharmony_ci			obj_index];
11268c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_ISTREAM,
11278c2ecf20Sopenharmony_ci			HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);
11288c2ecf20Sopenharmony_ci		phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
11298c2ecf20Sopenharmony_ci		phr->u.d.u.hostbuffer_info.p_status = status;
11308c2ecf20Sopenharmony_ci	} else {
11318c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_ISTREAM,
11328c2ecf20Sopenharmony_ci			HPI_ISTREAM_HOSTBUFFER_GET_INFO,
11338c2ecf20Sopenharmony_ci			HPI_ERROR_INVALID_OPERATION);
11348c2ecf20Sopenharmony_ci	}
11358c2ecf20Sopenharmony_ci}
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cistatic void instream_host_buffer_free(struct hpi_adapter_obj *pao,
11388c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
11398c2ecf20Sopenharmony_ci{
11408c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
11418c2ecf20Sopenharmony_ci	u32 command = phm->u.d.u.buffer.command;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	if (phw->instream_host_buffer_size[phm->obj_index]) {
11448c2ecf20Sopenharmony_ci		if (command == HPI_BUFFER_CMD_EXTERNAL
11458c2ecf20Sopenharmony_ci			|| command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
11468c2ecf20Sopenharmony_ci			phw->instream_host_buffer_size[phm->obj_index] = 0;
11478c2ecf20Sopenharmony_ci			hw_message(pao, phm, phr);
11488c2ecf20Sopenharmony_ci		}
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci		if (command == HPI_BUFFER_CMD_EXTERNAL
11518c2ecf20Sopenharmony_ci			|| command == HPI_BUFFER_CMD_INTERNAL_FREE)
11528c2ecf20Sopenharmony_ci			hpios_locked_mem_free(&phw->instream_host_buffers
11538c2ecf20Sopenharmony_ci				[phm->obj_index]);
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	} else {
11568c2ecf20Sopenharmony_ci		/* Should HPI_ERROR_INVALID_OPERATION be returned
11578c2ecf20Sopenharmony_ci		   if no host buffer is allocated? */
11588c2ecf20Sopenharmony_ci		hpi_init_response(phr, HPI_OBJ_ISTREAM,
11598c2ecf20Sopenharmony_ci			HPI_ISTREAM_HOSTBUFFER_FREE, 0);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci}
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_cistatic void instream_start(struct hpi_adapter_obj *pao,
11668c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	hw_message(pao, phm, phr);
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_cistatic u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
11728c2ecf20Sopenharmony_ci{
11738c2ecf20Sopenharmony_ci	return status->dsp_index - status->host_index;
11748c2ecf20Sopenharmony_ci}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic void instream_read(struct hpi_adapter_obj *pao,
11778c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
11788c2ecf20Sopenharmony_ci{
11798c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
11808c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
11818c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
11828c2ecf20Sopenharmony_ci	u32 data_available;
11838c2ecf20Sopenharmony_ci	u8 *p_bbm_data;
11848c2ecf20Sopenharmony_ci	u32 l_first_read;
11858c2ecf20Sopenharmony_ci	u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	if (!phw->instream_host_buffer_size[phm->obj_index]) {
11888c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
11898c2ecf20Sopenharmony_ci		return;
11908c2ecf20Sopenharmony_ci	}
11918c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	status = &interface->instream_host_buffer_status[phm->obj_index];
11948c2ecf20Sopenharmony_ci	data_available = instream_get_bytes_available(status);
11958c2ecf20Sopenharmony_ci	if (data_available < phm->u.d.u.data.data_size) {
11968c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_INVALID_DATASIZE;
11978c2ecf20Sopenharmony_ci		return;
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
12018c2ecf20Sopenharmony_ci				obj_index])) {
12028c2ecf20Sopenharmony_ci		if (hpios_locked_mem_get_virt_addr(&phw->
12038c2ecf20Sopenharmony_ci				instream_host_buffers[phm->obj_index],
12048c2ecf20Sopenharmony_ci				(void *)&p_bbm_data)) {
12058c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_INVALID_OPERATION;
12068c2ecf20Sopenharmony_ci			return;
12078c2ecf20Sopenharmony_ci		}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci		/* either all data,
12108c2ecf20Sopenharmony_ci		   or enough to fit from current to end of BBM buffer */
12118c2ecf20Sopenharmony_ci		l_first_read =
12128c2ecf20Sopenharmony_ci			min(phm->u.d.u.data.data_size,
12138c2ecf20Sopenharmony_ci			status->size_in_bytes -
12148c2ecf20Sopenharmony_ci			(status->host_index & (status->size_in_bytes - 1)));
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci		memcpy(p_app_data,
12178c2ecf20Sopenharmony_ci			p_bbm_data +
12188c2ecf20Sopenharmony_ci			(status->host_index & (status->size_in_bytes - 1)),
12198c2ecf20Sopenharmony_ci			l_first_read);
12208c2ecf20Sopenharmony_ci		/* remaining data if any */
12218c2ecf20Sopenharmony_ci		memcpy(p_app_data + l_first_read, p_bbm_data,
12228c2ecf20Sopenharmony_ci			phm->u.d.u.data.data_size - l_first_read);
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci	status->host_index += phm->u.d.u.data.data_size;
12258c2ecf20Sopenharmony_ci}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_cistatic void instream_get_info(struct hpi_adapter_obj *pao,
12288c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
12298c2ecf20Sopenharmony_ci{
12308c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
12318c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
12328c2ecf20Sopenharmony_ci	struct hpi_hostbuffer_status *status;
12338c2ecf20Sopenharmony_ci	if (!phw->instream_host_buffer_size[phm->obj_index]) {
12348c2ecf20Sopenharmony_ci		hw_message(pao, phm, phr);
12358c2ecf20Sopenharmony_ci		return;
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	status = &interface->instream_host_buffer_status[phm->obj_index];
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	hpi_init_response(phr, phm->object, phm->function, 0);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.state = (u16)status->stream_state;
12438c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.samples_transferred =
12448c2ecf20Sopenharmony_ci		status->samples_processed;
12458c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
12468c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.data_available =
12478c2ecf20Sopenharmony_ci		instream_get_bytes_available(status);
12488c2ecf20Sopenharmony_ci	phr->u.d.u.stream_info.auxiliary_data_available =
12498c2ecf20Sopenharmony_ci		status->auxiliary_data_available;
12508c2ecf20Sopenharmony_ci}
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci/*****************************************************************************/
12538c2ecf20Sopenharmony_ci/* LOW-LEVEL */
12548c2ecf20Sopenharmony_ci#define HPI6205_MAX_FILES_TO_LOAD 2
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_cistatic u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
12578c2ecf20Sopenharmony_ci	u32 *pos_error_code)
12588c2ecf20Sopenharmony_ci{
12598c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
12608c2ecf20Sopenharmony_ci	struct dsp_code dsp_code;
12618c2ecf20Sopenharmony_ci	u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
12628c2ecf20Sopenharmony_ci	u32 temp;
12638c2ecf20Sopenharmony_ci	int dsp = 0, i = 0;
12648c2ecf20Sopenharmony_ci	u16 err = 0;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	boot_code_id[1] = pao->pci.pci_dev->subsystem_device;
12698c2ecf20Sopenharmony_ci	boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]);
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	/* fix up cases where bootcode id[1] != subsys id */
12728c2ecf20Sopenharmony_ci	switch (boot_code_id[1]) {
12738c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x5000):
12748c2ecf20Sopenharmony_ci		boot_code_id[0] = boot_code_id[1];
12758c2ecf20Sopenharmony_ci		boot_code_id[1] = 0;
12768c2ecf20Sopenharmony_ci		break;
12778c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x5300):
12788c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x5400):
12798c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x6300):
12808c2ecf20Sopenharmony_ci		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400);
12818c2ecf20Sopenharmony_ci		break;
12828c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x5500):
12838c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x5600):
12848c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x6500):
12858c2ecf20Sopenharmony_ci		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600);
12868c2ecf20Sopenharmony_ci		break;
12878c2ecf20Sopenharmony_ci	case HPI_ADAPTER_FAMILY_ASI(0x8800):
12888c2ecf20Sopenharmony_ci		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900);
12898c2ecf20Sopenharmony_ci		break;
12908c2ecf20Sopenharmony_ci	default:
12918c2ecf20Sopenharmony_ci		break;
12928c2ecf20Sopenharmony_ci	}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	/* reset DSP by writing a 1 to the WARMRESET bit */
12958c2ecf20Sopenharmony_ci	temp = C6205_HDCR_WARMRESET;
12968c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prHDCR);
12978c2ecf20Sopenharmony_ci	hpios_delay_micro_seconds(1000);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	/* check that PCI i/f was configured by EEPROM */
13008c2ecf20Sopenharmony_ci	temp = ioread32(phw->prHSR);
13018c2ecf20Sopenharmony_ci	if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
13028c2ecf20Sopenharmony_ci		C6205_HSR_EEREAD)
13038c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_EEPROM;
13048c2ecf20Sopenharmony_ci	temp |= 0x04;
13058c2ecf20Sopenharmony_ci	/* disable PINTA interrupt */
13068c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prHSR);
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	/* check control register reports PCI boot mode */
13098c2ecf20Sopenharmony_ci	temp = ioread32(phw->prHDCR);
13108c2ecf20Sopenharmony_ci	if (!(temp & C6205_HDCR_PCIBOOT))
13118c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_REG;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	/* try writing a few numbers to the DSP page register */
13148c2ecf20Sopenharmony_ci	/* and reading them back. */
13158c2ecf20Sopenharmony_ci	temp = 3;
13168c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prDSPP);
13178c2ecf20Sopenharmony_ci	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
13188c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_DSPPAGE;
13198c2ecf20Sopenharmony_ci	temp = 2;
13208c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prDSPP);
13218c2ecf20Sopenharmony_ci	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
13228c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_DSPPAGE;
13238c2ecf20Sopenharmony_ci	temp = 1;
13248c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prDSPP);
13258c2ecf20Sopenharmony_ci	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
13268c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_DSPPAGE;
13278c2ecf20Sopenharmony_ci	/* reset DSP page to the correct number */
13288c2ecf20Sopenharmony_ci	temp = 0;
13298c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prDSPP);
13308c2ecf20Sopenharmony_ci	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
13318c2ecf20Sopenharmony_ci		return HPI6205_ERROR_6205_DSPPAGE;
13328c2ecf20Sopenharmony_ci	phw->dsp_page = 0;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	/* release 6713 from reset before 6205 is bootloaded.
13358c2ecf20Sopenharmony_ci	   This ensures that the EMIF is inactive,
13368c2ecf20Sopenharmony_ci	   and the 6713 HPI gets the correct bootmode etc
13378c2ecf20Sopenharmony_ci	 */
13388c2ecf20Sopenharmony_ci	if (boot_code_id[1] != 0) {
13398c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
13408c2ecf20Sopenharmony_ci		/* CLKX0 <- '1' release the C6205 bootmode pulldowns */
13418c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, 0x018C0024, 0x00002202);
13428c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(100);
13438c2ecf20Sopenharmony_ci		/* Reset the 6713 #1 - revB */
13448c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
13458c2ecf20Sopenharmony_ci		/* value of bit 3 is unknown after DSP reset, other bits shoudl be 0 */
13468c2ecf20Sopenharmony_ci		if (0 != (boot_loader_read_mem32(pao, 0,
13478c2ecf20Sopenharmony_ci					(C6205_BAR0_TIMER1_CTL)) & ~8))
13488c2ecf20Sopenharmony_ci			return HPI6205_ERROR_6205_REG;
13498c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(100);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci		/* Release C6713 from reset - revB */
13528c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);
13538c2ecf20Sopenharmony_ci		if (4 != (boot_loader_read_mem32(pao, 0,
13548c2ecf20Sopenharmony_ci					(C6205_BAR0_TIMER1_CTL)) & ~8))
13558c2ecf20Sopenharmony_ci			return HPI6205_ERROR_6205_REG;
13568c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(100);
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {
13608c2ecf20Sopenharmony_ci		/* is there a DSP to load? */
13618c2ecf20Sopenharmony_ci		if (boot_code_id[dsp] == 0)
13628c2ecf20Sopenharmony_ci			continue;
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci		err = boot_loader_config_emif(pao, dsp);
13658c2ecf20Sopenharmony_ci		if (err)
13668c2ecf20Sopenharmony_ci			return err;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci		err = boot_loader_test_internal_memory(pao, dsp);
13698c2ecf20Sopenharmony_ci		if (err)
13708c2ecf20Sopenharmony_ci			return err;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci		err = boot_loader_test_external_memory(pao, dsp);
13738c2ecf20Sopenharmony_ci		if (err)
13748c2ecf20Sopenharmony_ci			return err;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci		err = boot_loader_test_pld(pao, dsp);
13778c2ecf20Sopenharmony_ci		if (err)
13788c2ecf20Sopenharmony_ci			return err;
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci		/* write the DSP code down into the DSPs memory */
13818c2ecf20Sopenharmony_ci		err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev,
13828c2ecf20Sopenharmony_ci			&dsp_code, pos_error_code);
13838c2ecf20Sopenharmony_ci		if (err)
13848c2ecf20Sopenharmony_ci			return err;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci		while (1) {
13878c2ecf20Sopenharmony_ci			u32 length;
13888c2ecf20Sopenharmony_ci			u32 address;
13898c2ecf20Sopenharmony_ci			u32 type;
13908c2ecf20Sopenharmony_ci			u32 *pcode;
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci			err = hpi_dsp_code_read_word(&dsp_code, &length);
13938c2ecf20Sopenharmony_ci			if (err)
13948c2ecf20Sopenharmony_ci				break;
13958c2ecf20Sopenharmony_ci			if (length == 0xFFFFFFFF)
13968c2ecf20Sopenharmony_ci				break;	/* end of code */
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci			err = hpi_dsp_code_read_word(&dsp_code, &address);
13998c2ecf20Sopenharmony_ci			if (err)
14008c2ecf20Sopenharmony_ci				break;
14018c2ecf20Sopenharmony_ci			err = hpi_dsp_code_read_word(&dsp_code, &type);
14028c2ecf20Sopenharmony_ci			if (err)
14038c2ecf20Sopenharmony_ci				break;
14048c2ecf20Sopenharmony_ci			err = hpi_dsp_code_read_block(length, &dsp_code,
14058c2ecf20Sopenharmony_ci				&pcode);
14068c2ecf20Sopenharmony_ci			if (err)
14078c2ecf20Sopenharmony_ci				break;
14088c2ecf20Sopenharmony_ci			for (i = 0; i < (int)length; i++) {
14098c2ecf20Sopenharmony_ci				boot_loader_write_mem32(pao, dsp, address,
14108c2ecf20Sopenharmony_ci					*pcode);
14118c2ecf20Sopenharmony_ci				/* dummy read every 4 words */
14128c2ecf20Sopenharmony_ci				/* for 6205 advisory 1.4.4 */
14138c2ecf20Sopenharmony_ci				if (i % 4 == 0)
14148c2ecf20Sopenharmony_ci					boot_loader_read_mem32(pao, dsp,
14158c2ecf20Sopenharmony_ci						address);
14168c2ecf20Sopenharmony_ci				pcode++;
14178c2ecf20Sopenharmony_ci				address += 4;
14188c2ecf20Sopenharmony_ci			}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci		}
14218c2ecf20Sopenharmony_ci		if (err) {
14228c2ecf20Sopenharmony_ci			hpi_dsp_code_close(&dsp_code);
14238c2ecf20Sopenharmony_ci			return err;
14248c2ecf20Sopenharmony_ci		}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci		/* verify code */
14278c2ecf20Sopenharmony_ci		hpi_dsp_code_rewind(&dsp_code);
14288c2ecf20Sopenharmony_ci		while (1) {
14298c2ecf20Sopenharmony_ci			u32 length = 0;
14308c2ecf20Sopenharmony_ci			u32 address = 0;
14318c2ecf20Sopenharmony_ci			u32 type = 0;
14328c2ecf20Sopenharmony_ci			u32 *pcode = NULL;
14338c2ecf20Sopenharmony_ci			u32 data = 0;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci			hpi_dsp_code_read_word(&dsp_code, &length);
14368c2ecf20Sopenharmony_ci			if (length == 0xFFFFFFFF)
14378c2ecf20Sopenharmony_ci				break;	/* end of code */
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci			hpi_dsp_code_read_word(&dsp_code, &address);
14408c2ecf20Sopenharmony_ci			hpi_dsp_code_read_word(&dsp_code, &type);
14418c2ecf20Sopenharmony_ci			hpi_dsp_code_read_block(length, &dsp_code, &pcode);
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci			for (i = 0; i < (int)length; i++) {
14448c2ecf20Sopenharmony_ci				data = boot_loader_read_mem32(pao, dsp,
14458c2ecf20Sopenharmony_ci					address);
14468c2ecf20Sopenharmony_ci				if (data != *pcode) {
14478c2ecf20Sopenharmony_ci					err = 0;
14488c2ecf20Sopenharmony_ci					break;
14498c2ecf20Sopenharmony_ci				}
14508c2ecf20Sopenharmony_ci				pcode++;
14518c2ecf20Sopenharmony_ci				address += 4;
14528c2ecf20Sopenharmony_ci			}
14538c2ecf20Sopenharmony_ci			if (err)
14548c2ecf20Sopenharmony_ci				break;
14558c2ecf20Sopenharmony_ci		}
14568c2ecf20Sopenharmony_ci		hpi_dsp_code_close(&dsp_code);
14578c2ecf20Sopenharmony_ci		if (err)
14588c2ecf20Sopenharmony_ci			return err;
14598c2ecf20Sopenharmony_ci	}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	/* After bootloading all DSPs, start DSP0 running
14628c2ecf20Sopenharmony_ci	 * The DSP0 code will handle starting and synchronizing with its slaves
14638c2ecf20Sopenharmony_ci	 */
14648c2ecf20Sopenharmony_ci	if (phw->p_interface_buffer) {
14658c2ecf20Sopenharmony_ci		/* we need to tell the card the physical PCI address */
14668c2ecf20Sopenharmony_ci		u32 physicalPC_iaddress;
14678c2ecf20Sopenharmony_ci		struct bus_master_interface *interface =
14688c2ecf20Sopenharmony_ci			phw->p_interface_buffer;
14698c2ecf20Sopenharmony_ci		u32 host_mailbox_address_on_dsp;
14708c2ecf20Sopenharmony_ci		u32 physicalPC_iaddress_verify = 0;
14718c2ecf20Sopenharmony_ci		int time_out = 10;
14728c2ecf20Sopenharmony_ci		/* set ack so we know when DSP is ready to go */
14738c2ecf20Sopenharmony_ci		/* (dwDspAck will be changed to HIF_RESET) */
14748c2ecf20Sopenharmony_ci		interface->dsp_ack = H620_HIF_UNKNOWN;
14758c2ecf20Sopenharmony_ci		wmb();	/* ensure ack is written before dsp writes back */
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci		err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,
14788c2ecf20Sopenharmony_ci			&physicalPC_iaddress);
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci		/* locate the host mailbox on the DSP. */
14818c2ecf20Sopenharmony_ci		host_mailbox_address_on_dsp = 0x80000000;
14828c2ecf20Sopenharmony_ci		while ((physicalPC_iaddress != physicalPC_iaddress_verify)
14838c2ecf20Sopenharmony_ci			&& time_out--) {
14848c2ecf20Sopenharmony_ci			boot_loader_write_mem32(pao, 0,
14858c2ecf20Sopenharmony_ci				host_mailbox_address_on_dsp,
14868c2ecf20Sopenharmony_ci				physicalPC_iaddress);
14878c2ecf20Sopenharmony_ci			physicalPC_iaddress_verify =
14888c2ecf20Sopenharmony_ci				boot_loader_read_mem32(pao, 0,
14898c2ecf20Sopenharmony_ci				host_mailbox_address_on_dsp);
14908c2ecf20Sopenharmony_ci		}
14918c2ecf20Sopenharmony_ci	}
14928c2ecf20Sopenharmony_ci	HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");
14938c2ecf20Sopenharmony_ci	/* enable interrupts */
14948c2ecf20Sopenharmony_ci	temp = ioread32(phw->prHSR);
14958c2ecf20Sopenharmony_ci	temp &= ~(u32)C6205_HSR_INTAM;
14968c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prHSR);
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	/* start code running... */
14998c2ecf20Sopenharmony_ci	temp = ioread32(phw->prHDCR);
15008c2ecf20Sopenharmony_ci	temp |= (u32)C6205_HDCR_DSPINT;
15018c2ecf20Sopenharmony_ci	iowrite32(temp, phw->prHDCR);
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	/* give the DSP 10ms to start up */
15048c2ecf20Sopenharmony_ci	hpios_delay_micro_seconds(10000);
15058c2ecf20Sopenharmony_ci	return err;
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci}
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci/*****************************************************************************/
15108c2ecf20Sopenharmony_ci/* Bootloader utility functions */
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_cistatic u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
15138c2ecf20Sopenharmony_ci	u32 address)
15148c2ecf20Sopenharmony_ci{
15158c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
15168c2ecf20Sopenharmony_ci	u32 data = 0;
15178c2ecf20Sopenharmony_ci	__iomem u32 *p_data;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
15208c2ecf20Sopenharmony_ci		/* DSP 0 is always C6205 */
15218c2ecf20Sopenharmony_ci		if ((address >= 0x01800000) & (address < 0x02000000)) {
15228c2ecf20Sopenharmony_ci			/* BAR1 register access */
15238c2ecf20Sopenharmony_ci			p_data = pao->pci.ap_mem_base[1] +
15248c2ecf20Sopenharmony_ci				(address & 0x007fffff) /
15258c2ecf20Sopenharmony_ci				sizeof(*pao->pci.ap_mem_base[1]);
15268c2ecf20Sopenharmony_ci			/* HPI_DEBUG_LOG(WARNING,
15278c2ecf20Sopenharmony_ci			   "BAR1 access %08x\n", dwAddress); */
15288c2ecf20Sopenharmony_ci		} else {
15298c2ecf20Sopenharmony_ci			u32 dw4M_page = address >> 22L;
15308c2ecf20Sopenharmony_ci			if (dw4M_page != phw->dsp_page) {
15318c2ecf20Sopenharmony_ci				phw->dsp_page = dw4M_page;
15328c2ecf20Sopenharmony_ci				/* *INDENT OFF* */
15338c2ecf20Sopenharmony_ci				iowrite32(phw->dsp_page, phw->prDSPP);
15348c2ecf20Sopenharmony_ci				/* *INDENT-ON* */
15358c2ecf20Sopenharmony_ci			}
15368c2ecf20Sopenharmony_ci			address &= 0x3fffff;	/* address within 4M page */
15378c2ecf20Sopenharmony_ci			/* BAR0 memory access */
15388c2ecf20Sopenharmony_ci			p_data = pao->pci.ap_mem_base[0] +
15398c2ecf20Sopenharmony_ci				address / sizeof(u32);
15408c2ecf20Sopenharmony_ci		}
15418c2ecf20Sopenharmony_ci		data = ioread32(p_data);
15428c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
15438c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
15448c2ecf20Sopenharmony_ci		u32 lsb;
15458c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
15468c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
15478c2ecf20Sopenharmony_ci		lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);
15488c2ecf20Sopenharmony_ci		data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);
15498c2ecf20Sopenharmony_ci		data = (data << 16) | (lsb & 0xFFFF);
15508c2ecf20Sopenharmony_ci	}
15518c2ecf20Sopenharmony_ci	return data;
15528c2ecf20Sopenharmony_ci}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_cistatic void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
15558c2ecf20Sopenharmony_ci	int dsp_index, u32 address, u32 data)
15568c2ecf20Sopenharmony_ci{
15578c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
15588c2ecf20Sopenharmony_ci	__iomem u32 *p_data;
15598c2ecf20Sopenharmony_ci	/*      u32 dwVerifyData=0; */
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
15628c2ecf20Sopenharmony_ci		/* DSP 0 is always C6205 */
15638c2ecf20Sopenharmony_ci		if ((address >= 0x01800000) & (address < 0x02000000)) {
15648c2ecf20Sopenharmony_ci			/* BAR1 - DSP  register access using */
15658c2ecf20Sopenharmony_ci			/* Non-prefetchable PCI access */
15668c2ecf20Sopenharmony_ci			p_data = pao->pci.ap_mem_base[1] +
15678c2ecf20Sopenharmony_ci				(address & 0x007fffff) /
15688c2ecf20Sopenharmony_ci				sizeof(*pao->pci.ap_mem_base[1]);
15698c2ecf20Sopenharmony_ci		} else {
15708c2ecf20Sopenharmony_ci			/* BAR0 access - all of DSP memory using */
15718c2ecf20Sopenharmony_ci			/* pre-fetchable PCI access */
15728c2ecf20Sopenharmony_ci			u32 dw4M_page = address >> 22L;
15738c2ecf20Sopenharmony_ci			if (dw4M_page != phw->dsp_page) {
15748c2ecf20Sopenharmony_ci				phw->dsp_page = dw4M_page;
15758c2ecf20Sopenharmony_ci				/* *INDENT-OFF* */
15768c2ecf20Sopenharmony_ci				iowrite32(phw->dsp_page, phw->prDSPP);
15778c2ecf20Sopenharmony_ci				/* *INDENT-ON* */
15788c2ecf20Sopenharmony_ci			}
15798c2ecf20Sopenharmony_ci			address &= 0x3fffff;	/* address within 4M page */
15808c2ecf20Sopenharmony_ci			p_data = pao->pci.ap_mem_base[0] +
15818c2ecf20Sopenharmony_ci				address / sizeof(u32);
15828c2ecf20Sopenharmony_ci		}
15838c2ecf20Sopenharmony_ci		iowrite32(data, p_data);
15848c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
15858c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
15868c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
15878c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci		/* dummy read every 4 words for 6205 advisory 1.4.4 */
15908c2ecf20Sopenharmony_ci		boot_loader_read_mem32(pao, 0, 0);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);
15938c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci		/* dummy read every 4 words for 6205 advisory 1.4.4 */
15968c2ecf20Sopenharmony_ci		boot_loader_read_mem32(pao, 0, 0);
15978c2ecf20Sopenharmony_ci	}
15988c2ecf20Sopenharmony_ci}
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_cistatic u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
16018c2ecf20Sopenharmony_ci{
16028c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
16038c2ecf20Sopenharmony_ci		u32 setting;
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci		/* DSP 0 is always C6205 */
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci		/* Set the EMIF */
16088c2ecf20Sopenharmony_ci		/* memory map of C6205 */
16098c2ecf20Sopenharmony_ci		/* 00000000-0000FFFF    16Kx32 internal program */
16108c2ecf20Sopenharmony_ci		/* 00400000-00BFFFFF    CE0     2Mx32 SDRAM running @ 100MHz */
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci		/* EMIF config */
16138c2ecf20Sopenharmony_ci		/*------------ */
16148c2ecf20Sopenharmony_ci		/* Global EMIF control */
16158c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);
16168c2ecf20Sopenharmony_ci#define WS_OFS 28
16178c2ecf20Sopenharmony_ci#define WST_OFS 22
16188c2ecf20Sopenharmony_ci#define WH_OFS 20
16198c2ecf20Sopenharmony_ci#define RS_OFS 16
16208c2ecf20Sopenharmony_ci#define RST_OFS 8
16218c2ecf20Sopenharmony_ci#define MTYPE_OFS 4
16228c2ecf20Sopenharmony_ci#define RH_OFS 0
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci		/* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */
16258c2ecf20Sopenharmony_ci		setting = 0x00000030;
16268c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
16278c2ecf20Sopenharmony_ci		if (setting != boot_loader_read_mem32(pao, dsp_index,
16288c2ecf20Sopenharmony_ci				0x01800008))
16298c2ecf20Sopenharmony_ci			return HPI6205_ERROR_DSP_EMIF1;
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci		/* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
16328c2ecf20Sopenharmony_ci		/* which occupies D15..0. 6713 starts at 27MHz, so need */
16338c2ecf20Sopenharmony_ci		/* plenty of wait states. See dsn8701.rtf, and 6713 errata. */
16348c2ecf20Sopenharmony_ci		/* WST should be 71, but 63  is max possible */
16358c2ecf20Sopenharmony_ci		setting =
16368c2ecf20Sopenharmony_ci			(1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |
16378c2ecf20Sopenharmony_ci			(1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
16388c2ecf20Sopenharmony_ci			(2L << MTYPE_OFS);
16398c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
16408c2ecf20Sopenharmony_ci		if (setting != boot_loader_read_mem32(pao, dsp_index,
16418c2ecf20Sopenharmony_ci				0x01800004))
16428c2ecf20Sopenharmony_ci			return HPI6205_ERROR_DSP_EMIF2;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci		/* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
16458c2ecf20Sopenharmony_ci		/* which occupies D15..0. 6713 starts at 27MHz, so need */
16468c2ecf20Sopenharmony_ci		/* plenty of wait states */
16478c2ecf20Sopenharmony_ci		setting =
16488c2ecf20Sopenharmony_ci			(1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |
16498c2ecf20Sopenharmony_ci			(1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
16508c2ecf20Sopenharmony_ci			(2L << MTYPE_OFS);
16518c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
16528c2ecf20Sopenharmony_ci		if (setting != boot_loader_read_mem32(pao, dsp_index,
16538c2ecf20Sopenharmony_ci				0x01800010))
16548c2ecf20Sopenharmony_ci			return HPI6205_ERROR_DSP_EMIF3;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci		/* EMIF CE3 setup - 32 bit async. */
16578c2ecf20Sopenharmony_ci		/* This is the PLD on the ASI5000 cards only */
16588c2ecf20Sopenharmony_ci		setting =
16598c2ecf20Sopenharmony_ci			(1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |
16608c2ecf20Sopenharmony_ci			(1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |
16618c2ecf20Sopenharmony_ci			(2L << MTYPE_OFS);
16628c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
16638c2ecf20Sopenharmony_ci		if (setting != boot_loader_read_mem32(pao, dsp_index,
16648c2ecf20Sopenharmony_ci				0x01800014))
16658c2ecf20Sopenharmony_ci			return HPI6205_ERROR_DSP_EMIF4;
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci		/* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
16688c2ecf20Sopenharmony_ci		/*  need to use this else DSP code crashes? */
16698c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01800018,
16708c2ecf20Sopenharmony_ci			0x07117000);
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci		/* EMIF SDRAM Refresh Timing */
16738c2ecf20Sopenharmony_ci		/* EMIF SDRAM timing  (orig = 0x410, emulator = 0x61a) */
16748c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x0180001C,
16758c2ecf20Sopenharmony_ci			0x00000410);
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
16788c2ecf20Sopenharmony_ci		/* test access to the C6713s HPI registers */
16798c2ecf20Sopenharmony_ci		u32 write_data = 0, read_data = 0, i = 0;
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci		/* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */
16828c2ecf20Sopenharmony_ci		write_data = 1;
16838c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);
16848c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);
16858c2ecf20Sopenharmony_ci		/* C67 HPI is on lower 16bits of 32bit EMIF */
16868c2ecf20Sopenharmony_ci		read_data =
16878c2ecf20Sopenharmony_ci			0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
16888c2ecf20Sopenharmony_ci		if (write_data != read_data) {
16898c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
16908c2ecf20Sopenharmony_ci				read_data);
16918c2ecf20Sopenharmony_ci			return HPI6205_ERROR_C6713_HPIC;
16928c2ecf20Sopenharmony_ci		}
16938c2ecf20Sopenharmony_ci		/* HPIA - walking ones test */
16948c2ecf20Sopenharmony_ci		write_data = 1;
16958c2ecf20Sopenharmony_ci		for (i = 0; i < 32; i++) {
16968c2ecf20Sopenharmony_ci			boot_loader_write_mem32(pao, 0, HPIAL_ADDR,
16978c2ecf20Sopenharmony_ci				write_data);
16988c2ecf20Sopenharmony_ci			boot_loader_write_mem32(pao, 0, HPIAH_ADDR,
16998c2ecf20Sopenharmony_ci				(write_data >> 16));
17008c2ecf20Sopenharmony_ci			read_data =
17018c2ecf20Sopenharmony_ci				0xFFFF & boot_loader_read_mem32(pao, 0,
17028c2ecf20Sopenharmony_ci				HPIAL_ADDR);
17038c2ecf20Sopenharmony_ci			read_data =
17048c2ecf20Sopenharmony_ci				read_data | ((0xFFFF &
17058c2ecf20Sopenharmony_ci					boot_loader_read_mem32(pao, 0,
17068c2ecf20Sopenharmony_ci						HPIAH_ADDR))
17078c2ecf20Sopenharmony_ci				<< 16);
17088c2ecf20Sopenharmony_ci			if (read_data != write_data) {
17098c2ecf20Sopenharmony_ci				HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
17108c2ecf20Sopenharmony_ci					write_data, read_data);
17118c2ecf20Sopenharmony_ci				return HPI6205_ERROR_C6713_HPIA;
17128c2ecf20Sopenharmony_ci			}
17138c2ecf20Sopenharmony_ci			write_data = write_data << 1;
17148c2ecf20Sopenharmony_ci		}
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci		/* setup C67x PLL
17178c2ecf20Sopenharmony_ci		 *  ** C6713 datasheet says we cannot program PLL from HPI,
17188c2ecf20Sopenharmony_ci		 * and indeed if we try to set the PLL multiply from the HPI,
17198c2ecf20Sopenharmony_ci		 * the PLL does not seem to lock, so we enable the PLL and
17208c2ecf20Sopenharmony_ci		 * use the default multiply of x 7, which for a 27MHz clock
17218c2ecf20Sopenharmony_ci		 * gives a DSP speed of 189MHz
17228c2ecf20Sopenharmony_ci		 */
17238c2ecf20Sopenharmony_ci		/* bypass PLL */
17248c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);
17258c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(1000);
17268c2ecf20Sopenharmony_ci		/* EMIF = 189/3=63MHz */
17278c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);
17288c2ecf20Sopenharmony_ci		/* peri = 189/2 */
17298c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);
17308c2ecf20Sopenharmony_ci		/* cpu  = 189/1 */
17318c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);
17328c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(1000);
17338c2ecf20Sopenharmony_ci		/* ** SGT test to take GPO3 high when we start the PLL */
17348c2ecf20Sopenharmony_ci		/* and low when the delay is completed */
17358c2ecf20Sopenharmony_ci		/* FSX0 <- '1' (GPO3) */
17368c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);
17378c2ecf20Sopenharmony_ci		/* PLL not bypassed */
17388c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);
17398c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(1000);
17408c2ecf20Sopenharmony_ci		/* FSX0 <- '0' (GPO3) */
17418c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci		/* 6205 EMIF CE1 resetup - 32 bit async. */
17448c2ecf20Sopenharmony_ci		/* Now 6713 #1 is running at 189MHz can reduce waitstates */
17458c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, 0, 0x01800004,	/* CE1 */
17468c2ecf20Sopenharmony_ci			(1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |
17478c2ecf20Sopenharmony_ci			(1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |
17488c2ecf20Sopenharmony_ci			(2L << MTYPE_OFS));
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(1000);
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci		/* check that we can read one of the PLL registers */
17538c2ecf20Sopenharmony_ci		/* PLL should not be bypassed! */
17548c2ecf20Sopenharmony_ci		if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
17558c2ecf20Sopenharmony_ci			!= 0x0001) {
17568c2ecf20Sopenharmony_ci			return HPI6205_ERROR_C6713_PLL;
17578c2ecf20Sopenharmony_ci		}
17588c2ecf20Sopenharmony_ci		/* setup C67x EMIF  (note this is the only use of
17598c2ecf20Sopenharmony_ci		   BAR1 via BootLoader_WriteMem32) */
17608c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
17618c2ecf20Sopenharmony_ci			0x000034A8);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci		/* EMIF CE0 setup - 2Mx32 Sync DRAM
17648c2ecf20Sopenharmony_ci		   31..28       Wr setup
17658c2ecf20Sopenharmony_ci		   27..22       Wr strobe
17668c2ecf20Sopenharmony_ci		   21..20       Wr hold
17678c2ecf20Sopenharmony_ci		   19..16       Rd setup
17688c2ecf20Sopenharmony_ci		   15..14       -
17698c2ecf20Sopenharmony_ci		   13..8        Rd strobe
17708c2ecf20Sopenharmony_ci		   7..4         MTYPE   0011            Sync DRAM 32bits
17718c2ecf20Sopenharmony_ci		   3            Wr hold MSB
17728c2ecf20Sopenharmony_ci		   2..0         Rd hold
17738c2ecf20Sopenharmony_ci		 */
17748c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
17758c2ecf20Sopenharmony_ci			0x00000030);
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci		/* EMIF SDRAM Extension
17788c2ecf20Sopenharmony_ci		   0x00
17798c2ecf20Sopenharmony_ci		   31-21        0000b 0000b 000b
17808c2ecf20Sopenharmony_ci		   20           WR2RD = 2cycles-1  = 1b
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci		   19-18        WR2DEAC = 3cycle-1 = 10b
17838c2ecf20Sopenharmony_ci		   17           WR2WR = 2cycle-1   = 1b
17848c2ecf20Sopenharmony_ci		   16-15        R2WDQM = 4cycle-1  = 11b
17858c2ecf20Sopenharmony_ci		   14-12        RD2WR = 6cycles-1  = 101b
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci		   11-10        RD2DEAC = 4cycle-1 = 11b
17888c2ecf20Sopenharmony_ci		   9            RD2RD = 2cycle-1   = 1b
17898c2ecf20Sopenharmony_ci		   8-7          THZP = 3cycle-1    = 10b
17908c2ecf20Sopenharmony_ci		   6-5          TWR  = 2cycle-1    = 01b (tWR = 17ns)
17918c2ecf20Sopenharmony_ci		   4            TRRD = 2cycle      = 0b  (tRRD = 14ns)
17928c2ecf20Sopenharmony_ci		   3-1          TRAS = 5cycle-1    = 100b (Tras=42ns)
17938c2ecf20Sopenharmony_ci		   1            CAS latency = 3cyc = 1b
17948c2ecf20Sopenharmony_ci		   (for Micron 2M32-7 operating at 100MHz)
17958c2ecf20Sopenharmony_ci		 */
17968c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
17978c2ecf20Sopenharmony_ci			0x001BDF29);
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci		/* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
18008c2ecf20Sopenharmony_ci		   31           -       0b       -
18018c2ecf20Sopenharmony_ci		   30           SDBSZ   1b              4 bank
18028c2ecf20Sopenharmony_ci		   29..28       SDRSZ   00b             11 row address pins
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci		   27..26       SDCSZ   01b             8 column address pins
18058c2ecf20Sopenharmony_ci		   25           RFEN    1b              refersh enabled
18068c2ecf20Sopenharmony_ci		   24           INIT    1b              init SDRAM!
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci		   23..20       TRCD    0001b                   (Trcd/Tcyc)-1 = (20/10)-1 = 1
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci		   19..16       TRP     0001b                   (Trp/Tcyc)-1 = (20/10)-1 = 1
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci		   15..12       TRC     0110b                   (Trc/Tcyc)-1 = (70/10)-1 = 6
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci		   11..0        -       0000b 0000b 0000b
18158c2ecf20Sopenharmony_ci		 */
18168c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
18178c2ecf20Sopenharmony_ci			0x47116000);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci		/* SDRAM refresh timing
18208c2ecf20Sopenharmony_ci		   Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A
18218c2ecf20Sopenharmony_ci		 */
18228c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index,
18238c2ecf20Sopenharmony_ci			C6713_EMIF_SDRAMTIMING, 0x00000410);
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(1000);
18268c2ecf20Sopenharmony_ci	} else if (dsp_index == 2) {
18278c2ecf20Sopenharmony_ci		/* DSP 2 is a C6713 */
18288c2ecf20Sopenharmony_ci	}
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	return 0;
18318c2ecf20Sopenharmony_ci}
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_cistatic u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
18348c2ecf20Sopenharmony_ci	u32 start_address, u32 length)
18358c2ecf20Sopenharmony_ci{
18368c2ecf20Sopenharmony_ci	u32 i = 0, j = 0;
18378c2ecf20Sopenharmony_ci	u32 test_addr = 0;
18388c2ecf20Sopenharmony_ci	u32 test_data = 0, data = 0;
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	length = 1000;
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci	/* for 1st word, test each bit in the 32bit word, */
18438c2ecf20Sopenharmony_ci	/* dwLength specifies number of 32bit words to test */
18448c2ecf20Sopenharmony_ci	/*for(i=0; i<dwLength; i++) */
18458c2ecf20Sopenharmony_ci	i = 0;
18468c2ecf20Sopenharmony_ci	{
18478c2ecf20Sopenharmony_ci		test_addr = start_address + i * 4;
18488c2ecf20Sopenharmony_ci		test_data = 0x00000001;
18498c2ecf20Sopenharmony_ci		for (j = 0; j < 32; j++) {
18508c2ecf20Sopenharmony_ci			boot_loader_write_mem32(pao, dsp_index, test_addr,
18518c2ecf20Sopenharmony_ci				test_data);
18528c2ecf20Sopenharmony_ci			data = boot_loader_read_mem32(pao, dsp_index,
18538c2ecf20Sopenharmony_ci				test_addr);
18548c2ecf20Sopenharmony_ci			if (data != test_data) {
18558c2ecf20Sopenharmony_ci				HPI_DEBUG_LOG(VERBOSE,
18568c2ecf20Sopenharmony_ci					"Memtest error details  "
18578c2ecf20Sopenharmony_ci					"%08x %08x %08x %i\n", test_addr,
18588c2ecf20Sopenharmony_ci					test_data, data, dsp_index);
18598c2ecf20Sopenharmony_ci				return 1;	/* error */
18608c2ecf20Sopenharmony_ci			}
18618c2ecf20Sopenharmony_ci			test_data = test_data << 1;
18628c2ecf20Sopenharmony_ci		}	/* for(j) */
18638c2ecf20Sopenharmony_ci	}	/* for(i) */
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	/* for the next 100 locations test each location, leaving it as zero */
18668c2ecf20Sopenharmony_ci	/* write a zero to the next word in memory before we read */
18678c2ecf20Sopenharmony_ci	/* the previous write to make sure every memory location is unique */
18688c2ecf20Sopenharmony_ci	for (i = 0; i < 100; i++) {
18698c2ecf20Sopenharmony_ci		test_addr = start_address + i * 4;
18708c2ecf20Sopenharmony_ci		test_data = 0xA5A55A5A;
18718c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);
18728c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);
18738c2ecf20Sopenharmony_ci		data = boot_loader_read_mem32(pao, dsp_index, test_addr);
18748c2ecf20Sopenharmony_ci		if (data != test_data) {
18758c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(VERBOSE,
18768c2ecf20Sopenharmony_ci				"Memtest error details  "
18778c2ecf20Sopenharmony_ci				"%08x %08x %08x %i\n", test_addr, test_data,
18788c2ecf20Sopenharmony_ci				data, dsp_index);
18798c2ecf20Sopenharmony_ci			return 1;	/* error */
18808c2ecf20Sopenharmony_ci		}
18818c2ecf20Sopenharmony_ci		/* leave location as zero */
18828c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
18838c2ecf20Sopenharmony_ci	}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci	/* zero out entire memory block */
18868c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++) {
18878c2ecf20Sopenharmony_ci		test_addr = start_address + i * 4;
18888c2ecf20Sopenharmony_ci		boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
18898c2ecf20Sopenharmony_ci	}
18908c2ecf20Sopenharmony_ci	return 0;
18918c2ecf20Sopenharmony_ci}
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_cistatic u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
18948c2ecf20Sopenharmony_ci	int dsp_index)
18958c2ecf20Sopenharmony_ci{
18968c2ecf20Sopenharmony_ci	int err = 0;
18978c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
18988c2ecf20Sopenharmony_ci		/* DSP 0 is a C6205 */
18998c2ecf20Sopenharmony_ci		/* 64K prog mem */
19008c2ecf20Sopenharmony_ci		err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
19018c2ecf20Sopenharmony_ci			0x10000);
19028c2ecf20Sopenharmony_ci		if (!err)
19038c2ecf20Sopenharmony_ci			/* 64K data mem */
19048c2ecf20Sopenharmony_ci			err = boot_loader_test_memory(pao, dsp_index,
19058c2ecf20Sopenharmony_ci				0x80000000, 0x10000);
19068c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
19078c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
19088c2ecf20Sopenharmony_ci		/* 192K internal mem */
19098c2ecf20Sopenharmony_ci		err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
19108c2ecf20Sopenharmony_ci			0x30000);
19118c2ecf20Sopenharmony_ci		if (!err)
19128c2ecf20Sopenharmony_ci			/* 64K internal mem / L2 cache */
19138c2ecf20Sopenharmony_ci			err = boot_loader_test_memory(pao, dsp_index,
19148c2ecf20Sopenharmony_ci				0x00030000, 0x10000);
19158c2ecf20Sopenharmony_ci	}
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci	if (err)
19188c2ecf20Sopenharmony_ci		return HPI6205_ERROR_DSP_INTMEM;
19198c2ecf20Sopenharmony_ci	else
19208c2ecf20Sopenharmony_ci		return 0;
19218c2ecf20Sopenharmony_ci}
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_cistatic u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
19248c2ecf20Sopenharmony_ci	int dsp_index)
19258c2ecf20Sopenharmony_ci{
19268c2ecf20Sopenharmony_ci	u32 dRAM_start_address = 0;
19278c2ecf20Sopenharmony_ci	u32 dRAM_size = 0;
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
19308c2ecf20Sopenharmony_ci		/* only test for SDRAM if an ASI5000 card */
19318c2ecf20Sopenharmony_ci		if (pao->pci.pci_dev->subsystem_device == 0x5000) {
19328c2ecf20Sopenharmony_ci			/* DSP 0 is always C6205 */
19338c2ecf20Sopenharmony_ci			dRAM_start_address = 0x00400000;
19348c2ecf20Sopenharmony_ci			dRAM_size = 0x200000;
19358c2ecf20Sopenharmony_ci			/*dwDRAMinc=1024; */
19368c2ecf20Sopenharmony_ci		} else
19378c2ecf20Sopenharmony_ci			return 0;
19388c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
19398c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
19408c2ecf20Sopenharmony_ci		dRAM_start_address = 0x80000000;
19418c2ecf20Sopenharmony_ci		dRAM_size = 0x200000;
19428c2ecf20Sopenharmony_ci		/*dwDRAMinc=1024; */
19438c2ecf20Sopenharmony_ci	}
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
19468c2ecf20Sopenharmony_ci			dRAM_size))
19478c2ecf20Sopenharmony_ci		return HPI6205_ERROR_DSP_EXTMEM;
19488c2ecf20Sopenharmony_ci	return 0;
19498c2ecf20Sopenharmony_ci}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_cistatic u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
19528c2ecf20Sopenharmony_ci{
19538c2ecf20Sopenharmony_ci	u32 data = 0;
19548c2ecf20Sopenharmony_ci	if (dsp_index == 0) {
19558c2ecf20Sopenharmony_ci		/* only test for DSP0 PLD on ASI5000 card */
19568c2ecf20Sopenharmony_ci		if (pao->pci.pci_dev->subsystem_device == 0x5000) {
19578c2ecf20Sopenharmony_ci			/* PLD is located at CE3=0x03000000 */
19588c2ecf20Sopenharmony_ci			data = boot_loader_read_mem32(pao, dsp_index,
19598c2ecf20Sopenharmony_ci				0x03000008);
19608c2ecf20Sopenharmony_ci			if ((data & 0xF) != 0x5)
19618c2ecf20Sopenharmony_ci				return HPI6205_ERROR_DSP_PLD;
19628c2ecf20Sopenharmony_ci			data = boot_loader_read_mem32(pao, dsp_index,
19638c2ecf20Sopenharmony_ci				0x0300000C);
19648c2ecf20Sopenharmony_ci			if ((data & 0xF) != 0xA)
19658c2ecf20Sopenharmony_ci				return HPI6205_ERROR_DSP_PLD;
19668c2ecf20Sopenharmony_ci		}
19678c2ecf20Sopenharmony_ci	} else if (dsp_index == 1) {
19688c2ecf20Sopenharmony_ci		/* DSP 1 is a C6713 */
19698c2ecf20Sopenharmony_ci		if (pao->pci.pci_dev->subsystem_device == 0x8700) {
19708c2ecf20Sopenharmony_ci			/* PLD is located at CE1=0x90000000 */
19718c2ecf20Sopenharmony_ci			data = boot_loader_read_mem32(pao, dsp_index,
19728c2ecf20Sopenharmony_ci				0x90000010);
19738c2ecf20Sopenharmony_ci			if ((data & 0xFF) != 0xAA)
19748c2ecf20Sopenharmony_ci				return HPI6205_ERROR_DSP_PLD;
19758c2ecf20Sopenharmony_ci			/* 8713 - LED on */
19768c2ecf20Sopenharmony_ci			boot_loader_write_mem32(pao, dsp_index, 0x90000000,
19778c2ecf20Sopenharmony_ci				0x02);
19788c2ecf20Sopenharmony_ci		}
19798c2ecf20Sopenharmony_ci	}
19808c2ecf20Sopenharmony_ci	return 0;
19818c2ecf20Sopenharmony_ci}
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci/** Transfer data to or from DSP
19848c2ecf20Sopenharmony_ci nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA
19858c2ecf20Sopenharmony_ci*/
19868c2ecf20Sopenharmony_cistatic short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
19878c2ecf20Sopenharmony_ci	u32 data_size, int operation)
19888c2ecf20Sopenharmony_ci{
19898c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
19908c2ecf20Sopenharmony_ci	u32 data_transferred = 0;
19918c2ecf20Sopenharmony_ci	u16 err = 0;
19928c2ecf20Sopenharmony_ci	u32 temp2;
19938c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	if (!p_data)
19968c2ecf20Sopenharmony_ci		return HPI_ERROR_INVALID_DATA_POINTER;
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	data_size &= ~3L;	/* round data_size down to nearest 4 bytes */
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	/* make sure state is IDLE */
20018c2ecf20Sopenharmony_ci	if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))
20028c2ecf20Sopenharmony_ci		return HPI_ERROR_DSP_HARDWARE;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	while (data_transferred < data_size) {
20058c2ecf20Sopenharmony_ci		u32 this_copy = data_size - data_transferred;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci		if (this_copy > HPI6205_SIZEOF_DATA)
20088c2ecf20Sopenharmony_ci			this_copy = HPI6205_SIZEOF_DATA;
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci		if (operation == H620_HIF_SEND_DATA)
20118c2ecf20Sopenharmony_ci			memcpy((void *)&interface->u.b_data[0],
20128c2ecf20Sopenharmony_ci				&p_data[data_transferred], this_copy);
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci		interface->transfer_size_in_bytes = this_copy;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci		/* DSP must change this back to nOperation */
20178c2ecf20Sopenharmony_ci		interface->dsp_ack = H620_HIF_IDLE;
20188c2ecf20Sopenharmony_ci		send_dsp_command(phw, operation);
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci		temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
20218c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
20228c2ecf20Sopenharmony_ci			HPI6205_TIMEOUT - temp2, this_copy);
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci		if (!temp2) {
20258c2ecf20Sopenharmony_ci			/* timed out */
20268c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR,
20278c2ecf20Sopenharmony_ci				"Timed out waiting for " "state %d got %d\n",
20288c2ecf20Sopenharmony_ci				operation, interface->dsp_ack);
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci			break;
20318c2ecf20Sopenharmony_ci		}
20328c2ecf20Sopenharmony_ci		if (operation == H620_HIF_GET_DATA)
20338c2ecf20Sopenharmony_ci			memcpy(&p_data[data_transferred],
20348c2ecf20Sopenharmony_ci				(void *)&interface->u.b_data[0], this_copy);
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci		data_transferred += this_copy;
20378c2ecf20Sopenharmony_ci	}
20388c2ecf20Sopenharmony_ci	if (interface->dsp_ack != operation)
20398c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",
20408c2ecf20Sopenharmony_ci			interface->dsp_ack, operation);
20418c2ecf20Sopenharmony_ci	/*                      err=HPI_ERROR_DSP_HARDWARE; */
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	send_dsp_command(phw, H620_HIF_IDLE);
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_ci	return err;
20468c2ecf20Sopenharmony_ci}
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci/* wait for up to timeout_us microseconds for the DSP
20498c2ecf20Sopenharmony_ci   to signal state by DMA into dwDspAck
20508c2ecf20Sopenharmony_ci*/
20518c2ecf20Sopenharmony_cistatic int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
20528c2ecf20Sopenharmony_ci{
20538c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
20548c2ecf20Sopenharmony_ci	int t = timeout_us / 4;
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	rmb();	/* ensure interface->dsp_ack is up to date */
20578c2ecf20Sopenharmony_ci	while ((interface->dsp_ack != state) && --t) {
20588c2ecf20Sopenharmony_ci		hpios_delay_micro_seconds(4);
20598c2ecf20Sopenharmony_ci		rmb();	/* DSP changes dsp_ack by DMA */
20608c2ecf20Sopenharmony_ci	}
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	/*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */
20638c2ecf20Sopenharmony_ci	return t * 4;
20648c2ecf20Sopenharmony_ci}
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci/* set the busmaster interface to cmd, then interrupt the DSP */
20678c2ecf20Sopenharmony_cistatic void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
20688c2ecf20Sopenharmony_ci{
20698c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
20708c2ecf20Sopenharmony_ci	u32 r;
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	interface->host_cmd = cmd;
20738c2ecf20Sopenharmony_ci	wmb();	/* DSP gets state by DMA, make sure it is written to memory */
20748c2ecf20Sopenharmony_ci	/* before we interrupt the DSP */
20758c2ecf20Sopenharmony_ci	r = ioread32(phw->prHDCR);
20768c2ecf20Sopenharmony_ci	r |= (u32)C6205_HDCR_DSPINT;
20778c2ecf20Sopenharmony_ci	iowrite32(r, phw->prHDCR);
20788c2ecf20Sopenharmony_ci	r &= ~(u32)C6205_HDCR_DSPINT;
20798c2ecf20Sopenharmony_ci	iowrite32(r, phw->prHDCR);
20808c2ecf20Sopenharmony_ci}
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_cistatic unsigned int message_count;
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_cistatic u16 message_response_sequence(struct hpi_adapter_obj *pao,
20858c2ecf20Sopenharmony_ci	struct hpi_message *phm, struct hpi_response *phr)
20868c2ecf20Sopenharmony_ci{
20878c2ecf20Sopenharmony_ci	u32 time_out, time_out2;
20888c2ecf20Sopenharmony_ci	struct hpi_hw_obj *phw = pao->priv;
20898c2ecf20Sopenharmony_ci	struct bus_master_interface *interface = phw->p_interface_buffer;
20908c2ecf20Sopenharmony_ci	u16 err = 0;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	message_count++;
20938c2ecf20Sopenharmony_ci	if (phm->size > sizeof(interface->u.message_buffer)) {
20948c2ecf20Sopenharmony_ci		phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;
20958c2ecf20Sopenharmony_ci		phr->specific_error = sizeof(interface->u.message_buffer);
20968c2ecf20Sopenharmony_ci		phr->size = sizeof(struct hpi_response_header);
20978c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR,
20988c2ecf20Sopenharmony_ci			"message len %d too big for buffer %zd \n", phm->size,
20998c2ecf20Sopenharmony_ci			sizeof(interface->u.message_buffer));
21008c2ecf20Sopenharmony_ci		return 0;
21018c2ecf20Sopenharmony_ci	}
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_ci	/* Assume buffer of type struct bus_master_interface_62
21048c2ecf20Sopenharmony_ci	   is allocated "noncacheable" */
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
21078c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
21088c2ecf20Sopenharmony_ci		return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
21098c2ecf20Sopenharmony_ci	}
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	memcpy(&interface->u.message_buffer, phm, phm->size);
21128c2ecf20Sopenharmony_ci	/* signal we want a response */
21138c2ecf20Sopenharmony_ci	send_dsp_command(phw, H620_HIF_GET_RESP);
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci	if (!time_out2) {
21188c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(ERROR,
21198c2ecf20Sopenharmony_ci			"(%u) Timed out waiting for " "GET_RESP state [%x]\n",
21208c2ecf20Sopenharmony_ci			message_count, interface->dsp_ack);
21218c2ecf20Sopenharmony_ci	} else {
21228c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(VERBOSE,
21238c2ecf20Sopenharmony_ci			"(%u) transition to GET_RESP after %u\n",
21248c2ecf20Sopenharmony_ci			message_count, HPI6205_TIMEOUT - time_out2);
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci	/* spin waiting on HIF interrupt flag (end of msg process) */
21278c2ecf20Sopenharmony_ci	time_out = HPI6205_TIMEOUT;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	/* read the result */
21308c2ecf20Sopenharmony_ci	if (time_out) {
21318c2ecf20Sopenharmony_ci		if (interface->u.response_buffer.response.size <= phr->size)
21328c2ecf20Sopenharmony_ci			memcpy(phr, &interface->u.response_buffer,
21338c2ecf20Sopenharmony_ci				interface->u.response_buffer.response.size);
21348c2ecf20Sopenharmony_ci		else {
21358c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(ERROR,
21368c2ecf20Sopenharmony_ci				"response len %d too big for buffer %d\n",
21378c2ecf20Sopenharmony_ci				interface->u.response_buffer.response.size,
21388c2ecf20Sopenharmony_ci				phr->size);
21398c2ecf20Sopenharmony_ci			memcpy(phr, &interface->u.response_buffer,
21408c2ecf20Sopenharmony_ci				sizeof(struct hpi_response_header));
21418c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
21428c2ecf20Sopenharmony_ci			phr->specific_error =
21438c2ecf20Sopenharmony_ci				interface->u.response_buffer.response.size;
21448c2ecf20Sopenharmony_ci			phr->size = sizeof(struct hpi_response_header);
21458c2ecf20Sopenharmony_ci		}
21468c2ecf20Sopenharmony_ci	}
21478c2ecf20Sopenharmony_ci	/* set interface back to idle */
21488c2ecf20Sopenharmony_ci	send_dsp_command(phw, H620_HIF_IDLE);
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	if (!time_out || !time_out2) {
21518c2ecf20Sopenharmony_ci		HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
21528c2ecf20Sopenharmony_ci		return HPI6205_ERROR_MSG_RESP_TIMEOUT;
21538c2ecf20Sopenharmony_ci	}
21548c2ecf20Sopenharmony_ci	/* special case for adapter close - */
21558c2ecf20Sopenharmony_ci	/* wait for the DSP to indicate it is idle */
21568c2ecf20Sopenharmony_ci	if (phm->function == HPI_ADAPTER_CLOSE) {
21578c2ecf20Sopenharmony_ci		if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
21588c2ecf20Sopenharmony_ci			HPI_DEBUG_LOG(DEBUG,
21598c2ecf20Sopenharmony_ci				"Timeout waiting for idle "
21608c2ecf20Sopenharmony_ci				"(on adapter_close)\n");
21618c2ecf20Sopenharmony_ci			return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
21628c2ecf20Sopenharmony_ci		}
21638c2ecf20Sopenharmony_ci	}
21648c2ecf20Sopenharmony_ci	err = hpi_validate_response(phm, phr);
21658c2ecf20Sopenharmony_ci	return err;
21668c2ecf20Sopenharmony_ci}
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_cistatic void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
21698c2ecf20Sopenharmony_ci	struct hpi_response *phr)
21708c2ecf20Sopenharmony_ci{
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci	u16 err = 0;
21738c2ecf20Sopenharmony_ci
21748c2ecf20Sopenharmony_ci	hpios_dsplock_lock(pao);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	err = message_response_sequence(pao, phm, phr);
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci	/* maybe an error response */
21798c2ecf20Sopenharmony_ci	if (err) {
21808c2ecf20Sopenharmony_ci		/* something failed in the HPI/DSP interface */
21818c2ecf20Sopenharmony_ci		if (err >= HPI_ERROR_BACKEND_BASE) {
21828c2ecf20Sopenharmony_ci			phr->error = HPI_ERROR_DSP_COMMUNICATION;
21838c2ecf20Sopenharmony_ci			phr->specific_error = err;
21848c2ecf20Sopenharmony_ci		} else {
21858c2ecf20Sopenharmony_ci			phr->error = err;
21868c2ecf20Sopenharmony_ci		}
21878c2ecf20Sopenharmony_ci
21888c2ecf20Sopenharmony_ci		pao->dsp_crashed++;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci		/* just the header of the response is valid */
21918c2ecf20Sopenharmony_ci		phr->size = sizeof(struct hpi_response_header);
21928c2ecf20Sopenharmony_ci		goto err;
21938c2ecf20Sopenharmony_ci	} else
21948c2ecf20Sopenharmony_ci		pao->dsp_crashed = 0;
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	if (phr->error != 0)	/* something failed in the DSP */
21978c2ecf20Sopenharmony_ci		goto err;
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci	switch (phm->function) {
22008c2ecf20Sopenharmony_ci	case HPI_OSTREAM_WRITE:
22018c2ecf20Sopenharmony_ci	case HPI_ISTREAM_ANC_WRITE:
22028c2ecf20Sopenharmony_ci		err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
22038c2ecf20Sopenharmony_ci			phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);
22048c2ecf20Sopenharmony_ci		break;
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	case HPI_ISTREAM_READ:
22078c2ecf20Sopenharmony_ci	case HPI_OSTREAM_ANC_READ:
22088c2ecf20Sopenharmony_ci		err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
22098c2ecf20Sopenharmony_ci			phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
22108c2ecf20Sopenharmony_ci		break;
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	}
22138c2ecf20Sopenharmony_ci	phr->error = err;
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_cierr:
22168c2ecf20Sopenharmony_ci	hpios_dsplock_unlock(pao);
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_ci	return;
22198c2ecf20Sopenharmony_ci}
2220