107d7fe7bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2719f82d3SEliot Blennerhassett /******************************************************************************
3719f82d3SEliot Blennerhassett
4719f82d3SEliot Blennerhassett AudioScience HPI driver
540818b62SEliot Blennerhassett Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
6719f82d3SEliot Blennerhassett
7719f82d3SEliot Blennerhassett
8719f82d3SEliot Blennerhassett Hardware Programming Interface (HPI) for AudioScience ASI6200 series adapters.
9719f82d3SEliot Blennerhassett These PCI bus adapters are based on the TI C6711 DSP.
10719f82d3SEliot Blennerhassett
11719f82d3SEliot Blennerhassett Exported functions:
12719f82d3SEliot Blennerhassett void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
13719f82d3SEliot Blennerhassett
14719f82d3SEliot Blennerhassett #defines
15719f82d3SEliot Blennerhassett HIDE_PCI_ASSERTS to show the PCI asserts
16719f82d3SEliot Blennerhassett PROFILE_DSP2 get profile data from DSP2 if present (instead of DSP 1)
17719f82d3SEliot Blennerhassett
18719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 1998-2003
19719f82d3SEliot Blennerhassett *******************************************************************************/
20719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpi6000.c"
21719f82d3SEliot Blennerhassett
22719f82d3SEliot Blennerhassett #include "hpi_internal.h"
23719f82d3SEliot Blennerhassett #include "hpimsginit.h"
24719f82d3SEliot Blennerhassett #include "hpidebug.h"
25719f82d3SEliot Blennerhassett #include "hpi6000.h"
26719f82d3SEliot Blennerhassett #include "hpidspcd.h"
27719f82d3SEliot Blennerhassett #include "hpicmn.h"
28719f82d3SEliot Blennerhassett
29719f82d3SEliot Blennerhassett #define HPI_HIF_BASE (0x00000200) /* start of C67xx internal RAM */
30719f82d3SEliot Blennerhassett #define HPI_HIF_ADDR(member) \
31719f82d3SEliot Blennerhassett (HPI_HIF_BASE + offsetof(struct hpi_hif_6000, member))
32719f82d3SEliot Blennerhassett #define HPI_HIF_ERROR_MASK 0x4000
33719f82d3SEliot Blennerhassett
34719f82d3SEliot Blennerhassett /* HPI6000 specific error codes */
353285ea10SEliot Blennerhassett #define HPI6000_ERROR_BASE 900 /* not actually used anywhere */
361528fbb5SEliot Blennerhassett
373285ea10SEliot Blennerhassett /* operational/messaging errors */
38719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901
390d02e129SEliot Blennerhassett #define HPI6000_ERROR_RESP_GET_LEN 902
40719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903
41719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_GET_ADR 904
42719f82d3SEliot Blennerhassett #define HPI6000_ERROR_RESP_GET_ADR 905
43719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906
44719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907
453285ea10SEliot Blennerhassett
46719f82d3SEliot Blennerhassett #define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909
47719f82d3SEliot Blennerhassett
48719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911
49719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_ACK 912
50719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_ADR 913
51719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_TIMEOUT 914
52719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_CMD 915
53719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_WRITE 916
54719f82d3SEliot Blennerhassett #define HPI6000_ERROR_SEND_DATA_IDLECMD 917
55719f82d3SEliot Blennerhassett
56719f82d3SEliot Blennerhassett #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921
57719f82d3SEliot Blennerhassett #define HPI6000_ERROR_GET_DATA_ACK 922
58719f82d3SEliot Blennerhassett #define HPI6000_ERROR_GET_DATA_CMD 923
59719f82d3SEliot Blennerhassett #define HPI6000_ERROR_GET_DATA_READ 924
60719f82d3SEliot Blennerhassett #define HPI6000_ERROR_GET_DATA_IDLECMD 925
61719f82d3SEliot Blennerhassett
62719f82d3SEliot Blennerhassett #define HPI6000_ERROR_CONTROL_CACHE_ADDRLEN 951
63719f82d3SEliot Blennerhassett #define HPI6000_ERROR_CONTROL_CACHE_READ 952
64719f82d3SEliot Blennerhassett #define HPI6000_ERROR_CONTROL_CACHE_FLUSH 953
65719f82d3SEliot Blennerhassett
66719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961
67719f82d3SEliot Blennerhassett #define HPI6000_ERROR_MSG_RESP_IDLECMD 962
68719f82d3SEliot Blennerhassett
693285ea10SEliot Blennerhassett /* Initialisation/bootload errors */
70719f82d3SEliot Blennerhassett #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930
71719f82d3SEliot Blennerhassett
72719f82d3SEliot Blennerhassett /* can't access PCI2040 */
73719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_PCI2040 931
74719f82d3SEliot Blennerhassett /* can't access DSP HPI i/f */
75719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_DSPHPI 932
76719f82d3SEliot Blennerhassett /* can't access internal DSP memory */
77719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_DSPINTMEM 933
78719f82d3SEliot Blennerhassett /* can't access SDRAM - test#1 */
79719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_SDRAM1 934
80719f82d3SEliot Blennerhassett /* can't access SDRAM - test#2 */
81719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_SDRAM2 935
82719f82d3SEliot Blennerhassett
83719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_VERIFY 938
84719f82d3SEliot Blennerhassett
85719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_NOACK 939
86719f82d3SEliot Blennerhassett
87719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_PLDTEST1 941
88719f82d3SEliot Blennerhassett #define HPI6000_ERROR_INIT_PLDTEST2 942
89719f82d3SEliot Blennerhassett
90719f82d3SEliot Blennerhassett /* local defines */
91719f82d3SEliot Blennerhassett
92719f82d3SEliot Blennerhassett #define HIDE_PCI_ASSERTS
93719f82d3SEliot Blennerhassett #define PROFILE_DSP2
94719f82d3SEliot Blennerhassett
95719f82d3SEliot Blennerhassett /* for PCI2040 i/f chip */
96719f82d3SEliot Blennerhassett /* HPI CSR registers */
97719f82d3SEliot Blennerhassett /* word offsets from CSR base */
98719f82d3SEliot Blennerhassett /* use when io addresses defined as u32 * */
99719f82d3SEliot Blennerhassett
100719f82d3SEliot Blennerhassett #define INTERRUPT_EVENT_SET 0
101719f82d3SEliot Blennerhassett #define INTERRUPT_EVENT_CLEAR 1
102719f82d3SEliot Blennerhassett #define INTERRUPT_MASK_SET 2
103719f82d3SEliot Blennerhassett #define INTERRUPT_MASK_CLEAR 3
104719f82d3SEliot Blennerhassett #define HPI_ERROR_REPORT 4
105719f82d3SEliot Blennerhassett #define HPI_RESET 5
106719f82d3SEliot Blennerhassett #define HPI_DATA_WIDTH 6
107719f82d3SEliot Blennerhassett
108719f82d3SEliot Blennerhassett #define MAX_DSPS 2
109719f82d3SEliot Blennerhassett /* HPI registers, spaced 8K bytes = 2K words apart */
110719f82d3SEliot Blennerhassett #define DSP_SPACING 0x800
111719f82d3SEliot Blennerhassett
112719f82d3SEliot Blennerhassett #define CONTROL 0x0000
113719f82d3SEliot Blennerhassett #define ADDRESS 0x0200
114719f82d3SEliot Blennerhassett #define DATA_AUTOINC 0x0400
115719f82d3SEliot Blennerhassett #define DATA 0x0600
116719f82d3SEliot Blennerhassett
117719f82d3SEliot Blennerhassett #define TIMEOUT 500000
118719f82d3SEliot Blennerhassett
119719f82d3SEliot Blennerhassett struct dsp_obj {
120719f82d3SEliot Blennerhassett __iomem u32 *prHPI_control;
121719f82d3SEliot Blennerhassett __iomem u32 *prHPI_address;
122719f82d3SEliot Blennerhassett __iomem u32 *prHPI_data;
123719f82d3SEliot Blennerhassett __iomem u32 *prHPI_data_auto_inc;
124719f82d3SEliot Blennerhassett char c_dsp_rev; /*A, B */
125719f82d3SEliot Blennerhassett u32 control_cache_address_on_dsp;
126719f82d3SEliot Blennerhassett u32 control_cache_length_on_dsp;
127719f82d3SEliot Blennerhassett struct hpi_adapter_obj *pa_parent_adapter;
128719f82d3SEliot Blennerhassett };
129719f82d3SEliot Blennerhassett
130719f82d3SEliot Blennerhassett struct hpi_hw_obj {
131719f82d3SEliot Blennerhassett __iomem u32 *dw2040_HPICSR;
132719f82d3SEliot Blennerhassett __iomem u32 *dw2040_HPIDSP;
133719f82d3SEliot Blennerhassett
134719f82d3SEliot Blennerhassett u16 num_dsp;
135719f82d3SEliot Blennerhassett struct dsp_obj ado[MAX_DSPS];
136719f82d3SEliot Blennerhassett
137719f82d3SEliot Blennerhassett u32 message_buffer_address_on_dsp;
138719f82d3SEliot Blennerhassett u32 response_buffer_address_on_dsp;
139719f82d3SEliot Blennerhassett u32 pCI2040HPI_error_count;
140719f82d3SEliot Blennerhassett
141719f82d3SEliot Blennerhassett struct hpi_control_cache_single control_cache[HPI_NMIXER_CONTROLS];
142719f82d3SEliot Blennerhassett struct hpi_control_cache *p_cache;
143719f82d3SEliot Blennerhassett };
144719f82d3SEliot Blennerhassett
145719f82d3SEliot Blennerhassett static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
146719f82d3SEliot Blennerhassett u16 dsp_index, u32 hpi_address, u32 *source, u32 count);
147719f82d3SEliot Blennerhassett static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
148719f82d3SEliot Blennerhassett u16 dsp_index, u32 hpi_address, u32 *dest, u32 count);
149719f82d3SEliot Blennerhassett
150719f82d3SEliot Blennerhassett static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
151719f82d3SEliot Blennerhassett u32 *pos_error_code);
152719f82d3SEliot Blennerhassett static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
153719f82d3SEliot Blennerhassett u16 read_or_write);
154719f82d3SEliot Blennerhassett #define H6READ 1
155719f82d3SEliot Blennerhassett #define H6WRITE 0
156719f82d3SEliot Blennerhassett
157719f82d3SEliot Blennerhassett static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
158719f82d3SEliot Blennerhassett struct hpi_message *phm);
159719f82d3SEliot Blennerhassett static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
160719f82d3SEliot Blennerhassett u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr);
161719f82d3SEliot Blennerhassett
162719f82d3SEliot Blennerhassett static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
163719f82d3SEliot Blennerhassett struct hpi_response *phr);
164719f82d3SEliot Blennerhassett
165719f82d3SEliot Blennerhassett static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
166719f82d3SEliot Blennerhassett u32 ack_value);
167719f82d3SEliot Blennerhassett
168719f82d3SEliot Blennerhassett static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
169719f82d3SEliot Blennerhassett u16 dsp_index, u32 host_cmd);
170719f82d3SEliot Blennerhassett
171719f82d3SEliot Blennerhassett static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo);
172719f82d3SEliot Blennerhassett
173719f82d3SEliot Blennerhassett static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
174719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr);
175719f82d3SEliot Blennerhassett
176719f82d3SEliot Blennerhassett static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
177719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr);
178719f82d3SEliot Blennerhassett
179719f82d3SEliot Blennerhassett static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data);
180719f82d3SEliot Blennerhassett
181719f82d3SEliot Blennerhassett static u32 hpi_read_word(struct dsp_obj *pdo, u32 address);
182719f82d3SEliot Blennerhassett
183719f82d3SEliot Blennerhassett static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
184719f82d3SEliot Blennerhassett u32 length);
185719f82d3SEliot Blennerhassett
186719f82d3SEliot Blennerhassett static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
187719f82d3SEliot Blennerhassett u32 length);
188719f82d3SEliot Blennerhassett
189719f82d3SEliot Blennerhassett static void subsys_create_adapter(struct hpi_message *phm,
190719f82d3SEliot Blennerhassett struct hpi_response *phr);
191719f82d3SEliot Blennerhassett
1926d0b898eSEliot Blennerhassett static void adapter_delete(struct hpi_adapter_obj *pao,
1936d0b898eSEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr);
194719f82d3SEliot Blennerhassett
195719f82d3SEliot Blennerhassett static void adapter_get_asserts(struct hpi_adapter_obj *pao,
196719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr);
197719f82d3SEliot Blennerhassett
198719f82d3SEliot Blennerhassett static short create_adapter_obj(struct hpi_adapter_obj *pao,
199719f82d3SEliot Blennerhassett u32 *pos_error_code);
200719f82d3SEliot Blennerhassett
2013285ea10SEliot Blennerhassett static void delete_adapter_obj(struct hpi_adapter_obj *pao);
2023285ea10SEliot Blennerhassett
203719f82d3SEliot Blennerhassett /* local globals */
204719f82d3SEliot Blennerhassett
205719f82d3SEliot Blennerhassett static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */
206719f82d3SEliot Blennerhassett static u16 gw_pci_write_asserts; /* used to count PCI2040 errors */
207719f82d3SEliot Blennerhassett
subsys_message(struct hpi_message * phm,struct hpi_response * phr)208719f82d3SEliot Blennerhassett static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
209719f82d3SEliot Blennerhassett {
210719f82d3SEliot Blennerhassett switch (phm->function) {
211719f82d3SEliot Blennerhassett case HPI_SUBSYS_CREATE_ADAPTER:
212719f82d3SEliot Blennerhassett subsys_create_adapter(phm, phr);
213719f82d3SEliot Blennerhassett break;
214719f82d3SEliot Blennerhassett default:
215719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_FUNC;
216719f82d3SEliot Blennerhassett break;
217719f82d3SEliot Blennerhassett }
218719f82d3SEliot Blennerhassett }
219719f82d3SEliot Blennerhassett
control_message(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)220719f82d3SEliot Blennerhassett static void control_message(struct hpi_adapter_obj *pao,
221719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
222719f82d3SEliot Blennerhassett {
2237036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
2247036b92dSEliot Blennerhassett
225719f82d3SEliot Blennerhassett switch (phm->function) {
226719f82d3SEliot Blennerhassett case HPI_CONTROL_GET_STATE:
227719f82d3SEliot Blennerhassett if (pao->has_control_cache) {
2280a00044dSEliot Blennerhassett u16 err;
2290a00044dSEliot Blennerhassett err = hpi6000_update_control_cache(pao, phm);
230719f82d3SEliot Blennerhassett
2310a00044dSEliot Blennerhassett if (err) {
2320a00044dSEliot Blennerhassett if (err >= HPI_ERROR_BACKEND_BASE) {
2330a00044dSEliot Blennerhassett phr->error =
2340a00044dSEliot Blennerhassett HPI_ERROR_CONTROL_CACHING;
2350a00044dSEliot Blennerhassett phr->specific_error = err;
2360a00044dSEliot Blennerhassett } else {
2370a00044dSEliot Blennerhassett phr->error = err;
2380a00044dSEliot Blennerhassett }
239719f82d3SEliot Blennerhassett break;
2400a00044dSEliot Blennerhassett }
241719f82d3SEliot Blennerhassett
2427036b92dSEliot Blennerhassett if (hpi_check_control_cache(phw->p_cache, phm, phr))
243719f82d3SEliot Blennerhassett break;
244719f82d3SEliot Blennerhassett }
245719f82d3SEliot Blennerhassett hw_message(pao, phm, phr);
246719f82d3SEliot Blennerhassett break;
247719f82d3SEliot Blennerhassett case HPI_CONTROL_SET_STATE:
248719f82d3SEliot Blennerhassett hw_message(pao, phm, phr);
2497036b92dSEliot Blennerhassett hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, phr);
250719f82d3SEliot Blennerhassett break;
2513285ea10SEliot Blennerhassett
2523285ea10SEliot Blennerhassett case HPI_CONTROL_GET_INFO:
253719f82d3SEliot Blennerhassett default:
2543285ea10SEliot Blennerhassett hw_message(pao, phm, phr);
255719f82d3SEliot Blennerhassett break;
256719f82d3SEliot Blennerhassett }
257719f82d3SEliot Blennerhassett }
258719f82d3SEliot Blennerhassett
adapter_message(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)259719f82d3SEliot Blennerhassett static void adapter_message(struct hpi_adapter_obj *pao,
260719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
261719f82d3SEliot Blennerhassett {
262719f82d3SEliot Blennerhassett switch (phm->function) {
263719f82d3SEliot Blennerhassett case HPI_ADAPTER_GET_ASSERT:
264719f82d3SEliot Blennerhassett adapter_get_asserts(pao, phm, phr);
265719f82d3SEliot Blennerhassett break;
2663285ea10SEliot Blennerhassett
2676d0b898eSEliot Blennerhassett case HPI_ADAPTER_DELETE:
2686d0b898eSEliot Blennerhassett adapter_delete(pao, phm, phr);
2696d0b898eSEliot Blennerhassett break;
2706d0b898eSEliot Blennerhassett
271719f82d3SEliot Blennerhassett default:
2723285ea10SEliot Blennerhassett hw_message(pao, phm, phr);
273719f82d3SEliot Blennerhassett break;
274719f82d3SEliot Blennerhassett }
275719f82d3SEliot Blennerhassett }
276719f82d3SEliot Blennerhassett
outstream_message(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)277719f82d3SEliot Blennerhassett static void outstream_message(struct hpi_adapter_obj *pao,
278719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
279719f82d3SEliot Blennerhassett {
280719f82d3SEliot Blennerhassett switch (phm->function) {
281719f82d3SEliot Blennerhassett case HPI_OSTREAM_HOSTBUFFER_ALLOC:
282719f82d3SEliot Blennerhassett case HPI_OSTREAM_HOSTBUFFER_FREE:
283719f82d3SEliot Blennerhassett /* Don't let these messages go to the HW function because
2843285ea10SEliot Blennerhassett * they're called without locking the spinlock.
285719f82d3SEliot Blennerhassett * For the HPI6000 adapters the HW would return
286719f82d3SEliot Blennerhassett * HPI_ERROR_INVALID_FUNC anyway.
287719f82d3SEliot Blennerhassett */
288719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_FUNC;
289719f82d3SEliot Blennerhassett break;
290719f82d3SEliot Blennerhassett default:
291719f82d3SEliot Blennerhassett hw_message(pao, phm, phr);
292719f82d3SEliot Blennerhassett return;
293719f82d3SEliot Blennerhassett }
294719f82d3SEliot Blennerhassett }
295719f82d3SEliot Blennerhassett
instream_message(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)296719f82d3SEliot Blennerhassett static void instream_message(struct hpi_adapter_obj *pao,
297719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
298719f82d3SEliot Blennerhassett {
299719f82d3SEliot Blennerhassett
300719f82d3SEliot Blennerhassett switch (phm->function) {
301719f82d3SEliot Blennerhassett case HPI_ISTREAM_HOSTBUFFER_ALLOC:
302719f82d3SEliot Blennerhassett case HPI_ISTREAM_HOSTBUFFER_FREE:
303719f82d3SEliot Blennerhassett /* Don't let these messages go to the HW function because
3043285ea10SEliot Blennerhassett * they're called without locking the spinlock.
305719f82d3SEliot Blennerhassett * For the HPI6000 adapters the HW would return
306719f82d3SEliot Blennerhassett * HPI_ERROR_INVALID_FUNC anyway.
307719f82d3SEliot Blennerhassett */
308719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_FUNC;
309719f82d3SEliot Blennerhassett break;
310719f82d3SEliot Blennerhassett default:
311719f82d3SEliot Blennerhassett hw_message(pao, phm, phr);
312719f82d3SEliot Blennerhassett return;
313719f82d3SEliot Blennerhassett }
314719f82d3SEliot Blennerhassett }
315719f82d3SEliot Blennerhassett
316719f82d3SEliot Blennerhassett /************************************************************************/
317719f82d3SEliot Blennerhassett /** HPI_6000()
318719f82d3SEliot Blennerhassett * Entry point from HPIMAN
319719f82d3SEliot Blennerhassett * All calls to the HPI start here
320719f82d3SEliot Blennerhassett */
HPI_6000(struct hpi_message * phm,struct hpi_response * phr)321719f82d3SEliot Blennerhassett void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
322719f82d3SEliot Blennerhassett {
323719f82d3SEliot Blennerhassett struct hpi_adapter_obj *pao = NULL;
324719f82d3SEliot Blennerhassett
325719f82d3SEliot Blennerhassett if (phm->object != HPI_OBJ_SUBSYSTEM) {
326719f82d3SEliot Blennerhassett pao = hpi_find_adapter(phm->adapter_index);
327719f82d3SEliot Blennerhassett if (!pao) {
3286d0b898eSEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function,
3296d0b898eSEliot Blennerhassett HPI_ERROR_BAD_ADAPTER_NUMBER);
3306d0b898eSEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n",
3316d0b898eSEliot Blennerhassett phm->adapter_index);
332719f82d3SEliot Blennerhassett return;
333719f82d3SEliot Blennerhassett }
334719f82d3SEliot Blennerhassett
3356d0b898eSEliot Blennerhassett /* Don't even try to communicate with crashed DSP */
336719f82d3SEliot Blennerhassett if (pao->dsp_crashed >= 10) {
337719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function,
338719f82d3SEliot Blennerhassett HPI_ERROR_DSP_HARDWARE);
3396d0b898eSEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n",
3406d0b898eSEliot Blennerhassett phm->adapter_index);
341719f82d3SEliot Blennerhassett return;
342719f82d3SEliot Blennerhassett }
343719f82d3SEliot Blennerhassett }
344719f82d3SEliot Blennerhassett /* Init default response including the size field */
345719f82d3SEliot Blennerhassett if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
346719f82d3SEliot Blennerhassett hpi_init_response(phr, phm->object, phm->function,
347719f82d3SEliot Blennerhassett HPI_ERROR_PROCESSING_MESSAGE);
348719f82d3SEliot Blennerhassett
349719f82d3SEliot Blennerhassett switch (phm->type) {
35082b5774fSEliot Blennerhassett case HPI_TYPE_REQUEST:
351719f82d3SEliot Blennerhassett switch (phm->object) {
352719f82d3SEliot Blennerhassett case HPI_OBJ_SUBSYSTEM:
353719f82d3SEliot Blennerhassett subsys_message(phm, phr);
354719f82d3SEliot Blennerhassett break;
355719f82d3SEliot Blennerhassett
356719f82d3SEliot Blennerhassett case HPI_OBJ_ADAPTER:
357719f82d3SEliot Blennerhassett phr->size =
358719f82d3SEliot Blennerhassett sizeof(struct hpi_response_header) +
359719f82d3SEliot Blennerhassett sizeof(struct hpi_adapter_res);
360719f82d3SEliot Blennerhassett adapter_message(pao, phm, phr);
361719f82d3SEliot Blennerhassett break;
362719f82d3SEliot Blennerhassett
363719f82d3SEliot Blennerhassett case HPI_OBJ_CONTROL:
364719f82d3SEliot Blennerhassett control_message(pao, phm, phr);
365719f82d3SEliot Blennerhassett break;
366719f82d3SEliot Blennerhassett
367719f82d3SEliot Blennerhassett case HPI_OBJ_OSTREAM:
368719f82d3SEliot Blennerhassett outstream_message(pao, phm, phr);
369719f82d3SEliot Blennerhassett break;
370719f82d3SEliot Blennerhassett
371719f82d3SEliot Blennerhassett case HPI_OBJ_ISTREAM:
372719f82d3SEliot Blennerhassett instream_message(pao, phm, phr);
373719f82d3SEliot Blennerhassett break;
374719f82d3SEliot Blennerhassett
375719f82d3SEliot Blennerhassett default:
376719f82d3SEliot Blennerhassett hw_message(pao, phm, phr);
377719f82d3SEliot Blennerhassett break;
378719f82d3SEliot Blennerhassett }
379719f82d3SEliot Blennerhassett break;
380719f82d3SEliot Blennerhassett
381719f82d3SEliot Blennerhassett default:
382719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_INVALID_TYPE;
383719f82d3SEliot Blennerhassett break;
384719f82d3SEliot Blennerhassett }
385719f82d3SEliot Blennerhassett }
386719f82d3SEliot Blennerhassett
387719f82d3SEliot Blennerhassett /************************************************************************/
388719f82d3SEliot Blennerhassett /* SUBSYSTEM */
389719f82d3SEliot Blennerhassett
390719f82d3SEliot Blennerhassett /* create an adapter object and initialise it based on resource information
391*ccc86a0aSwangjianli * passed in the message
392719f82d3SEliot Blennerhassett * NOTE - you cannot use this function AND the FindAdapters function at the
393719f82d3SEliot Blennerhassett * same time, the application must use only one of them to get the adapters
394719f82d3SEliot Blennerhassett */
subsys_create_adapter(struct hpi_message * phm,struct hpi_response * phr)395719f82d3SEliot Blennerhassett static void subsys_create_adapter(struct hpi_message *phm,
396719f82d3SEliot Blennerhassett struct hpi_response *phr)
397719f82d3SEliot Blennerhassett {
398719f82d3SEliot Blennerhassett /* create temp adapter obj, because we don't know what index yet */
399719f82d3SEliot Blennerhassett struct hpi_adapter_obj ao;
400719f82d3SEliot Blennerhassett struct hpi_adapter_obj *pao;
401719f82d3SEliot Blennerhassett u32 os_error_code;
4020a00044dSEliot Blennerhassett u16 err = 0;
403719f82d3SEliot Blennerhassett u32 dsp_index = 0;
404719f82d3SEliot Blennerhassett
405719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
406719f82d3SEliot Blennerhassett
407719f82d3SEliot Blennerhassett memset(&ao, 0, sizeof(ao));
408719f82d3SEliot Blennerhassett
409550a8b69SJulia Lawall ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
410719f82d3SEliot Blennerhassett if (!ao.priv) {
41125985edcSLucas De Marchi HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n");
412719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_MEMORY_ALLOC;
413719f82d3SEliot Blennerhassett return;
414719f82d3SEliot Blennerhassett }
415719f82d3SEliot Blennerhassett
416719f82d3SEliot Blennerhassett /* create the adapter object based on the resource information */
417719f82d3SEliot Blennerhassett ao.pci = *phm->u.s.resource.r.pci;
418719f82d3SEliot Blennerhassett
4190a00044dSEliot Blennerhassett err = create_adapter_obj(&ao, &os_error_code);
4200a00044dSEliot Blennerhassett if (err) {
4213285ea10SEliot Blennerhassett delete_adapter_obj(&ao);
4220a00044dSEliot Blennerhassett if (err >= HPI_ERROR_BACKEND_BASE) {
4230a00044dSEliot Blennerhassett phr->error = HPI_ERROR_DSP_BOOTLOAD;
4240a00044dSEliot Blennerhassett phr->specific_error = err;
4250a00044dSEliot Blennerhassett } else {
4260a00044dSEliot Blennerhassett phr->error = err;
4270a00044dSEliot Blennerhassett }
4280a00044dSEliot Blennerhassett
4293285ea10SEliot Blennerhassett phr->u.s.data = os_error_code;
430719f82d3SEliot Blennerhassett return;
431719f82d3SEliot Blennerhassett }
432719f82d3SEliot Blennerhassett /* need to update paParentAdapter */
433719f82d3SEliot Blennerhassett pao = hpi_find_adapter(ao.index);
434719f82d3SEliot Blennerhassett if (!pao) {
435719f82d3SEliot Blennerhassett /* We just added this adapter, why can't we find it!? */
436719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
4370a00044dSEliot Blennerhassett phr->error = HPI_ERROR_BAD_ADAPTER;
438719f82d3SEliot Blennerhassett return;
439719f82d3SEliot Blennerhassett }
440719f82d3SEliot Blennerhassett
441719f82d3SEliot Blennerhassett for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
4427036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
443719f82d3SEliot Blennerhassett phw->ado[dsp_index].pa_parent_adapter = pao;
444719f82d3SEliot Blennerhassett }
445719f82d3SEliot Blennerhassett
4467036b92dSEliot Blennerhassett phr->u.s.adapter_type = ao.type;
447719f82d3SEliot Blennerhassett phr->u.s.adapter_index = ao.index;
448719f82d3SEliot Blennerhassett phr->error = 0;
449719f82d3SEliot Blennerhassett }
450719f82d3SEliot Blennerhassett
adapter_delete(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)4516d0b898eSEliot Blennerhassett static void adapter_delete(struct hpi_adapter_obj *pao,
4526d0b898eSEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
453719f82d3SEliot Blennerhassett {
4543285ea10SEliot Blennerhassett delete_adapter_obj(pao);
455719f82d3SEliot Blennerhassett hpi_delete_adapter(pao);
456719f82d3SEliot Blennerhassett phr->error = 0;
457719f82d3SEliot Blennerhassett }
458719f82d3SEliot Blennerhassett
459719f82d3SEliot Blennerhassett /* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
create_adapter_obj(struct hpi_adapter_obj * pao,u32 * pos_error_code)460719f82d3SEliot Blennerhassett static short create_adapter_obj(struct hpi_adapter_obj *pao,
461719f82d3SEliot Blennerhassett u32 *pos_error_code)
462719f82d3SEliot Blennerhassett {
463719f82d3SEliot Blennerhassett short boot_error = 0;
464719f82d3SEliot Blennerhassett u32 dsp_index = 0;
465719f82d3SEliot Blennerhassett u32 control_cache_size = 0;
466719f82d3SEliot Blennerhassett u32 control_cache_count = 0;
4677036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
468719f82d3SEliot Blennerhassett
469719f82d3SEliot Blennerhassett /* The PCI2040 has the following address map */
470719f82d3SEliot Blennerhassett /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
471719f82d3SEliot Blennerhassett /* BAR1 - 32K = HPI registers on DSP */
472719f82d3SEliot Blennerhassett phw->dw2040_HPICSR = pao->pci.ap_mem_base[0];
473719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1];
474719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR,
475719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP);
476719f82d3SEliot Blennerhassett
477719f82d3SEliot Blennerhassett /* set addresses for the possible DSP HPI interfaces */
478719f82d3SEliot Blennerhassett for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
479719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_control =
480719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP + (CONTROL +
481719f82d3SEliot Blennerhassett DSP_SPACING * dsp_index);
482719f82d3SEliot Blennerhassett
483719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_address =
484719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP + (ADDRESS +
485719f82d3SEliot Blennerhassett DSP_SPACING * dsp_index);
486719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_data =
487719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index);
488719f82d3SEliot Blennerhassett
489719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_data_auto_inc =
490719f82d3SEliot Blennerhassett phw->dw2040_HPIDSP + (DATA_AUTOINC +
491719f82d3SEliot Blennerhassett DSP_SPACING * dsp_index);
492719f82d3SEliot Blennerhassett
493719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
494719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_control,
495719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_address,
496719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_data,
497719f82d3SEliot Blennerhassett phw->ado[dsp_index].prHPI_data_auto_inc);
498719f82d3SEliot Blennerhassett
499719f82d3SEliot Blennerhassett phw->ado[dsp_index].pa_parent_adapter = pao;
500719f82d3SEliot Blennerhassett }
501719f82d3SEliot Blennerhassett
502719f82d3SEliot Blennerhassett phw->pCI2040HPI_error_count = 0;
503719f82d3SEliot Blennerhassett pao->has_control_cache = 0;
504719f82d3SEliot Blennerhassett
505719f82d3SEliot Blennerhassett /* Set the default number of DSPs on this card */
506719f82d3SEliot Blennerhassett /* This is (conditionally) adjusted after bootloading */
507719f82d3SEliot Blennerhassett /* of the first DSP in the bootload section. */
508719f82d3SEliot Blennerhassett phw->num_dsp = 1;
509719f82d3SEliot Blennerhassett
510719f82d3SEliot Blennerhassett boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code);
511719f82d3SEliot Blennerhassett if (boot_error)
512719f82d3SEliot Blennerhassett return boot_error;
513719f82d3SEliot Blennerhassett
514719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
515719f82d3SEliot Blennerhassett
516719f82d3SEliot Blennerhassett phw->message_buffer_address_on_dsp = 0L;
517719f82d3SEliot Blennerhassett phw->response_buffer_address_on_dsp = 0L;
518719f82d3SEliot Blennerhassett
519719f82d3SEliot Blennerhassett /* get info about the adapter by asking the adapter */
520719f82d3SEliot Blennerhassett /* send a HPI_ADAPTER_GET_INFO message */
521719f82d3SEliot Blennerhassett {
5223285ea10SEliot Blennerhassett struct hpi_message hm;
5233285ea10SEliot Blennerhassett struct hpi_response hr0; /* response from DSP 0 */
5243285ea10SEliot Blennerhassett struct hpi_response hr1; /* response from DSP 1 */
525719f82d3SEliot Blennerhassett u16 error = 0;
526719f82d3SEliot Blennerhassett
527719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
5283285ea10SEliot Blennerhassett memset(&hm, 0, sizeof(hm));
52982b5774fSEliot Blennerhassett hm.type = HPI_TYPE_REQUEST;
5303285ea10SEliot Blennerhassett hm.size = sizeof(struct hpi_message);
5313285ea10SEliot Blennerhassett hm.object = HPI_OBJ_ADAPTER;
5323285ea10SEliot Blennerhassett hm.function = HPI_ADAPTER_GET_INFO;
5333285ea10SEliot Blennerhassett hm.adapter_index = 0;
5343285ea10SEliot Blennerhassett memset(&hr0, 0, sizeof(hr0));
5353285ea10SEliot Blennerhassett memset(&hr1, 0, sizeof(hr1));
5363285ea10SEliot Blennerhassett hr0.size = sizeof(hr0);
5373285ea10SEliot Blennerhassett hr1.size = sizeof(hr1);
538719f82d3SEliot Blennerhassett
5393285ea10SEliot Blennerhassett error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
5403285ea10SEliot Blennerhassett if (hr0.error) {
5413285ea10SEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
5423285ea10SEliot Blennerhassett return hr0.error;
543719f82d3SEliot Blennerhassett }
544719f82d3SEliot Blennerhassett if (phw->num_dsp == 2) {
5453285ea10SEliot Blennerhassett error = hpi6000_message_response_sequence(pao, 1, &hm,
5463285ea10SEliot Blennerhassett &hr1);
547719f82d3SEliot Blennerhassett if (error)
548719f82d3SEliot Blennerhassett return error;
549719f82d3SEliot Blennerhassett }
5507036b92dSEliot Blennerhassett pao->type = hr0.u.ax.info.adapter_type;
5513285ea10SEliot Blennerhassett pao->index = hr0.u.ax.info.adapter_index;
552719f82d3SEliot Blennerhassett }
553719f82d3SEliot Blennerhassett
554719f82d3SEliot Blennerhassett memset(&phw->control_cache[0], 0,
555719f82d3SEliot Blennerhassett sizeof(struct hpi_control_cache_single) *
556719f82d3SEliot Blennerhassett HPI_NMIXER_CONTROLS);
557719f82d3SEliot Blennerhassett /* Read the control cache length to figure out if it is turned on */
558719f82d3SEliot Blennerhassett control_cache_size =
559719f82d3SEliot Blennerhassett hpi_read_word(&phw->ado[0],
560719f82d3SEliot Blennerhassett HPI_HIF_ADDR(control_cache_size_in_bytes));
561719f82d3SEliot Blennerhassett if (control_cache_size) {
562719f82d3SEliot Blennerhassett control_cache_count =
563719f82d3SEliot Blennerhassett hpi_read_word(&phw->ado[0],
564719f82d3SEliot Blennerhassett HPI_HIF_ADDR(control_cache_count));
565719f82d3SEliot Blennerhassett
566719f82d3SEliot Blennerhassett phw->p_cache =
567719f82d3SEliot Blennerhassett hpi_alloc_control_cache(control_cache_count,
5683285ea10SEliot Blennerhassett control_cache_size, (unsigned char *)
569719f82d3SEliot Blennerhassett &phw->control_cache[0]
570719f82d3SEliot Blennerhassett );
5713285ea10SEliot Blennerhassett if (phw->p_cache)
5723285ea10SEliot Blennerhassett pao->has_control_cache = 1;
5733285ea10SEliot Blennerhassett }
574719f82d3SEliot Blennerhassett
5757036b92dSEliot Blennerhassett HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type,
5767036b92dSEliot Blennerhassett pao->index);
5773285ea10SEliot Blennerhassett
578ffdb5787SEliot Blennerhassett if (phw->p_cache)
579ffdb5787SEliot Blennerhassett phw->p_cache->adap_idx = pao->index;
580ffdb5787SEliot Blennerhassett
5813285ea10SEliot Blennerhassett return hpi_add_adapter(pao);
5823285ea10SEliot Blennerhassett }
5833285ea10SEliot Blennerhassett
delete_adapter_obj(struct hpi_adapter_obj * pao)5843285ea10SEliot Blennerhassett static void delete_adapter_obj(struct hpi_adapter_obj *pao)
5853285ea10SEliot Blennerhassett {
5867036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
5873285ea10SEliot Blennerhassett
5883285ea10SEliot Blennerhassett if (pao->has_control_cache)
5893285ea10SEliot Blennerhassett hpi_free_control_cache(phw->p_cache);
5903285ea10SEliot Blennerhassett
5913285ea10SEliot Blennerhassett /* reset DSPs on adapter */
5923285ea10SEliot Blennerhassett iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET);
5933285ea10SEliot Blennerhassett
5943285ea10SEliot Blennerhassett kfree(phw);
595719f82d3SEliot Blennerhassett }
596719f82d3SEliot Blennerhassett
597719f82d3SEliot Blennerhassett /************************************************************************/
598719f82d3SEliot Blennerhassett /* ADAPTER */
599719f82d3SEliot Blennerhassett
adapter_get_asserts(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)600719f82d3SEliot Blennerhassett static void adapter_get_asserts(struct hpi_adapter_obj *pao,
601719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
602719f82d3SEliot Blennerhassett {
603719f82d3SEliot Blennerhassett #ifndef HIDE_PCI_ASSERTS
604719f82d3SEliot Blennerhassett /* if we have PCI2040 asserts then collect them */
605719f82d3SEliot Blennerhassett if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
6063285ea10SEliot Blennerhassett phr->u.ax.assert.p1 =
607719f82d3SEliot Blennerhassett gw_pci_read_asserts * 100 + gw_pci_write_asserts;
6083285ea10SEliot Blennerhassett phr->u.ax.assert.p2 = 0;
6093285ea10SEliot Blennerhassett phr->u.ax.assert.count = 1; /* assert count */
6103285ea10SEliot Blennerhassett phr->u.ax.assert.dsp_index = -1; /* "dsp index" */
6113285ea10SEliot Blennerhassett strcpy(phr->u.ax.assert.sz_message, "PCI2040 error");
6123285ea10SEliot Blennerhassett phr->u.ax.assert.dsp_msg_addr = 0;
613719f82d3SEliot Blennerhassett gw_pci_read_asserts = 0;
614719f82d3SEliot Blennerhassett gw_pci_write_asserts = 0;
615719f82d3SEliot Blennerhassett phr->error = 0;
616719f82d3SEliot Blennerhassett } else
617719f82d3SEliot Blennerhassett #endif
618719f82d3SEliot Blennerhassett hw_message(pao, phm, phr); /*get DSP asserts */
619719f82d3SEliot Blennerhassett
620719f82d3SEliot Blennerhassett return;
621719f82d3SEliot Blennerhassett }
622719f82d3SEliot Blennerhassett
623719f82d3SEliot Blennerhassett /************************************************************************/
624719f82d3SEliot Blennerhassett /* LOW-LEVEL */
625719f82d3SEliot Blennerhassett
hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj * pao,u32 * pos_error_code)626719f82d3SEliot Blennerhassett static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
627719f82d3SEliot Blennerhassett u32 *pos_error_code)
628719f82d3SEliot Blennerhassett {
6297036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
630719f82d3SEliot Blennerhassett short error;
631719f82d3SEliot Blennerhassett u32 timeout;
632719f82d3SEliot Blennerhassett u32 read = 0;
633719f82d3SEliot Blennerhassett u32 i = 0;
634719f82d3SEliot Blennerhassett u32 data = 0;
635719f82d3SEliot Blennerhassett u32 j = 0;
636719f82d3SEliot Blennerhassett u32 test_addr = 0x80000000;
637719f82d3SEliot Blennerhassett u32 test_data = 0x00000001;
638719f82d3SEliot Blennerhassett u32 dw2040_reset = 0;
639719f82d3SEliot Blennerhassett u32 dsp_index = 0;
640719f82d3SEliot Blennerhassett u32 endian = 0;
641719f82d3SEliot Blennerhassett u32 adapter_info = 0;
642719f82d3SEliot Blennerhassett u32 delay = 0;
643719f82d3SEliot Blennerhassett
644719f82d3SEliot Blennerhassett struct dsp_code dsp_code;
645719f82d3SEliot Blennerhassett u16 boot_load_family = 0;
646719f82d3SEliot Blennerhassett
647719f82d3SEliot Blennerhassett /* NOTE don't use wAdapterType in this routine. It is not setup yet */
648719f82d3SEliot Blennerhassett
6493285ea10SEliot Blennerhassett switch (pao->pci.pci_dev->subsystem_device) {
650719f82d3SEliot Blennerhassett case 0x5100:
651719f82d3SEliot Blennerhassett case 0x5110: /* ASI5100 revB or higher with C6711D */
6523285ea10SEliot Blennerhassett case 0x5200: /* ASI5200 PCIe version of ASI5100 */
653719f82d3SEliot Blennerhassett case 0x6100:
654719f82d3SEliot Blennerhassett case 0x6200:
655719f82d3SEliot Blennerhassett boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
656719f82d3SEliot Blennerhassett break;
657719f82d3SEliot Blennerhassett default:
658719f82d3SEliot Blennerhassett return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
659719f82d3SEliot Blennerhassett }
660719f82d3SEliot Blennerhassett
661719f82d3SEliot Blennerhassett /* reset all DSPs, indicate two DSPs are present
662719f82d3SEliot Blennerhassett * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode
663719f82d3SEliot Blennerhassett */
664719f82d3SEliot Blennerhassett endian = 0;
665719f82d3SEliot Blennerhassett dw2040_reset = 0x0003000F;
666719f82d3SEliot Blennerhassett iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
667719f82d3SEliot Blennerhassett
668719f82d3SEliot Blennerhassett /* read back register to make sure PCI2040 chip is functioning
669719f82d3SEliot Blennerhassett * note that bits 4..15 are read-only and so should always return zero,
670719f82d3SEliot Blennerhassett * even though we wrote 1 to them
671719f82d3SEliot Blennerhassett */
6723285ea10SEliot Blennerhassett hpios_delay_micro_seconds(1000);
673719f82d3SEliot Blennerhassett delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
6743285ea10SEliot Blennerhassett
675719f82d3SEliot Blennerhassett if (delay != dw2040_reset) {
676719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
677719f82d3SEliot Blennerhassett delay);
678719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_PCI2040;
679719f82d3SEliot Blennerhassett }
680719f82d3SEliot Blennerhassett
681719f82d3SEliot Blennerhassett /* Indicate that DSP#0,1 is a C6X */
682719f82d3SEliot Blennerhassett iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH);
683719f82d3SEliot Blennerhassett /* set Bit30 and 29 - which will prevent Target aborts from being
684719f82d3SEliot Blennerhassett * issued upon HPI or GP error
685719f82d3SEliot Blennerhassett */
686719f82d3SEliot Blennerhassett iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET);
687719f82d3SEliot Blennerhassett
688719f82d3SEliot Blennerhassett /* isolate DSP HAD8 line from PCI2040 so that
689719f82d3SEliot Blennerhassett * Little endian can be set by pullup
690719f82d3SEliot Blennerhassett */
691719f82d3SEliot Blennerhassett dw2040_reset = dw2040_reset & (~(endian << 3));
692719f82d3SEliot Blennerhassett iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
693719f82d3SEliot Blennerhassett
694719f82d3SEliot Blennerhassett phw->ado[0].c_dsp_rev = 'B'; /* revB */
695719f82d3SEliot Blennerhassett phw->ado[1].c_dsp_rev = 'B'; /* revB */
696719f82d3SEliot Blennerhassett
697719f82d3SEliot Blennerhassett /*Take both DSPs out of reset, setting HAD8 to the correct Endian */
698719f82d3SEliot Blennerhassett dw2040_reset = dw2040_reset & (~0x00000001); /* start DSP 0 */
699719f82d3SEliot Blennerhassett iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
700719f82d3SEliot Blennerhassett dw2040_reset = dw2040_reset & (~0x00000002); /* start DSP 1 */
701719f82d3SEliot Blennerhassett iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
702719f82d3SEliot Blennerhassett
703719f82d3SEliot Blennerhassett /* set HAD8 back to PCI2040, now that DSP set to little endian mode */
704719f82d3SEliot Blennerhassett dw2040_reset = dw2040_reset & (~0x00000008);
705719f82d3SEliot Blennerhassett iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
706719f82d3SEliot Blennerhassett /*delay to allow DSP to get going */
7073285ea10SEliot Blennerhassett hpios_delay_micro_seconds(100);
708719f82d3SEliot Blennerhassett
709719f82d3SEliot Blennerhassett /* loop through all DSPs, downloading DSP code */
710719f82d3SEliot Blennerhassett for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
711719f82d3SEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
712719f82d3SEliot Blennerhassett
713719f82d3SEliot Blennerhassett /* configure DSP so that we download code into the SRAM */
714719f82d3SEliot Blennerhassett /* set control reg for little endian, HWOB=1 */
715719f82d3SEliot Blennerhassett iowrite32(0x00010001, pdo->prHPI_control);
716719f82d3SEliot Blennerhassett
717719f82d3SEliot Blennerhassett /* test access to the HPI address register (HPIA) */
718719f82d3SEliot Blennerhassett test_data = 0x00000001;
719719f82d3SEliot Blennerhassett for (j = 0; j < 32; j++) {
720719f82d3SEliot Blennerhassett iowrite32(test_data, pdo->prHPI_address);
721719f82d3SEliot Blennerhassett data = ioread32(pdo->prHPI_address);
722719f82d3SEliot Blennerhassett if (data != test_data) {
723719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n",
724719f82d3SEliot Blennerhassett test_data, data, dsp_index);
725719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_DSPHPI;
726719f82d3SEliot Blennerhassett }
727719f82d3SEliot Blennerhassett test_data = test_data << 1;
728719f82d3SEliot Blennerhassett }
729719f82d3SEliot Blennerhassett
730719f82d3SEliot Blennerhassett /* if C6713 the setup PLL to generate 225MHz from 25MHz.
731719f82d3SEliot Blennerhassett * Since the PLLDIV1 read is sometimes wrong, even on a C6713,
732719f82d3SEliot Blennerhassett * we're going to do this unconditionally
733719f82d3SEliot Blennerhassett */
734719f82d3SEliot Blennerhassett /* PLLDIV1 should have a value of 8000 after reset */
735719f82d3SEliot Blennerhassett /*
736719f82d3SEliot Blennerhassett if (HpiReadWord(pdo,0x01B7C118) == 0x8000)
737719f82d3SEliot Blennerhassett */
738719f82d3SEliot Blennerhassett {
739719f82d3SEliot Blennerhassett /* C6713 datasheet says we cannot program PLL from HPI,
740719f82d3SEliot Blennerhassett * and indeed if we try to set the PLL multiply from the
741719f82d3SEliot Blennerhassett * HPI, the PLL does not seem to lock,
742719f82d3SEliot Blennerhassett * so we enable the PLL and use the default of x 7
743719f82d3SEliot Blennerhassett */
744719f82d3SEliot Blennerhassett /* bypass PLL */
745719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01B7C100, 0x0000);
7463285ea10SEliot Blennerhassett hpios_delay_micro_seconds(100);
747719f82d3SEliot Blennerhassett
748719f82d3SEliot Blennerhassett /* ** use default of PLL x7 ** */
749719f82d3SEliot Blennerhassett /* EMIF = 225/3=75MHz */
750719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01B7C120, 0x8002);
7513285ea10SEliot Blennerhassett hpios_delay_micro_seconds(100);
7523285ea10SEliot Blennerhassett
753719f82d3SEliot Blennerhassett /* peri = 225/2 */
754719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01B7C11C, 0x8001);
7553285ea10SEliot Blennerhassett hpios_delay_micro_seconds(100);
7563285ea10SEliot Blennerhassett
757719f82d3SEliot Blennerhassett /* cpu = 225/1 */
758719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01B7C118, 0x8000);
7593285ea10SEliot Blennerhassett
7603285ea10SEliot Blennerhassett /* ~2ms delay */
7613285ea10SEliot Blennerhassett hpios_delay_micro_seconds(2000);
7623285ea10SEliot Blennerhassett
763719f82d3SEliot Blennerhassett /* PLL not bypassed */
764719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01B7C100, 0x0001);
7653285ea10SEliot Blennerhassett /* ~2ms delay */
7663285ea10SEliot Blennerhassett hpios_delay_micro_seconds(2000);
767719f82d3SEliot Blennerhassett }
768719f82d3SEliot Blennerhassett
769719f82d3SEliot Blennerhassett /* test r/w to internal DSP memory
770719f82d3SEliot Blennerhassett * C6711 has L2 cache mapped to 0x0 when reset
771719f82d3SEliot Blennerhassett *
772719f82d3SEliot Blennerhassett * revB - because of bug 3.0.1 last HPI read
773719f82d3SEliot Blennerhassett * (before HPI address issued) must be non-autoinc
774719f82d3SEliot Blennerhassett */
775719f82d3SEliot Blennerhassett /* test each bit in the 32bit word */
776719f82d3SEliot Blennerhassett for (i = 0; i < 100; i++) {
777719f82d3SEliot Blennerhassett test_addr = 0x00000000;
778719f82d3SEliot Blennerhassett test_data = 0x00000001;
779719f82d3SEliot Blennerhassett for (j = 0; j < 32; j++) {
780719f82d3SEliot Blennerhassett hpi_write_word(pdo, test_addr + i, test_data);
781719f82d3SEliot Blennerhassett data = hpi_read_word(pdo, test_addr + i);
782719f82d3SEliot Blennerhassett if (data != test_data) {
783719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR,
784719f82d3SEliot Blennerhassett "DSP mem %x %x %x %x\n",
785719f82d3SEliot Blennerhassett test_addr + i, test_data,
786719f82d3SEliot Blennerhassett data, dsp_index);
787719f82d3SEliot Blennerhassett
788719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_DSPINTMEM;
789719f82d3SEliot Blennerhassett }
790719f82d3SEliot Blennerhassett test_data = test_data << 1;
791719f82d3SEliot Blennerhassett }
792719f82d3SEliot Blennerhassett }
793719f82d3SEliot Blennerhassett
794719f82d3SEliot Blennerhassett /* memory map of ASI6200
795719f82d3SEliot Blennerhassett 00000000-0000FFFF 16Kx32 internal program
796719f82d3SEliot Blennerhassett 01800000-019FFFFF Internal peripheral
797719f82d3SEliot Blennerhassett 80000000-807FFFFF CE0 2Mx32 SDRAM running @ 100MHz
798719f82d3SEliot Blennerhassett 90000000-9000FFFF CE1 Async peripherals:
799719f82d3SEliot Blennerhassett
800719f82d3SEliot Blennerhassett EMIF config
801719f82d3SEliot Blennerhassett ------------
802719f82d3SEliot Blennerhassett Global EMIF control
803719f82d3SEliot Blennerhassett 0 -
804719f82d3SEliot Blennerhassett 1 -
805719f82d3SEliot Blennerhassett 2 -
806719f82d3SEliot Blennerhassett 3 CLK2EN = 1 CLKOUT2 enabled
807719f82d3SEliot Blennerhassett 4 CLK1EN = 0 CLKOUT1 disabled
808719f82d3SEliot Blennerhassett 5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT
809719f82d3SEliot Blennerhassett 6 -
810719f82d3SEliot Blennerhassett 7 NOHOLD = 1 external HOLD disabled
811719f82d3SEliot Blennerhassett 8 HOLDA = 0 HOLDA output is low
812719f82d3SEliot Blennerhassett 9 HOLD = 0 HOLD input is low
813719f82d3SEliot Blennerhassett 10 ARDY = 1 ARDY input is high
814719f82d3SEliot Blennerhassett 11 BUSREQ = 0 BUSREQ output is low
815719f82d3SEliot Blennerhassett 12,13 Reserved = 1
816719f82d3SEliot Blennerhassett */
817719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01800000, 0x34A8);
818719f82d3SEliot Blennerhassett
819719f82d3SEliot Blennerhassett /* EMIF CE0 setup - 2Mx32 Sync DRAM
820719f82d3SEliot Blennerhassett 31..28 Wr setup
821719f82d3SEliot Blennerhassett 27..22 Wr strobe
822719f82d3SEliot Blennerhassett 21..20 Wr hold
823719f82d3SEliot Blennerhassett 19..16 Rd setup
824719f82d3SEliot Blennerhassett 15..14 -
825719f82d3SEliot Blennerhassett 13..8 Rd strobe
826719f82d3SEliot Blennerhassett 7..4 MTYPE 0011 Sync DRAM 32bits
827719f82d3SEliot Blennerhassett 3 Wr hold MSB
828719f82d3SEliot Blennerhassett 2..0 Rd hold
829719f82d3SEliot Blennerhassett */
830719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01800008, 0x00000030);
831719f82d3SEliot Blennerhassett
832719f82d3SEliot Blennerhassett /* EMIF SDRAM Extension
833719f82d3SEliot Blennerhassett 31-21 0
834719f82d3SEliot Blennerhassett 20 WR2RD = 0
835719f82d3SEliot Blennerhassett 19-18 WR2DEAC = 1
836719f82d3SEliot Blennerhassett 17 WR2WR = 0
837719f82d3SEliot Blennerhassett 16-15 R2WDQM = 2
838719f82d3SEliot Blennerhassett 14-12 RD2WR = 4
839719f82d3SEliot Blennerhassett 11-10 RD2DEAC = 1
840719f82d3SEliot Blennerhassett 9 RD2RD = 1
841719f82d3SEliot Blennerhassett 8-7 THZP = 10b
842719f82d3SEliot Blennerhassett 6-5 TWR = 2-1 = 01b (tWR = 10ns)
843719f82d3SEliot Blennerhassett 4 TRRD = 0b = 2 ECLK (tRRD = 14ns)
844719f82d3SEliot Blennerhassett 3-1 TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK)
845719f82d3SEliot Blennerhassett 1 CAS latency = 3 ECLK
846719f82d3SEliot Blennerhassett (for Micron 2M32-7 operating at 100Mhz)
847719f82d3SEliot Blennerhassett */
848719f82d3SEliot Blennerhassett
849719f82d3SEliot Blennerhassett /* need to use this else DSP code crashes */
850719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01800020, 0x001BDF29);
851719f82d3SEliot Blennerhassett
852719f82d3SEliot Blennerhassett /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
853719f82d3SEliot Blennerhassett 31 - -
854719f82d3SEliot Blennerhassett 30 SDBSZ 1 4 bank
855719f82d3SEliot Blennerhassett 29..28 SDRSZ 00 11 row address pins
856719f82d3SEliot Blennerhassett 27..26 SDCSZ 01 8 column address pins
857719f82d3SEliot Blennerhassett 25 RFEN 1 refersh enabled
858719f82d3SEliot Blennerhassett 24 INIT 1 init SDRAM
859719f82d3SEliot Blennerhassett 23..20 TRCD 0001
860719f82d3SEliot Blennerhassett 19..16 TRP 0001
861719f82d3SEliot Blennerhassett 15..12 TRC 0110
862719f82d3SEliot Blennerhassett 11..0 - -
863719f82d3SEliot Blennerhassett */
864719f82d3SEliot Blennerhassett /* need to use this else DSP code crashes */
865719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01800018, 0x47117000);
866719f82d3SEliot Blennerhassett
867719f82d3SEliot Blennerhassett /* EMIF SDRAM Refresh Timing */
868719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x0180001C, 0x00000410);
869719f82d3SEliot Blennerhassett
870719f82d3SEliot Blennerhassett /*MIF CE1 setup - Async peripherals
871719f82d3SEliot Blennerhassett @100MHz bus speed, each cycle is 10ns,
872719f82d3SEliot Blennerhassett 31..28 Wr setup = 1
873719f82d3SEliot Blennerhassett 27..22 Wr strobe = 3 30ns
874719f82d3SEliot Blennerhassett 21..20 Wr hold = 1
875719f82d3SEliot Blennerhassett 19..16 Rd setup =1
876719f82d3SEliot Blennerhassett 15..14 Ta = 2
877719f82d3SEliot Blennerhassett 13..8 Rd strobe = 3 30ns
878719f82d3SEliot Blennerhassett 7..4 MTYPE 0010 Async 32bits
879719f82d3SEliot Blennerhassett 3 Wr hold MSB =0
880719f82d3SEliot Blennerhassett 2..0 Rd hold = 1
881719f82d3SEliot Blennerhassett */
882719f82d3SEliot Blennerhassett {
883719f82d3SEliot Blennerhassett u32 cE1 =
884719f82d3SEliot Blennerhassett (1L << 28) | (3L << 22) | (1L << 20) | (1L <<
885719f82d3SEliot Blennerhassett 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L;
886719f82d3SEliot Blennerhassett hpi_write_word(pdo, 0x01800004, cE1);
887719f82d3SEliot Blennerhassett }
888719f82d3SEliot Blennerhassett
889719f82d3SEliot Blennerhassett /* delay a little to allow SDRAM and DSP to "get going" */
8903285ea10SEliot Blennerhassett hpios_delay_micro_seconds(1000);
891719f82d3SEliot Blennerhassett
892719f82d3SEliot Blennerhassett /* test access to SDRAM */
893719f82d3SEliot Blennerhassett {
894719f82d3SEliot Blennerhassett test_addr = 0x80000000;
895719f82d3SEliot Blennerhassett test_data = 0x00000001;
896719f82d3SEliot Blennerhassett /* test each bit in the 32bit word */
897719f82d3SEliot Blennerhassett for (j = 0; j < 32; j++) {
898719f82d3SEliot Blennerhassett hpi_write_word(pdo, test_addr, test_data);
899719f82d3SEliot Blennerhassett data = hpi_read_word(pdo, test_addr);
900719f82d3SEliot Blennerhassett if (data != test_data) {
901719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR,
902719f82d3SEliot Blennerhassett "DSP dram %x %x %x %x\n",
903719f82d3SEliot Blennerhassett test_addr, test_data, data,
904719f82d3SEliot Blennerhassett dsp_index);
905719f82d3SEliot Blennerhassett
906719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_SDRAM1;
907719f82d3SEliot Blennerhassett }
908719f82d3SEliot Blennerhassett test_data = test_data << 1;
909719f82d3SEliot Blennerhassett }
910719f82d3SEliot Blennerhassett /* test every Nth address in the DRAM */
911719f82d3SEliot Blennerhassett #define DRAM_SIZE_WORDS 0x200000 /*2_mx32 */
912719f82d3SEliot Blennerhassett #define DRAM_INC 1024
913719f82d3SEliot Blennerhassett test_addr = 0x80000000;
914719f82d3SEliot Blennerhassett test_data = 0x0;
915719f82d3SEliot Blennerhassett for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
916719f82d3SEliot Blennerhassett hpi_write_word(pdo, test_addr + i, test_data);
917719f82d3SEliot Blennerhassett test_data++;
918719f82d3SEliot Blennerhassett }
919719f82d3SEliot Blennerhassett test_addr = 0x80000000;
920719f82d3SEliot Blennerhassett test_data = 0x0;
921719f82d3SEliot Blennerhassett for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
922719f82d3SEliot Blennerhassett data = hpi_read_word(pdo, test_addr + i);
923719f82d3SEliot Blennerhassett if (data != test_data) {
924719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR,
925719f82d3SEliot Blennerhassett "DSP dram %x %x %x %x\n",
926719f82d3SEliot Blennerhassett test_addr + i, test_data,
927719f82d3SEliot Blennerhassett data, dsp_index);
928719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_SDRAM2;
929719f82d3SEliot Blennerhassett }
930719f82d3SEliot Blennerhassett test_data++;
931719f82d3SEliot Blennerhassett }
932719f82d3SEliot Blennerhassett
933719f82d3SEliot Blennerhassett }
934719f82d3SEliot Blennerhassett
935719f82d3SEliot Blennerhassett /* write the DSP code down into the DSPs memory */
93695a4c6e7SEliot Blennerhassett error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev,
93795a4c6e7SEliot Blennerhassett &dsp_code, pos_error_code);
938719f82d3SEliot Blennerhassett
939719f82d3SEliot Blennerhassett if (error)
940719f82d3SEliot Blennerhassett return error;
941719f82d3SEliot Blennerhassett
942719f82d3SEliot Blennerhassett while (1) {
943719f82d3SEliot Blennerhassett u32 length;
944719f82d3SEliot Blennerhassett u32 address;
945719f82d3SEliot Blennerhassett u32 type;
946719f82d3SEliot Blennerhassett u32 *pcode;
947719f82d3SEliot Blennerhassett
948719f82d3SEliot Blennerhassett error = hpi_dsp_code_read_word(&dsp_code, &length);
949719f82d3SEliot Blennerhassett if (error)
950719f82d3SEliot Blennerhassett break;
951719f82d3SEliot Blennerhassett if (length == 0xFFFFFFFF)
952719f82d3SEliot Blennerhassett break; /* end of code */
953719f82d3SEliot Blennerhassett
954719f82d3SEliot Blennerhassett error = hpi_dsp_code_read_word(&dsp_code, &address);
955719f82d3SEliot Blennerhassett if (error)
956719f82d3SEliot Blennerhassett break;
957719f82d3SEliot Blennerhassett error = hpi_dsp_code_read_word(&dsp_code, &type);
958719f82d3SEliot Blennerhassett if (error)
959719f82d3SEliot Blennerhassett break;
960719f82d3SEliot Blennerhassett error = hpi_dsp_code_read_block(length, &dsp_code,
961719f82d3SEliot Blennerhassett &pcode);
962719f82d3SEliot Blennerhassett if (error)
963719f82d3SEliot Blennerhassett break;
964719f82d3SEliot Blennerhassett error = hpi6000_dsp_block_write32(pao, (u16)dsp_index,
965719f82d3SEliot Blennerhassett address, pcode, length);
966719f82d3SEliot Blennerhassett if (error)
967719f82d3SEliot Blennerhassett break;
968719f82d3SEliot Blennerhassett }
969719f82d3SEliot Blennerhassett
970719f82d3SEliot Blennerhassett if (error) {
971719f82d3SEliot Blennerhassett hpi_dsp_code_close(&dsp_code);
972719f82d3SEliot Blennerhassett return error;
973719f82d3SEliot Blennerhassett }
974719f82d3SEliot Blennerhassett /* verify that code was written correctly */
975719f82d3SEliot Blennerhassett /* this time through, assume no errors in DSP code file/array */
976719f82d3SEliot Blennerhassett hpi_dsp_code_rewind(&dsp_code);
977719f82d3SEliot Blennerhassett while (1) {
978719f82d3SEliot Blennerhassett u32 length;
979719f82d3SEliot Blennerhassett u32 address;
980719f82d3SEliot Blennerhassett u32 type;
981719f82d3SEliot Blennerhassett u32 *pcode;
982719f82d3SEliot Blennerhassett
983719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &length);
984719f82d3SEliot Blennerhassett if (length == 0xFFFFFFFF)
985719f82d3SEliot Blennerhassett break; /* end of code */
986719f82d3SEliot Blennerhassett
987719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &address);
988719f82d3SEliot Blennerhassett hpi_dsp_code_read_word(&dsp_code, &type);
989719f82d3SEliot Blennerhassett hpi_dsp_code_read_block(length, &dsp_code, &pcode);
990719f82d3SEliot Blennerhassett
991719f82d3SEliot Blennerhassett for (i = 0; i < length; i++) {
992719f82d3SEliot Blennerhassett data = hpi_read_word(pdo, address);
993719f82d3SEliot Blennerhassett if (data != *pcode) {
994719f82d3SEliot Blennerhassett error = HPI6000_ERROR_INIT_VERIFY;
995719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR,
996719f82d3SEliot Blennerhassett "DSP verify %x %x %x %x\n",
997719f82d3SEliot Blennerhassett address, *pcode, data,
998719f82d3SEliot Blennerhassett dsp_index);
999719f82d3SEliot Blennerhassett break;
1000719f82d3SEliot Blennerhassett }
1001719f82d3SEliot Blennerhassett pcode++;
1002719f82d3SEliot Blennerhassett address += 4;
1003719f82d3SEliot Blennerhassett }
1004719f82d3SEliot Blennerhassett if (error)
1005719f82d3SEliot Blennerhassett break;
1006719f82d3SEliot Blennerhassett }
1007719f82d3SEliot Blennerhassett hpi_dsp_code_close(&dsp_code);
1008719f82d3SEliot Blennerhassett if (error)
1009719f82d3SEliot Blennerhassett return error;
1010719f82d3SEliot Blennerhassett
1011719f82d3SEliot Blennerhassett /* zero out the hostmailbox */
1012719f82d3SEliot Blennerhassett {
1013719f82d3SEliot Blennerhassett u32 address = HPI_HIF_ADDR(host_cmd);
1014719f82d3SEliot Blennerhassett for (i = 0; i < 4; i++) {
1015719f82d3SEliot Blennerhassett hpi_write_word(pdo, address, 0);
1016719f82d3SEliot Blennerhassett address += 4;
1017719f82d3SEliot Blennerhassett }
1018719f82d3SEliot Blennerhassett }
1019719f82d3SEliot Blennerhassett /* write the DSP number into the hostmailbox */
1020719f82d3SEliot Blennerhassett /* structure before starting the DSP */
1021719f82d3SEliot Blennerhassett hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index);
1022719f82d3SEliot Blennerhassett
1023719f82d3SEliot Blennerhassett /* write the DSP adapter Info into the */
1024719f82d3SEliot Blennerhassett /* hostmailbox before starting the DSP */
1025719f82d3SEliot Blennerhassett if (dsp_index > 0)
1026719f82d3SEliot Blennerhassett hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info),
1027719f82d3SEliot Blennerhassett adapter_info);
1028719f82d3SEliot Blennerhassett
1029719f82d3SEliot Blennerhassett /* step 3. Start code by sending interrupt */
1030719f82d3SEliot Blennerhassett iowrite32(0x00030003, pdo->prHPI_control);
10313285ea10SEliot Blennerhassett hpios_delay_micro_seconds(10000);
1032719f82d3SEliot Blennerhassett
1033719f82d3SEliot Blennerhassett /* wait for a non-zero value in hostcmd -
1034719f82d3SEliot Blennerhassett * indicating initialization is complete
1035719f82d3SEliot Blennerhassett *
1036719f82d3SEliot Blennerhassett * Init could take a while if DSP checks SDRAM memory
1037719f82d3SEliot Blennerhassett * Was 200000. Increased to 2000000 for ASI8801 so we
1038719f82d3SEliot Blennerhassett * don't get 938 errors.
1039719f82d3SEliot Blennerhassett */
1040719f82d3SEliot Blennerhassett timeout = 2000000;
1041719f82d3SEliot Blennerhassett while (timeout) {
1042719f82d3SEliot Blennerhassett do {
1043719f82d3SEliot Blennerhassett read = hpi_read_word(pdo,
1044719f82d3SEliot Blennerhassett HPI_HIF_ADDR(host_cmd));
1045719f82d3SEliot Blennerhassett } while (--timeout
1046719f82d3SEliot Blennerhassett && hpi6000_check_PCI2040_error_flag(pao,
1047719f82d3SEliot Blennerhassett H6READ));
1048719f82d3SEliot Blennerhassett
1049719f82d3SEliot Blennerhassett if (read)
1050719f82d3SEliot Blennerhassett break;
1051719f82d3SEliot Blennerhassett /* The following is a workaround for bug #94:
1052719f82d3SEliot Blennerhassett * Bluescreen on install and subsequent boots on a
1053719f82d3SEliot Blennerhassett * DELL PowerEdge 600SC PC with 1.8GHz P4 and
1054719f82d3SEliot Blennerhassett * ServerWorks chipset. Without this delay the system
1055719f82d3SEliot Blennerhassett * locks up with a bluescreen (NOT GPF or pagefault).
1056719f82d3SEliot Blennerhassett */
1057719f82d3SEliot Blennerhassett else
10583285ea10SEliot Blennerhassett hpios_delay_micro_seconds(10000);
1059719f82d3SEliot Blennerhassett }
1060719f82d3SEliot Blennerhassett if (timeout == 0)
1061719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_NOACK;
1062719f82d3SEliot Blennerhassett
1063719f82d3SEliot Blennerhassett /* read the DSP adapter Info from the */
1064719f82d3SEliot Blennerhassett /* hostmailbox structure after starting the DSP */
1065719f82d3SEliot Blennerhassett if (dsp_index == 0) {
1066719f82d3SEliot Blennerhassett /*u32 dwTestData=0; */
1067719f82d3SEliot Blennerhassett u32 mask = 0;
1068719f82d3SEliot Blennerhassett
1069719f82d3SEliot Blennerhassett adapter_info =
1070719f82d3SEliot Blennerhassett hpi_read_word(pdo,
1071719f82d3SEliot Blennerhassett HPI_HIF_ADDR(adapter_info));
1072719f82d3SEliot Blennerhassett if (HPI_ADAPTER_FAMILY_ASI
1073719f82d3SEliot Blennerhassett (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER
1074719f82d3SEliot Blennerhassett (adapter_info)) ==
1075719f82d3SEliot Blennerhassett HPI_ADAPTER_FAMILY_ASI(0x6200))
1076719f82d3SEliot Blennerhassett /* all 6200 cards have this many DSPs */
1077719f82d3SEliot Blennerhassett phw->num_dsp = 2;
1078719f82d3SEliot Blennerhassett
1079719f82d3SEliot Blennerhassett /* test that the PLD is programmed */
1080719f82d3SEliot Blennerhassett /* and we can read/write 24bits */
1081719f82d3SEliot Blennerhassett #define PLD_BASE_ADDRESS 0x90000000L /*for ASI6100/6200/8800 */
1082719f82d3SEliot Blennerhassett
1083719f82d3SEliot Blennerhassett switch (boot_load_family) {
1084719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x6200):
1085719f82d3SEliot Blennerhassett /* ASI6100/6200 has 24bit path to FPGA */
1086719f82d3SEliot Blennerhassett mask = 0xFFFFFF00L;
1087719f82d3SEliot Blennerhassett /* ASI5100 uses AX6 code, */
1088719f82d3SEliot Blennerhassett /* but has no PLD r/w register to test */
10893285ea10SEliot Blennerhassett if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
10903285ea10SEliot Blennerhassett subsystem_device) ==
1091719f82d3SEliot Blennerhassett HPI_ADAPTER_FAMILY_ASI(0x5100))
1092719f82d3SEliot Blennerhassett mask = 0x00000000L;
109338439146SEliot Blennerhassett /* ASI5200 uses AX6 code, */
109438439146SEliot Blennerhassett /* but has no PLD r/w register to test */
10953285ea10SEliot Blennerhassett if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
10963285ea10SEliot Blennerhassett subsystem_device) ==
109738439146SEliot Blennerhassett HPI_ADAPTER_FAMILY_ASI(0x5200))
109838439146SEliot Blennerhassett mask = 0x00000000L;
1099719f82d3SEliot Blennerhassett break;
1100719f82d3SEliot Blennerhassett case HPI_ADAPTER_FAMILY_ASI(0x8800):
1101719f82d3SEliot Blennerhassett /* ASI8800 has 16bit path to FPGA */
1102719f82d3SEliot Blennerhassett mask = 0xFFFF0000L;
1103719f82d3SEliot Blennerhassett break;
1104719f82d3SEliot Blennerhassett }
1105719f82d3SEliot Blennerhassett test_data = 0xAAAAAA00L & mask;
1106719f82d3SEliot Blennerhassett /* write to 24 bit Debug register (D31-D8) */
1107719f82d3SEliot Blennerhassett hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1108719f82d3SEliot Blennerhassett read = hpi_read_word(pdo,
1109719f82d3SEliot Blennerhassett PLD_BASE_ADDRESS + 4L) & mask;
1110719f82d3SEliot Blennerhassett if (read != test_data) {
1111719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1112719f82d3SEliot Blennerhassett read);
1113719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_PLDTEST1;
1114719f82d3SEliot Blennerhassett }
1115719f82d3SEliot Blennerhassett test_data = 0x55555500L & mask;
1116719f82d3SEliot Blennerhassett hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1117719f82d3SEliot Blennerhassett read = hpi_read_word(pdo,
1118719f82d3SEliot Blennerhassett PLD_BASE_ADDRESS + 4L) & mask;
1119719f82d3SEliot Blennerhassett if (read != test_data) {
1120719f82d3SEliot Blennerhassett HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1121719f82d3SEliot Blennerhassett read);
1122719f82d3SEliot Blennerhassett return HPI6000_ERROR_INIT_PLDTEST2;
1123719f82d3SEliot Blennerhassett }
1124719f82d3SEliot Blennerhassett }
1125719f82d3SEliot Blennerhassett } /* for numDSP */
1126719f82d3SEliot Blennerhassett return 0;
1127719f82d3SEliot Blennerhassett }
1128719f82d3SEliot Blennerhassett
1129719f82d3SEliot Blennerhassett #define PCI_TIMEOUT 100
1130719f82d3SEliot Blennerhassett
hpi_set_address(struct dsp_obj * pdo,u32 address)1131719f82d3SEliot Blennerhassett static int hpi_set_address(struct dsp_obj *pdo, u32 address)
1132719f82d3SEliot Blennerhassett {
1133719f82d3SEliot Blennerhassett u32 timeout = PCI_TIMEOUT;
1134719f82d3SEliot Blennerhassett
1135719f82d3SEliot Blennerhassett do {
1136719f82d3SEliot Blennerhassett iowrite32(address, pdo->prHPI_address);
1137719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter,
1138719f82d3SEliot Blennerhassett H6WRITE)
1139719f82d3SEliot Blennerhassett && --timeout);
1140719f82d3SEliot Blennerhassett
1141719f82d3SEliot Blennerhassett if (timeout)
1142719f82d3SEliot Blennerhassett return 0;
1143719f82d3SEliot Blennerhassett
1144719f82d3SEliot Blennerhassett return 1;
1145719f82d3SEliot Blennerhassett }
1146719f82d3SEliot Blennerhassett
1147719f82d3SEliot Blennerhassett /* write one word to the HPI port */
hpi_write_word(struct dsp_obj * pdo,u32 address,u32 data)1148719f82d3SEliot Blennerhassett static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data)
1149719f82d3SEliot Blennerhassett {
1150719f82d3SEliot Blennerhassett if (hpi_set_address(pdo, address))
1151719f82d3SEliot Blennerhassett return;
1152719f82d3SEliot Blennerhassett iowrite32(data, pdo->prHPI_data);
1153719f82d3SEliot Blennerhassett }
1154719f82d3SEliot Blennerhassett
1155719f82d3SEliot Blennerhassett /* read one word from the HPI port */
hpi_read_word(struct dsp_obj * pdo,u32 address)1156719f82d3SEliot Blennerhassett static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
1157719f82d3SEliot Blennerhassett {
1158719f82d3SEliot Blennerhassett u32 data = 0;
1159719f82d3SEliot Blennerhassett
1160719f82d3SEliot Blennerhassett if (hpi_set_address(pdo, address))
11613285ea10SEliot Blennerhassett return 0; /*? No way to return error */
1162719f82d3SEliot Blennerhassett
1163719f82d3SEliot Blennerhassett /* take care of errata in revB DSP (2.0.1) */
1164719f82d3SEliot Blennerhassett data = ioread32(pdo->prHPI_data);
1165719f82d3SEliot Blennerhassett return data;
1166719f82d3SEliot Blennerhassett }
1167719f82d3SEliot Blennerhassett
1168719f82d3SEliot Blennerhassett /* write a block of 32bit words to the DSP HPI port using auto-inc mode */
hpi_write_block(struct dsp_obj * pdo,u32 address,u32 * pdata,u32 length)1169719f82d3SEliot Blennerhassett static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1170719f82d3SEliot Blennerhassett u32 length)
1171719f82d3SEliot Blennerhassett {
1172719f82d3SEliot Blennerhassett u16 length16 = length - 1;
1173719f82d3SEliot Blennerhassett
1174719f82d3SEliot Blennerhassett if (length == 0)
1175719f82d3SEliot Blennerhassett return;
1176719f82d3SEliot Blennerhassett
1177719f82d3SEliot Blennerhassett if (hpi_set_address(pdo, address))
1178719f82d3SEliot Blennerhassett return;
1179719f82d3SEliot Blennerhassett
1180719f82d3SEliot Blennerhassett iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1181719f82d3SEliot Blennerhassett
1182719f82d3SEliot Blennerhassett /* take care of errata in revB DSP (2.0.1) */
1183719f82d3SEliot Blennerhassett /* must end with non auto-inc */
1184719f82d3SEliot Blennerhassett iowrite32(*(pdata + length - 1), pdo->prHPI_data);
1185719f82d3SEliot Blennerhassett }
1186719f82d3SEliot Blennerhassett
1187719f82d3SEliot Blennerhassett /** read a block of 32bit words from the DSP HPI port using auto-inc mode
1188719f82d3SEliot Blennerhassett */
hpi_read_block(struct dsp_obj * pdo,u32 address,u32 * pdata,u32 length)1189719f82d3SEliot Blennerhassett static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1190719f82d3SEliot Blennerhassett u32 length)
1191719f82d3SEliot Blennerhassett {
1192719f82d3SEliot Blennerhassett u16 length16 = length - 1;
1193719f82d3SEliot Blennerhassett
1194719f82d3SEliot Blennerhassett if (length == 0)
1195719f82d3SEliot Blennerhassett return;
1196719f82d3SEliot Blennerhassett
1197719f82d3SEliot Blennerhassett if (hpi_set_address(pdo, address))
1198719f82d3SEliot Blennerhassett return;
1199719f82d3SEliot Blennerhassett
1200719f82d3SEliot Blennerhassett ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1201719f82d3SEliot Blennerhassett
1202719f82d3SEliot Blennerhassett /* take care of errata in revB DSP (2.0.1) */
1203719f82d3SEliot Blennerhassett /* must end with non auto-inc */
1204719f82d3SEliot Blennerhassett *(pdata + length - 1) = ioread32(pdo->prHPI_data);
1205719f82d3SEliot Blennerhassett }
1206719f82d3SEliot Blennerhassett
hpi6000_dsp_block_write32(struct hpi_adapter_obj * pao,u16 dsp_index,u32 hpi_address,u32 * source,u32 count)1207719f82d3SEliot Blennerhassett static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
1208719f82d3SEliot Blennerhassett u16 dsp_index, u32 hpi_address, u32 *source, u32 count)
1209719f82d3SEliot Blennerhassett {
12107036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
12117036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1212719f82d3SEliot Blennerhassett u32 time_out = PCI_TIMEOUT;
1213719f82d3SEliot Blennerhassett int c6711_burst_size = 128;
1214719f82d3SEliot Blennerhassett u32 local_hpi_address = hpi_address;
1215719f82d3SEliot Blennerhassett int local_count = count;
1216719f82d3SEliot Blennerhassett int xfer_size;
1217719f82d3SEliot Blennerhassett u32 *pdata = source;
1218719f82d3SEliot Blennerhassett
1219719f82d3SEliot Blennerhassett while (local_count) {
1220719f82d3SEliot Blennerhassett if (local_count > c6711_burst_size)
1221719f82d3SEliot Blennerhassett xfer_size = c6711_burst_size;
1222719f82d3SEliot Blennerhassett else
1223719f82d3SEliot Blennerhassett xfer_size = local_count;
1224719f82d3SEliot Blennerhassett
1225719f82d3SEliot Blennerhassett time_out = PCI_TIMEOUT;
1226719f82d3SEliot Blennerhassett do {
1227719f82d3SEliot Blennerhassett hpi_write_block(pdo, local_hpi_address, pdata,
1228719f82d3SEliot Blennerhassett xfer_size);
1229719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1230719f82d3SEliot Blennerhassett && --time_out);
1231719f82d3SEliot Blennerhassett
1232719f82d3SEliot Blennerhassett if (!time_out)
1233719f82d3SEliot Blennerhassett break;
1234719f82d3SEliot Blennerhassett pdata += xfer_size;
1235719f82d3SEliot Blennerhassett local_hpi_address += sizeof(u32) * xfer_size;
1236719f82d3SEliot Blennerhassett local_count -= xfer_size;
1237719f82d3SEliot Blennerhassett }
1238719f82d3SEliot Blennerhassett
1239719f82d3SEliot Blennerhassett if (time_out)
1240719f82d3SEliot Blennerhassett return 0;
1241719f82d3SEliot Blennerhassett else
1242719f82d3SEliot Blennerhassett return 1;
1243719f82d3SEliot Blennerhassett }
1244719f82d3SEliot Blennerhassett
hpi6000_dsp_block_read32(struct hpi_adapter_obj * pao,u16 dsp_index,u32 hpi_address,u32 * dest,u32 count)1245719f82d3SEliot Blennerhassett static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
1246719f82d3SEliot Blennerhassett u16 dsp_index, u32 hpi_address, u32 *dest, u32 count)
1247719f82d3SEliot Blennerhassett {
12487036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
12497036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1250719f82d3SEliot Blennerhassett u32 time_out = PCI_TIMEOUT;
1251719f82d3SEliot Blennerhassett int c6711_burst_size = 16;
1252719f82d3SEliot Blennerhassett u32 local_hpi_address = hpi_address;
1253719f82d3SEliot Blennerhassett int local_count = count;
1254719f82d3SEliot Blennerhassett int xfer_size;
1255719f82d3SEliot Blennerhassett u32 *pdata = dest;
1256719f82d3SEliot Blennerhassett
1257719f82d3SEliot Blennerhassett while (local_count) {
1258719f82d3SEliot Blennerhassett if (local_count > c6711_burst_size)
1259719f82d3SEliot Blennerhassett xfer_size = c6711_burst_size;
1260719f82d3SEliot Blennerhassett else
1261719f82d3SEliot Blennerhassett xfer_size = local_count;
1262719f82d3SEliot Blennerhassett
1263719f82d3SEliot Blennerhassett time_out = PCI_TIMEOUT;
1264719f82d3SEliot Blennerhassett do {
1265719f82d3SEliot Blennerhassett hpi_read_block(pdo, local_hpi_address, pdata,
1266719f82d3SEliot Blennerhassett xfer_size);
1267719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1268719f82d3SEliot Blennerhassett && --time_out);
1269719f82d3SEliot Blennerhassett if (!time_out)
1270719f82d3SEliot Blennerhassett break;
1271719f82d3SEliot Blennerhassett
1272719f82d3SEliot Blennerhassett pdata += xfer_size;
1273719f82d3SEliot Blennerhassett local_hpi_address += sizeof(u32) * xfer_size;
1274719f82d3SEliot Blennerhassett local_count -= xfer_size;
1275719f82d3SEliot Blennerhassett }
1276719f82d3SEliot Blennerhassett
1277719f82d3SEliot Blennerhassett if (time_out)
1278719f82d3SEliot Blennerhassett return 0;
1279719f82d3SEliot Blennerhassett else
1280719f82d3SEliot Blennerhassett return 1;
1281719f82d3SEliot Blennerhassett }
1282719f82d3SEliot Blennerhassett
hpi6000_message_response_sequence(struct hpi_adapter_obj * pao,u16 dsp_index,struct hpi_message * phm,struct hpi_response * phr)1283719f82d3SEliot Blennerhassett static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
1284719f82d3SEliot Blennerhassett u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr)
1285719f82d3SEliot Blennerhassett {
12867036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
1287719f82d3SEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1288719f82d3SEliot Blennerhassett u32 timeout;
1289719f82d3SEliot Blennerhassett u16 ack;
1290719f82d3SEliot Blennerhassett u32 address;
1291719f82d3SEliot Blennerhassett u32 length;
1292719f82d3SEliot Blennerhassett u32 *p_data;
1293719f82d3SEliot Blennerhassett u16 error = 0;
1294719f82d3SEliot Blennerhassett
1295719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1296719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK) {
1297719f82d3SEliot Blennerhassett pao->dsp_crashed++;
1298719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT;
1299719f82d3SEliot Blennerhassett }
1300719f82d3SEliot Blennerhassett pao->dsp_crashed = 0;
1301719f82d3SEliot Blennerhassett
13023285ea10SEliot Blennerhassett /* get the message address and size */
1303719f82d3SEliot Blennerhassett if (phw->message_buffer_address_on_dsp == 0) {
1304719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1305719f82d3SEliot Blennerhassett do {
1306719f82d3SEliot Blennerhassett address =
1307719f82d3SEliot Blennerhassett hpi_read_word(pdo,
1308719f82d3SEliot Blennerhassett HPI_HIF_ADDR(message_buffer_address));
1309719f82d3SEliot Blennerhassett phw->message_buffer_address_on_dsp = address;
1310719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1311719f82d3SEliot Blennerhassett && --timeout);
1312719f82d3SEliot Blennerhassett if (!timeout)
1313719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_GET_ADR;
1314719f82d3SEliot Blennerhassett } else
1315719f82d3SEliot Blennerhassett address = phw->message_buffer_address_on_dsp;
1316719f82d3SEliot Blennerhassett
1317719f82d3SEliot Blennerhassett length = phm->size;
1318719f82d3SEliot Blennerhassett
13193285ea10SEliot Blennerhassett /* send the message */
1320719f82d3SEliot Blennerhassett p_data = (u32 *)phm;
1321719f82d3SEliot Blennerhassett if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
1322719f82d3SEliot Blennerhassett (u16)length / 4))
1323719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32;
1324719f82d3SEliot Blennerhassett
1325719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP))
1326719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_GETRESPCMD;
1327719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1328719f82d3SEliot Blennerhassett
1329719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP);
1330719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1331719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
1332719f82d3SEliot Blennerhassett
13333285ea10SEliot Blennerhassett /* get the response address */
1334719f82d3SEliot Blennerhassett if (phw->response_buffer_address_on_dsp == 0) {
1335719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1336719f82d3SEliot Blennerhassett do {
1337719f82d3SEliot Blennerhassett address =
1338719f82d3SEliot Blennerhassett hpi_read_word(pdo,
1339719f82d3SEliot Blennerhassett HPI_HIF_ADDR(response_buffer_address));
1340719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1341719f82d3SEliot Blennerhassett && --timeout);
1342719f82d3SEliot Blennerhassett phw->response_buffer_address_on_dsp = address;
1343719f82d3SEliot Blennerhassett
1344719f82d3SEliot Blennerhassett if (!timeout)
1345719f82d3SEliot Blennerhassett return HPI6000_ERROR_RESP_GET_ADR;
1346719f82d3SEliot Blennerhassett } else
1347719f82d3SEliot Blennerhassett address = phw->response_buffer_address_on_dsp;
1348719f82d3SEliot Blennerhassett
1349719f82d3SEliot Blennerhassett /* read the length of the response back from the DSP */
1350719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1351719f82d3SEliot Blennerhassett do {
1352719f82d3SEliot Blennerhassett length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1353719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1354719f82d3SEliot Blennerhassett if (!timeout)
13550d02e129SEliot Blennerhassett return HPI6000_ERROR_RESP_GET_LEN;
13560d02e129SEliot Blennerhassett
13570d02e129SEliot Blennerhassett if (length > phr->size)
13580d02e129SEliot Blennerhassett return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
1359719f82d3SEliot Blennerhassett
13603285ea10SEliot Blennerhassett /* get the response */
1361719f82d3SEliot Blennerhassett p_data = (u32 *)phr;
1362719f82d3SEliot Blennerhassett if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
1363719f82d3SEliot Blennerhassett (u16)length / 4))
1364719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_BLOCKREAD32;
1365719f82d3SEliot Blennerhassett
1366719f82d3SEliot Blennerhassett /* set i/f back to idle */
1367719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1368719f82d3SEliot Blennerhassett return HPI6000_ERROR_MSG_RESP_IDLECMD;
1369719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1370719f82d3SEliot Blennerhassett
1371719f82d3SEliot Blennerhassett error = hpi_validate_response(phm, phr);
1372719f82d3SEliot Blennerhassett return error;
1373719f82d3SEliot Blennerhassett }
1374719f82d3SEliot Blennerhassett
1375719f82d3SEliot Blennerhassett /* have to set up the below defines to match stuff in the MAP file */
1376719f82d3SEliot Blennerhassett
1377719f82d3SEliot Blennerhassett #define MSG_ADDRESS (HPI_HIF_BASE+0x18)
1378719f82d3SEliot Blennerhassett #define MSG_LENGTH 11
1379719f82d3SEliot Blennerhassett #define RESP_ADDRESS (HPI_HIF_BASE+0x44)
1380719f82d3SEliot Blennerhassett #define RESP_LENGTH 16
1381719f82d3SEliot Blennerhassett #define QUEUE_START (HPI_HIF_BASE+0x88)
1382719f82d3SEliot Blennerhassett #define QUEUE_SIZE 0x8000
1383719f82d3SEliot Blennerhassett
hpi6000_send_data_check_adr(u32 address,u32 length_in_dwords)1384719f82d3SEliot Blennerhassett static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords)
1385719f82d3SEliot Blennerhassett {
1386719f82d3SEliot Blennerhassett /*#define CHECKING // comment this line in to enable checking */
1387719f82d3SEliot Blennerhassett #ifdef CHECKING
1388719f82d3SEliot Blennerhassett if (address < (u32)MSG_ADDRESS)
1389719f82d3SEliot Blennerhassett return 0;
1390719f82d3SEliot Blennerhassett if (address > (u32)(QUEUE_START + QUEUE_SIZE))
1391719f82d3SEliot Blennerhassett return 0;
1392719f82d3SEliot Blennerhassett if ((address + (length_in_dwords << 2)) >
1393719f82d3SEliot Blennerhassett (u32)(QUEUE_START + QUEUE_SIZE))
1394719f82d3SEliot Blennerhassett return 0;
1395719f82d3SEliot Blennerhassett #else
1396719f82d3SEliot Blennerhassett (void)address;
1397719f82d3SEliot Blennerhassett (void)length_in_dwords;
1398719f82d3SEliot Blennerhassett return 1;
1399719f82d3SEliot Blennerhassett #endif
1400719f82d3SEliot Blennerhassett }
1401719f82d3SEliot Blennerhassett
hpi6000_send_data(struct hpi_adapter_obj * pao,u16 dsp_index,struct hpi_message * phm,struct hpi_response * phr)1402719f82d3SEliot Blennerhassett static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1403719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
1404719f82d3SEliot Blennerhassett {
14057036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
14067036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1407719f82d3SEliot Blennerhassett u32 data_sent = 0;
1408719f82d3SEliot Blennerhassett u16 ack;
1409719f82d3SEliot Blennerhassett u32 length, address;
1410719f82d3SEliot Blennerhassett u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1411719f82d3SEliot Blennerhassett u16 time_out = 8;
1412719f82d3SEliot Blennerhassett
1413719f82d3SEliot Blennerhassett (void)phr;
1414719f82d3SEliot Blennerhassett
1415719f82d3SEliot Blennerhassett /* round dwDataSize down to nearest 4 bytes */
1416719f82d3SEliot Blennerhassett while ((data_sent < (phm->u.d.u.data.data_size & ~3L))
1417719f82d3SEliot Blennerhassett && --time_out) {
1418719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1419719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1420719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT;
1421719f82d3SEliot Blennerhassett
1422719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index,
1423719f82d3SEliot Blennerhassett HPI_HIF_SEND_DATA))
1424719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_CMD;
1425719f82d3SEliot Blennerhassett
1426719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1427719f82d3SEliot Blennerhassett
1428719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA);
1429719f82d3SEliot Blennerhassett
1430719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1431719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_ACK;
1432719f82d3SEliot Blennerhassett
1433719f82d3SEliot Blennerhassett do {
1434719f82d3SEliot Blennerhassett /* get the address and size */
1435719f82d3SEliot Blennerhassett address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1436719f82d3SEliot Blennerhassett /* DSP returns number of DWORDS */
1437719f82d3SEliot Blennerhassett length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1438719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1439719f82d3SEliot Blennerhassett
1440719f82d3SEliot Blennerhassett if (!hpi6000_send_data_check_adr(address, length))
1441719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_ADR;
1442719f82d3SEliot Blennerhassett
1443719f82d3SEliot Blennerhassett /* send the data. break data into 512 DWORD blocks (2K bytes)
1444719f82d3SEliot Blennerhassett * and send using block write. 2Kbytes is the max as this is the
1445719f82d3SEliot Blennerhassett * memory window given to the HPI data register by the PCI2040
1446719f82d3SEliot Blennerhassett */
1447719f82d3SEliot Blennerhassett
1448719f82d3SEliot Blennerhassett {
1449719f82d3SEliot Blennerhassett u32 len = length;
1450719f82d3SEliot Blennerhassett u32 blk_len = 512;
1451719f82d3SEliot Blennerhassett while (len) {
1452719f82d3SEliot Blennerhassett if (len < blk_len)
1453719f82d3SEliot Blennerhassett blk_len = len;
1454719f82d3SEliot Blennerhassett if (hpi6000_dsp_block_write32(pao, dsp_index,
1455719f82d3SEliot Blennerhassett address, p_data, blk_len))
1456719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_WRITE;
1457719f82d3SEliot Blennerhassett address += blk_len * 4;
1458719f82d3SEliot Blennerhassett p_data += blk_len;
1459719f82d3SEliot Blennerhassett len -= blk_len;
1460719f82d3SEliot Blennerhassett }
1461719f82d3SEliot Blennerhassett }
1462719f82d3SEliot Blennerhassett
1463719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1464719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_IDLECMD;
1465719f82d3SEliot Blennerhassett
1466719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1467719f82d3SEliot Blennerhassett
1468719f82d3SEliot Blennerhassett data_sent += length * 4;
1469719f82d3SEliot Blennerhassett }
1470719f82d3SEliot Blennerhassett if (!time_out)
1471719f82d3SEliot Blennerhassett return HPI6000_ERROR_SEND_DATA_TIMEOUT;
1472719f82d3SEliot Blennerhassett return 0;
1473719f82d3SEliot Blennerhassett }
1474719f82d3SEliot Blennerhassett
hpi6000_get_data(struct hpi_adapter_obj * pao,u16 dsp_index,struct hpi_message * phm,struct hpi_response * phr)1475719f82d3SEliot Blennerhassett static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1476719f82d3SEliot Blennerhassett struct hpi_message *phm, struct hpi_response *phr)
1477719f82d3SEliot Blennerhassett {
14787036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
14797036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1480719f82d3SEliot Blennerhassett u32 data_got = 0;
1481719f82d3SEliot Blennerhassett u16 ack;
1482719f82d3SEliot Blennerhassett u32 length, address;
1483719f82d3SEliot Blennerhassett u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1484719f82d3SEliot Blennerhassett
1485719f82d3SEliot Blennerhassett (void)phr; /* this parameter not used! */
1486719f82d3SEliot Blennerhassett
1487719f82d3SEliot Blennerhassett /* round dwDataSize down to nearest 4 bytes */
1488719f82d3SEliot Blennerhassett while (data_got < (phm->u.d.u.data.data_size & ~3L)) {
1489719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1490719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1491719f82d3SEliot Blennerhassett return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT;
1492719f82d3SEliot Blennerhassett
1493719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index,
1494719f82d3SEliot Blennerhassett HPI_HIF_GET_DATA))
1495719f82d3SEliot Blennerhassett return HPI6000_ERROR_GET_DATA_CMD;
1496719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1497719f82d3SEliot Blennerhassett
1498719f82d3SEliot Blennerhassett ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA);
1499719f82d3SEliot Blennerhassett
1500719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1501719f82d3SEliot Blennerhassett return HPI6000_ERROR_GET_DATA_ACK;
1502719f82d3SEliot Blennerhassett
1503719f82d3SEliot Blennerhassett /* get the address and size */
1504719f82d3SEliot Blennerhassett do {
1505719f82d3SEliot Blennerhassett address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1506719f82d3SEliot Blennerhassett length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1507719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1508719f82d3SEliot Blennerhassett
1509719f82d3SEliot Blennerhassett /* read the data */
1510719f82d3SEliot Blennerhassett {
1511719f82d3SEliot Blennerhassett u32 len = length;
1512719f82d3SEliot Blennerhassett u32 blk_len = 512;
1513719f82d3SEliot Blennerhassett while (len) {
1514719f82d3SEliot Blennerhassett if (len < blk_len)
1515719f82d3SEliot Blennerhassett blk_len = len;
1516719f82d3SEliot Blennerhassett if (hpi6000_dsp_block_read32(pao, dsp_index,
1517719f82d3SEliot Blennerhassett address, p_data, blk_len))
1518719f82d3SEliot Blennerhassett return HPI6000_ERROR_GET_DATA_READ;
1519719f82d3SEliot Blennerhassett address += blk_len * 4;
1520719f82d3SEliot Blennerhassett p_data += blk_len;
1521719f82d3SEliot Blennerhassett len -= blk_len;
1522719f82d3SEliot Blennerhassett }
1523719f82d3SEliot Blennerhassett }
1524719f82d3SEliot Blennerhassett
1525719f82d3SEliot Blennerhassett if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1526719f82d3SEliot Blennerhassett return HPI6000_ERROR_GET_DATA_IDLECMD;
1527719f82d3SEliot Blennerhassett hpi6000_send_dsp_interrupt(pdo);
1528719f82d3SEliot Blennerhassett
1529719f82d3SEliot Blennerhassett data_got += length * 4;
1530719f82d3SEliot Blennerhassett }
1531719f82d3SEliot Blennerhassett return 0;
1532719f82d3SEliot Blennerhassett }
1533719f82d3SEliot Blennerhassett
hpi6000_send_dsp_interrupt(struct dsp_obj * pdo)1534719f82d3SEliot Blennerhassett static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo)
1535719f82d3SEliot Blennerhassett {
1536719f82d3SEliot Blennerhassett iowrite32(0x00030003, pdo->prHPI_control); /* DSPINT */
1537719f82d3SEliot Blennerhassett }
1538719f82d3SEliot Blennerhassett
hpi6000_send_host_command(struct hpi_adapter_obj * pao,u16 dsp_index,u32 host_cmd)1539719f82d3SEliot Blennerhassett static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
1540719f82d3SEliot Blennerhassett u16 dsp_index, u32 host_cmd)
1541719f82d3SEliot Blennerhassett {
15427036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
15437036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1544719f82d3SEliot Blennerhassett u32 timeout = TIMEOUT;
1545719f82d3SEliot Blennerhassett
1546719f82d3SEliot Blennerhassett /* set command */
1547719f82d3SEliot Blennerhassett do {
1548719f82d3SEliot Blennerhassett hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd);
1549719f82d3SEliot Blennerhassett /* flush the FIFO */
1550719f82d3SEliot Blennerhassett hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1551719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout);
1552719f82d3SEliot Blennerhassett
1553719f82d3SEliot Blennerhassett /* reset the interrupt bit */
1554719f82d3SEliot Blennerhassett iowrite32(0x00040004, pdo->prHPI_control);
1555719f82d3SEliot Blennerhassett
1556719f82d3SEliot Blennerhassett if (timeout)
1557719f82d3SEliot Blennerhassett return 0;
1558719f82d3SEliot Blennerhassett else
1559719f82d3SEliot Blennerhassett return 1;
1560719f82d3SEliot Blennerhassett }
1561719f82d3SEliot Blennerhassett
1562719f82d3SEliot Blennerhassett /* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */
hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj * pao,u16 read_or_write)1563719f82d3SEliot Blennerhassett static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
1564719f82d3SEliot Blennerhassett u16 read_or_write)
1565719f82d3SEliot Blennerhassett {
1566719f82d3SEliot Blennerhassett u32 hPI_error;
1567719f82d3SEliot Blennerhassett
15687036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
1569719f82d3SEliot Blennerhassett
1570719f82d3SEliot Blennerhassett /* read the error bits from the PCI2040 */
1571719f82d3SEliot Blennerhassett hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1572719f82d3SEliot Blennerhassett if (hPI_error) {
1573719f82d3SEliot Blennerhassett /* reset the error flag */
1574719f82d3SEliot Blennerhassett iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1575719f82d3SEliot Blennerhassett phw->pCI2040HPI_error_count++;
1576719f82d3SEliot Blennerhassett if (read_or_write == 1)
1577719f82d3SEliot Blennerhassett gw_pci_read_asserts++; /************* inc global */
1578719f82d3SEliot Blennerhassett else
1579719f82d3SEliot Blennerhassett gw_pci_write_asserts++;
1580719f82d3SEliot Blennerhassett return 1;
1581719f82d3SEliot Blennerhassett } else
1582719f82d3SEliot Blennerhassett return 0;
1583719f82d3SEliot Blennerhassett }
1584719f82d3SEliot Blennerhassett
hpi6000_wait_dsp_ack(struct hpi_adapter_obj * pao,u16 dsp_index,u32 ack_value)1585719f82d3SEliot Blennerhassett static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
1586719f82d3SEliot Blennerhassett u32 ack_value)
1587719f82d3SEliot Blennerhassett {
15887036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
15897036b92dSEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1590719f82d3SEliot Blennerhassett u32 ack = 0L;
1591719f82d3SEliot Blennerhassett u32 timeout;
1592719f82d3SEliot Blennerhassett u32 hPIC = 0L;
1593719f82d3SEliot Blennerhassett
1594719f82d3SEliot Blennerhassett /* wait for host interrupt to signal ack is ready */
1595719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1596719f82d3SEliot Blennerhassett while (--timeout) {
1597719f82d3SEliot Blennerhassett hPIC = ioread32(pdo->prHPI_control);
1598719f82d3SEliot Blennerhassett if (hPIC & 0x04) /* 0x04 = HINT from DSP */
1599719f82d3SEliot Blennerhassett break;
1600719f82d3SEliot Blennerhassett }
1601719f82d3SEliot Blennerhassett if (timeout == 0)
1602719f82d3SEliot Blennerhassett return HPI_HIF_ERROR_MASK;
1603719f82d3SEliot Blennerhassett
1604719f82d3SEliot Blennerhassett /* wait for dwAckValue */
1605719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1606719f82d3SEliot Blennerhassett while (--timeout) {
1607719f82d3SEliot Blennerhassett /* read the ack mailbox */
1608719f82d3SEliot Blennerhassett ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack));
1609719f82d3SEliot Blennerhassett if (ack == ack_value)
1610719f82d3SEliot Blennerhassett break;
1611719f82d3SEliot Blennerhassett if ((ack & HPI_HIF_ERROR_MASK)
1612719f82d3SEliot Blennerhassett && !hpi6000_check_PCI2040_error_flag(pao, H6READ))
1613719f82d3SEliot Blennerhassett break;
1614719f82d3SEliot Blennerhassett /*for (i=0;i<1000;i++) */
1615719f82d3SEliot Blennerhassett /* dwPause=i+1; */
1616719f82d3SEliot Blennerhassett }
1617719f82d3SEliot Blennerhassett if (ack & HPI_HIF_ERROR_MASK)
1618719f82d3SEliot Blennerhassett /* indicates bad read from DSP -
1619719f82d3SEliot Blennerhassett typically 0xffffff is read for some reason */
1620719f82d3SEliot Blennerhassett ack = HPI_HIF_ERROR_MASK;
1621719f82d3SEliot Blennerhassett
1622719f82d3SEliot Blennerhassett if (timeout == 0)
1623719f82d3SEliot Blennerhassett ack = HPI_HIF_ERROR_MASK;
1624719f82d3SEliot Blennerhassett return (short)ack;
1625719f82d3SEliot Blennerhassett }
1626719f82d3SEliot Blennerhassett
hpi6000_update_control_cache(struct hpi_adapter_obj * pao,struct hpi_message * phm)1627719f82d3SEliot Blennerhassett static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
1628719f82d3SEliot Blennerhassett struct hpi_message *phm)
1629719f82d3SEliot Blennerhassett {
1630719f82d3SEliot Blennerhassett const u16 dsp_index = 0;
16317036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
1632719f82d3SEliot Blennerhassett struct dsp_obj *pdo = &phw->ado[dsp_index];
1633719f82d3SEliot Blennerhassett u32 timeout;
1634719f82d3SEliot Blennerhassett u32 cache_dirty_flag;
1635719f82d3SEliot Blennerhassett u16 err;
1636719f82d3SEliot Blennerhassett
1637719f82d3SEliot Blennerhassett hpios_dsplock_lock(pao);
1638719f82d3SEliot Blennerhassett
1639719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1640719f82d3SEliot Blennerhassett do {
1641719f82d3SEliot Blennerhassett cache_dirty_flag =
1642719f82d3SEliot Blennerhassett hpi_read_word((struct dsp_obj *)pdo,
1643719f82d3SEliot Blennerhassett HPI_HIF_ADDR(control_cache_is_dirty));
1644719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1645719f82d3SEliot Blennerhassett if (!timeout) {
1646719f82d3SEliot Blennerhassett err = HPI6000_ERROR_CONTROL_CACHE_PARAMS;
1647719f82d3SEliot Blennerhassett goto unlock;
1648719f82d3SEliot Blennerhassett }
1649719f82d3SEliot Blennerhassett
1650719f82d3SEliot Blennerhassett if (cache_dirty_flag) {
1651719f82d3SEliot Blennerhassett /* read the cached controls */
1652719f82d3SEliot Blennerhassett u32 address;
1653719f82d3SEliot Blennerhassett u32 length;
1654719f82d3SEliot Blennerhassett
1655719f82d3SEliot Blennerhassett timeout = TIMEOUT;
1656719f82d3SEliot Blennerhassett if (pdo->control_cache_address_on_dsp == 0) {
1657719f82d3SEliot Blennerhassett do {
1658719f82d3SEliot Blennerhassett address =
1659719f82d3SEliot Blennerhassett hpi_read_word((struct dsp_obj *)pdo,
1660719f82d3SEliot Blennerhassett HPI_HIF_ADDR(control_cache_address));
1661719f82d3SEliot Blennerhassett
1662719f82d3SEliot Blennerhassett length = hpi_read_word((struct dsp_obj *)pdo,
1663719f82d3SEliot Blennerhassett HPI_HIF_ADDR
1664719f82d3SEliot Blennerhassett (control_cache_size_in_bytes));
1665719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1666719f82d3SEliot Blennerhassett && --timeout);
1667719f82d3SEliot Blennerhassett if (!timeout) {
1668719f82d3SEliot Blennerhassett err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN;
1669719f82d3SEliot Blennerhassett goto unlock;
1670719f82d3SEliot Blennerhassett }
1671719f82d3SEliot Blennerhassett pdo->control_cache_address_on_dsp = address;
1672719f82d3SEliot Blennerhassett pdo->control_cache_length_on_dsp = length;
1673719f82d3SEliot Blennerhassett } else {
1674719f82d3SEliot Blennerhassett address = pdo->control_cache_address_on_dsp;
1675719f82d3SEliot Blennerhassett length = pdo->control_cache_length_on_dsp;
1676719f82d3SEliot Blennerhassett }
1677719f82d3SEliot Blennerhassett
1678719f82d3SEliot Blennerhassett if (hpi6000_dsp_block_read32(pao, dsp_index, address,
1679719f82d3SEliot Blennerhassett (u32 *)&phw->control_cache[0],
1680719f82d3SEliot Blennerhassett length / sizeof(u32))) {
1681719f82d3SEliot Blennerhassett err = HPI6000_ERROR_CONTROL_CACHE_READ;
1682719f82d3SEliot Blennerhassett goto unlock;
1683719f82d3SEliot Blennerhassett }
1684719f82d3SEliot Blennerhassett do {
1685719f82d3SEliot Blennerhassett hpi_write_word((struct dsp_obj *)pdo,
1686719f82d3SEliot Blennerhassett HPI_HIF_ADDR(control_cache_is_dirty), 0);
1687719f82d3SEliot Blennerhassett /* flush the FIFO */
1688719f82d3SEliot Blennerhassett hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1689719f82d3SEliot Blennerhassett } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1690719f82d3SEliot Blennerhassett && --timeout);
1691719f82d3SEliot Blennerhassett if (!timeout) {
1692719f82d3SEliot Blennerhassett err = HPI6000_ERROR_CONTROL_CACHE_FLUSH;
1693719f82d3SEliot Blennerhassett goto unlock;
1694719f82d3SEliot Blennerhassett }
1695719f82d3SEliot Blennerhassett
1696719f82d3SEliot Blennerhassett }
1697719f82d3SEliot Blennerhassett err = 0;
1698719f82d3SEliot Blennerhassett
1699719f82d3SEliot Blennerhassett unlock:
1700719f82d3SEliot Blennerhassett hpios_dsplock_unlock(pao);
1701719f82d3SEliot Blennerhassett return err;
1702719f82d3SEliot Blennerhassett }
1703719f82d3SEliot Blennerhassett
1704719f82d3SEliot Blennerhassett /** Get dsp index for multi DSP adapters only */
get_dsp_index(struct hpi_adapter_obj * pao,struct hpi_message * phm)1705719f82d3SEliot Blennerhassett static u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm)
1706719f82d3SEliot Blennerhassett {
1707719f82d3SEliot Blennerhassett u16 ret = 0;
1708719f82d3SEliot Blennerhassett switch (phm->object) {
1709719f82d3SEliot Blennerhassett case HPI_OBJ_ISTREAM:
1710719f82d3SEliot Blennerhassett if (phm->obj_index < 2)
1711719f82d3SEliot Blennerhassett ret = 1;
1712719f82d3SEliot Blennerhassett break;
1713719f82d3SEliot Blennerhassett case HPI_OBJ_PROFILE:
1714719f82d3SEliot Blennerhassett ret = phm->obj_index;
1715719f82d3SEliot Blennerhassett break;
1716719f82d3SEliot Blennerhassett default:
1717719f82d3SEliot Blennerhassett break;
1718719f82d3SEliot Blennerhassett }
1719719f82d3SEliot Blennerhassett return ret;
1720719f82d3SEliot Blennerhassett }
1721719f82d3SEliot Blennerhassett
1722719f82d3SEliot Blennerhassett /** Complete transaction with DSP
1723719f82d3SEliot Blennerhassett
1724719f82d3SEliot Blennerhassett Send message, get response, send or get stream data if any.
1725719f82d3SEliot Blennerhassett */
hw_message(struct hpi_adapter_obj * pao,struct hpi_message * phm,struct hpi_response * phr)1726719f82d3SEliot Blennerhassett static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
1727719f82d3SEliot Blennerhassett struct hpi_response *phr)
1728719f82d3SEliot Blennerhassett {
1729719f82d3SEliot Blennerhassett u16 error = 0;
1730719f82d3SEliot Blennerhassett u16 dsp_index = 0;
17317036b92dSEliot Blennerhassett struct hpi_hw_obj *phw = pao->priv;
17327036b92dSEliot Blennerhassett u16 num_dsp = phw->num_dsp;
1733719f82d3SEliot Blennerhassett
1734719f82d3SEliot Blennerhassett if (num_dsp < 2)
1735719f82d3SEliot Blennerhassett dsp_index = 0;
1736719f82d3SEliot Blennerhassett else {
1737719f82d3SEliot Blennerhassett dsp_index = get_dsp_index(pao, phm);
1738719f82d3SEliot Blennerhassett
1739719f82d3SEliot Blennerhassett /* is this checked on the DSP anyway? */
1740719f82d3SEliot Blennerhassett if ((phm->function == HPI_ISTREAM_GROUP_ADD)
1741719f82d3SEliot Blennerhassett || (phm->function == HPI_OSTREAM_GROUP_ADD)) {
1742719f82d3SEliot Blennerhassett struct hpi_message hm;
1743719f82d3SEliot Blennerhassett u16 add_index;
1744719f82d3SEliot Blennerhassett hm.obj_index = phm->u.d.u.stream.stream_index;
1745719f82d3SEliot Blennerhassett hm.object = phm->u.d.u.stream.object_type;
1746719f82d3SEliot Blennerhassett add_index = get_dsp_index(pao, &hm);
1747719f82d3SEliot Blennerhassett if (add_index != dsp_index) {
1748719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_NO_INTERDSP_GROUPS;
1749719f82d3SEliot Blennerhassett return;
1750719f82d3SEliot Blennerhassett }
1751719f82d3SEliot Blennerhassett }
1752719f82d3SEliot Blennerhassett }
1753bca516bfSEliot Blennerhassett
1754bca516bfSEliot Blennerhassett hpios_dsplock_lock(pao);
1755719f82d3SEliot Blennerhassett error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
1756719f82d3SEliot Blennerhassett
17570a00044dSEliot Blennerhassett if (error) /* something failed in the HPI/DSP interface */
1758719f82d3SEliot Blennerhassett goto err;
1759719f82d3SEliot Blennerhassett
17600a00044dSEliot Blennerhassett if (phr->error) /* something failed in the DSP */
17610a00044dSEliot Blennerhassett goto out;
1762719f82d3SEliot Blennerhassett
1763719f82d3SEliot Blennerhassett switch (phm->function) {
1764719f82d3SEliot Blennerhassett case HPI_OSTREAM_WRITE:
1765719f82d3SEliot Blennerhassett case HPI_ISTREAM_ANC_WRITE:
1766719f82d3SEliot Blennerhassett error = hpi6000_send_data(pao, dsp_index, phm, phr);
1767719f82d3SEliot Blennerhassett break;
1768719f82d3SEliot Blennerhassett case HPI_ISTREAM_READ:
1769719f82d3SEliot Blennerhassett case HPI_OSTREAM_ANC_READ:
1770719f82d3SEliot Blennerhassett error = hpi6000_get_data(pao, dsp_index, phm, phr);
1771719f82d3SEliot Blennerhassett break;
1772719f82d3SEliot Blennerhassett case HPI_ADAPTER_GET_ASSERT:
17733285ea10SEliot Blennerhassett phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */
1774719f82d3SEliot Blennerhassett if (num_dsp == 2) {
17753285ea10SEliot Blennerhassett if (!phr->u.ax.assert.count) {
1776719f82d3SEliot Blennerhassett /* no assert from dsp 0, check dsp 1 */
1777719f82d3SEliot Blennerhassett error = hpi6000_message_response_sequence(pao,
1778719f82d3SEliot Blennerhassett 1, phm, phr);
17793285ea10SEliot Blennerhassett phr->u.ax.assert.dsp_index = 1;
1780719f82d3SEliot Blennerhassett }
1781719f82d3SEliot Blennerhassett }
1782719f82d3SEliot Blennerhassett }
1783719f82d3SEliot Blennerhassett
1784719f82d3SEliot Blennerhassett err:
17850a00044dSEliot Blennerhassett if (error) {
17860a00044dSEliot Blennerhassett if (error >= HPI_ERROR_BACKEND_BASE) {
17870a00044dSEliot Blennerhassett phr->error = HPI_ERROR_DSP_COMMUNICATION;
17880a00044dSEliot Blennerhassett phr->specific_error = error;
17890a00044dSEliot Blennerhassett } else {
17900a00044dSEliot Blennerhassett phr->error = error;
17910a00044dSEliot Blennerhassett }
17920a00044dSEliot Blennerhassett
17930a00044dSEliot Blennerhassett /* just the header of the response is valid */
17940a00044dSEliot Blennerhassett phr->size = sizeof(struct hpi_response_header);
17950a00044dSEliot Blennerhassett }
17960a00044dSEliot Blennerhassett out:
1797719f82d3SEliot Blennerhassett hpios_dsplock_unlock(pao);
1798719f82d3SEliot Blennerhassett return;
1799719f82d3SEliot Blennerhassett }
1800