brintos

brintos / linux-shallow public Read only

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