Commit | Line | Data |
---|---|---|
635d2b00 GKH |
1 | /***************************************************************************** |
2 | ||
95edd09e | 3 | (c) Cambridge Silicon Radio Limited 2012 |
635d2b00 GKH |
4 | All rights reserved and confidential information of CSR |
5 | ||
6 | Refer to LICENSE.txt included with this source for details | |
7 | on the license terms. | |
8 | ||
9 | *****************************************************************************/ | |
10 | ||
11 | /* | |
12 | * --------------------------------------------------------------------------- | |
13 | * FILE: csr_wifi_hip_card_sdio_mem.c | |
14 | * | |
15 | * PURPOSE: Implementation of the Card API for SDIO. | |
16 | * | |
17 | * --------------------------------------------------------------------------- | |
18 | */ | |
19 | #include "csr_wifi_hip_unifi.h" | |
20 | #include "csr_wifi_hip_card.h" | |
21 | ||
22 | #define SDIO_RETRIES 3 | |
23 | #define CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH 16 | |
24 | ||
25 | ||
26 | #define retryable_sdio_error(_csrResult) (((_csrResult) == CSR_SDIO_RESULT_CRC_ERROR) || ((_csrResult) == CSR_SDIO_RESULT_TIMEOUT)) | |
27 | ||
28 | ||
29 | /* | |
30 | * --------------------------------------------------------------------------- | |
31 | * retrying_read8 | |
32 | * retrying_write8 | |
33 | * | |
34 | * These functions provide the first level of retry for SDIO operations. | |
35 | * If an SDIO command fails for reason of a response timeout or CRC | |
36 | * error, it is retried immediately. If three attempts fail we report a | |
37 | * failure. | |
38 | * If the command failed for any other reason, the failure is reported | |
39 | * immediately. | |
40 | * | |
41 | * Arguments: | |
42 | * card Pointer to card structure. | |
43 | * funcnum The SDIO function to access. | |
44 | * Function 0 is the Card Configuration Register space, | |
45 | * function 1/2 is the UniFi register space. | |
46 | * addr Address to access | |
47 | * pdata Pointer in which to return the value read. | |
48 | * data Value to write. | |
49 | * | |
50 | * Returns: | |
51 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
52 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
53 | * CSR_RESULT_FAILURE an SDIO error occurred | |
54 | * --------------------------------------------------------------------------- | |
55 | */ | |
26a6b2e1 | 56 | static CsrResult retrying_read8(card_t *card, s16 funcnum, u32 addr, u8 *pdata) |
635d2b00 GKH |
57 | { |
58 | CsrSdioFunction *sdio = card->sdio_if; | |
59 | CsrResult r = CSR_RESULT_SUCCESS; | |
ab2b8c73 | 60 | s16 retries; |
635d2b00 GKH |
61 | CsrResult csrResult = CSR_RESULT_SUCCESS; |
62 | ||
63 | retries = 0; | |
64 | while (retries++ < SDIO_RETRIES) | |
65 | { | |
66 | if (funcnum == 0) | |
67 | { | |
68 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
69 | unifi_debug_log_to_buf("r0@%02X", addr); | |
70 | #endif | |
71 | csrResult = CsrSdioF0Read8(sdio, addr, pdata); | |
72 | } | |
73 | else | |
74 | { | |
75 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
76 | unifi_error(card->ospriv, | |
77 | "retrying_read_f0_8: F1 8-bit reads are not allowed.\n"); | |
78 | return CSR_RESULT_FAILURE; | |
79 | #else | |
80 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
81 | unifi_debug_log_to_buf("r@%02X", addr); | |
82 | #endif | |
83 | csrResult = CsrSdioRead8(sdio, addr, pdata); | |
84 | #endif | |
85 | } | |
86 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
87 | if (csrResult != CSR_RESULT_SUCCESS) | |
88 | { | |
89 | unifi_debug_log_to_buf("error=%X\n", csrResult); | |
90 | } | |
91 | else | |
92 | { | |
93 | unifi_debug_log_to_buf("=%X\n", *pdata); | |
94 | } | |
95 | #endif | |
96 | if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) | |
97 | { | |
98 | return CSR_WIFI_HIP_RESULT_NO_DEVICE; | |
99 | } | |
100 | /* | |
101 | * Try again for retryable (CRC or TIMEOUT) errors, | |
102 | * break on success or fatal error | |
103 | */ | |
104 | if (!retryable_sdio_error(csrResult)) | |
105 | { | |
106 | #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE | |
107 | card->cmd_prof.cmd52_count++; | |
108 | #endif | |
109 | break; | |
110 | } | |
111 | unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); | |
112 | } | |
113 | ||
114 | if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) | |
115 | { | |
116 | unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); | |
117 | } | |
118 | ||
119 | if (csrResult != CSR_RESULT_SUCCESS) | |
120 | { | |
121 | unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", | |
122 | addr, retries - 1); | |
123 | /* Report any SDIO error as a general i/o error */ | |
124 | r = CSR_RESULT_FAILURE; | |
125 | } | |
126 | ||
127 | return r; | |
128 | } /* retrying_read8() */ | |
129 | ||
130 | ||
26a6b2e1 | 131 | static CsrResult retrying_write8(card_t *card, s16 funcnum, u32 addr, u8 data) |
635d2b00 GKH |
132 | { |
133 | CsrSdioFunction *sdio = card->sdio_if; | |
134 | CsrResult r = CSR_RESULT_SUCCESS; | |
ab2b8c73 | 135 | s16 retries; |
635d2b00 GKH |
136 | CsrResult csrResult = CSR_RESULT_SUCCESS; |
137 | ||
138 | retries = 0; | |
139 | while (retries++ < SDIO_RETRIES) | |
140 | { | |
141 | if (funcnum == 0) | |
142 | { | |
143 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
144 | unifi_debug_log_to_buf("w0@%02X=%X", addr, data); | |
145 | #endif | |
146 | csrResult = CsrSdioF0Write8(sdio, addr, data); | |
147 | } | |
148 | else | |
149 | { | |
150 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
151 | unifi_error(card->ospriv, | |
152 | "retrying_write_f0_8: F1 8-bit writes are not allowed.\n"); | |
153 | return CSR_RESULT_FAILURE; | |
154 | #else | |
155 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
156 | unifi_debug_log_to_buf("w@%02X=%X", addr, data); | |
157 | #endif | |
158 | csrResult = CsrSdioWrite8(sdio, addr, data); | |
159 | #endif | |
160 | } | |
161 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
162 | if (csrResult != CSR_RESULT_SUCCESS) | |
163 | { | |
164 | unifi_debug_log_to_buf(",error=%X", csrResult); | |
165 | } | |
166 | unifi_debug_string_to_buf("\n"); | |
167 | #endif | |
168 | if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) | |
169 | { | |
170 | return CSR_WIFI_HIP_RESULT_NO_DEVICE; | |
171 | } | |
172 | /* | |
173 | * Try again for retryable (CRC or TIMEOUT) errors, | |
174 | * break on success or fatal error | |
175 | */ | |
176 | if (!retryable_sdio_error(csrResult)) | |
177 | { | |
178 | #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE | |
179 | card->cmd_prof.cmd52_count++; | |
180 | #endif | |
181 | break; | |
182 | } | |
183 | unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", | |
184 | data, funcnum, addr); | |
185 | } | |
186 | ||
187 | if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) | |
188 | { | |
189 | unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); | |
190 | } | |
191 | ||
192 | if (csrResult != CSR_RESULT_SUCCESS) | |
193 | { | |
194 | unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", | |
195 | addr, retries - 1); | |
196 | /* Report any SDIO error as a general i/o error */ | |
197 | r = CSR_RESULT_FAILURE; | |
198 | } | |
199 | ||
200 | return r; | |
201 | } /* retrying_write8() */ | |
202 | ||
203 | ||
ab2b8c73 | 204 | static CsrResult retrying_read16(card_t *card, s16 funcnum, |
26a6b2e1 | 205 | u32 addr, u16 *pdata) |
635d2b00 GKH |
206 | { |
207 | CsrSdioFunction *sdio = card->sdio_if; | |
208 | CsrResult r = CSR_RESULT_SUCCESS; | |
ab2b8c73 | 209 | s16 retries; |
635d2b00 GKH |
210 | CsrResult csrResult = CSR_RESULT_SUCCESS; |
211 | ||
212 | retries = 0; | |
213 | while (retries++ < SDIO_RETRIES) | |
214 | { | |
215 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
216 | unifi_debug_log_to_buf("r@%02X", addr); | |
217 | #endif | |
218 | csrResult = CsrSdioRead16(sdio, addr, pdata); | |
219 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
220 | if (csrResult != CSR_RESULT_SUCCESS) | |
221 | { | |
222 | unifi_debug_log_to_buf("error=%X\n", csrResult); | |
223 | } | |
224 | else | |
225 | { | |
226 | unifi_debug_log_to_buf("=%X\n", *pdata); | |
227 | } | |
228 | #endif | |
229 | if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) | |
230 | { | |
231 | return CSR_WIFI_HIP_RESULT_NO_DEVICE; | |
232 | } | |
233 | ||
234 | /* | |
235 | * Try again for retryable (CRC or TIMEOUT) errors, | |
236 | * break on success or fatal error | |
237 | */ | |
238 | if (!retryable_sdio_error(csrResult)) | |
239 | { | |
240 | #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE | |
241 | card->cmd_prof.cmd52_count++; | |
242 | #endif | |
243 | break; | |
244 | } | |
245 | unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); | |
246 | } | |
247 | ||
248 | if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) | |
249 | { | |
250 | unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); | |
251 | } | |
252 | ||
253 | if (csrResult != CSR_RESULT_SUCCESS) | |
254 | { | |
255 | unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", | |
256 | addr, retries - 1); | |
257 | /* Report any SDIO error as a general i/o error */ | |
258 | r = CSR_RESULT_FAILURE; | |
259 | } | |
260 | ||
261 | return r; | |
262 | } /* retrying_read16() */ | |
263 | ||
264 | ||
ab2b8c73 | 265 | static CsrResult retrying_write16(card_t *card, s16 funcnum, |
26a6b2e1 | 266 | u32 addr, u16 data) |
635d2b00 GKH |
267 | { |
268 | CsrSdioFunction *sdio = card->sdio_if; | |
269 | CsrResult r = CSR_RESULT_SUCCESS; | |
ab2b8c73 | 270 | s16 retries; |
635d2b00 GKH |
271 | CsrResult csrResult = CSR_RESULT_SUCCESS; |
272 | ||
273 | retries = 0; | |
274 | while (retries++ < SDIO_RETRIES) | |
275 | { | |
276 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
277 | unifi_debug_log_to_buf("w@%02X=%X", addr, data); | |
278 | #endif | |
279 | csrResult = CsrSdioWrite16(sdio, addr, data); | |
280 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
281 | if (csrResult != CSR_RESULT_SUCCESS) | |
282 | { | |
283 | unifi_debug_log_to_buf(",error=%X", csrResult); | |
284 | } | |
285 | unifi_debug_string_to_buf("\n"); | |
286 | #endif | |
287 | if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) | |
288 | { | |
289 | return CSR_WIFI_HIP_RESULT_NO_DEVICE; | |
290 | } | |
291 | ||
292 | /* | |
293 | * Try again for retryable (CRC or TIMEOUT) errors, | |
294 | * break on success or fatal error | |
295 | */ | |
296 | if (!retryable_sdio_error(csrResult)) | |
297 | { | |
298 | #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE | |
299 | card->cmd_prof.cmd52_count++; | |
300 | #endif | |
301 | break; | |
302 | } | |
303 | unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", | |
304 | data, funcnum, addr); | |
305 | } | |
306 | ||
307 | if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) | |
308 | { | |
309 | unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); | |
310 | } | |
311 | ||
312 | if (csrResult != CSR_RESULT_SUCCESS) | |
313 | { | |
314 | unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", | |
315 | addr, retries - 1); | |
316 | /* Report any SDIO error as a general i/o error */ | |
317 | r = CSR_RESULT_FAILURE; | |
318 | } | |
319 | ||
320 | return r; | |
321 | } /* retrying_write16() */ | |
322 | ||
323 | ||
324 | /* | |
325 | * --------------------------------------------------------------------------- | |
326 | * sdio_read_f0 | |
327 | * | |
328 | * Reads a byte value from the CCCR (func 0) area of UniFi. | |
329 | * | |
330 | * Arguments: | |
331 | * card Pointer to card structure. | |
332 | * addr Address to read from | |
333 | * pdata Pointer in which to store the read value. | |
334 | * | |
335 | * Returns: | |
336 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
337 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
338 | * CSR_RESULT_FAILURE an SDIO error occurred | |
339 | * --------------------------------------------------------------------------- | |
340 | */ | |
26a6b2e1 | 341 | CsrResult sdio_read_f0(card_t *card, u32 addr, u8 *pdata) |
635d2b00 GKH |
342 | { |
343 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
344 | card->cmd_prof.cmd52_f0_r_count++; | |
345 | #endif | |
346 | return retrying_read8(card, 0, addr, pdata); | |
347 | } /* sdio_read_f0() */ | |
348 | ||
349 | ||
350 | /* | |
351 | * --------------------------------------------------------------------------- | |
352 | * sdio_write_f0 | |
353 | * | |
354 | * Writes a byte value to the CCCR (func 0) area of UniFi. | |
355 | * | |
356 | * Arguments: | |
357 | * card Pointer to card structure. | |
358 | * addr Address to read from | |
359 | * data Data value to write. | |
360 | * | |
361 | * Returns: | |
362 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
363 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
364 | * CSR_RESULT_FAILURE an SDIO error occurred | |
365 | * --------------------------------------------------------------------------- | |
366 | */ | |
26a6b2e1 | 367 | CsrResult sdio_write_f0(card_t *card, u32 addr, u8 data) |
635d2b00 GKH |
368 | { |
369 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
370 | card->cmd_prof.cmd52_f0_w_count++; | |
371 | #endif | |
372 | return retrying_write8(card, 0, addr, data); | |
373 | } /* sdio_write_f0() */ | |
374 | ||
375 | ||
376 | /* | |
377 | * --------------------------------------------------------------------------- | |
378 | * unifi_read_direct_8_or_16 | |
379 | * | |
380 | * Read a 8-bit value from the UniFi SDIO interface. | |
381 | * | |
382 | * Arguments: | |
383 | * card Pointer to card structure. | |
384 | * addr Address to read from | |
385 | * pdata Pointer in which to return data. | |
386 | * | |
387 | * Returns: | |
388 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
389 | * --------------------------------------------------------------------------- | |
390 | */ | |
26a6b2e1 | 391 | CsrResult unifi_read_direct_8_or_16(card_t *card, u32 addr, u8 *pdata) |
635d2b00 GKH |
392 | { |
393 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
8c87f69a | 394 | u16 w; |
635d2b00 GKH |
395 | CsrResult r; |
396 | ||
397 | r = retrying_read16(card, card->function, addr, &w); | |
7e6f5794 | 398 | *pdata = (u8)(w & 0xFF); |
635d2b00 GKH |
399 | return r; |
400 | #else | |
401 | return retrying_read8(card, card->function, addr, pdata); | |
402 | #endif | |
403 | } /* unifi_read_direct_8_or_16() */ | |
404 | ||
405 | ||
406 | /* | |
407 | * --------------------------------------------------------------------------- | |
408 | * unifi_write_direct_8_or_16 | |
409 | * | |
410 | * Write a byte value to the UniFi SDIO interface. | |
411 | * | |
412 | * Arguments: | |
413 | * card Pointer to card structure. | |
414 | * addr Address to write to | |
415 | * data Value to write. | |
416 | * | |
417 | * Returns: | |
418 | * CSR_RESULT_SUCCESS on success, non-zero error code on error | |
419 | * | |
420 | * Notes: | |
421 | * If 8-bit write is used, the even address *must* be written second. | |
422 | * This is because writes to odd bytes are cached and not committed | |
423 | * to memory until the preceding even address is written. | |
424 | * --------------------------------------------------------------------------- | |
425 | */ | |
26a6b2e1 | 426 | CsrResult unifi_write_direct_8_or_16(card_t *card, u32 addr, u8 data) |
635d2b00 GKH |
427 | { |
428 | if (addr & 1) | |
429 | { | |
430 | unifi_warning(card->ospriv, | |
431 | "Warning: Byte write to an odd address (0x%lX) is dangerous\n", | |
432 | addr); | |
433 | } | |
434 | ||
435 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
8c87f69a | 436 | return retrying_write16(card, card->function, addr, (u16)data); |
635d2b00 GKH |
437 | #else |
438 | return retrying_write8(card, card->function, addr, data); | |
439 | #endif | |
440 | } /* unifi_write_direct_8_or_16() */ | |
441 | ||
442 | ||
443 | /* | |
444 | * --------------------------------------------------------------------------- | |
445 | * unifi_read_direct16 | |
446 | * | |
447 | * Read a 16-bit value from the UniFi SDIO interface. | |
448 | * | |
449 | * Arguments: | |
450 | * card Pointer to card structure. | |
451 | * addr Address to read from | |
452 | * pdata Pointer in which to return data. | |
453 | * | |
454 | * Returns: | |
455 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
456 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
457 | * CSR_RESULT_FAILURE an SDIO error occurred | |
458 | * | |
459 | * Notes: | |
460 | * The even address *must* be read first. This is because reads from | |
461 | * odd bytes are cached and read from memory when the preceding | |
462 | * even address is read. | |
463 | * --------------------------------------------------------------------------- | |
464 | */ | |
26a6b2e1 | 465 | CsrResult unifi_read_direct16(card_t *card, u32 addr, u16 *pdata) |
635d2b00 GKH |
466 | { |
467 | return retrying_read16(card, card->function, addr, pdata); | |
468 | } /* unifi_read_direct16() */ | |
469 | ||
470 | ||
471 | /* | |
472 | * --------------------------------------------------------------------------- | |
473 | * unifi_write_direct16 | |
474 | * | |
475 | * Write a 16-bit value to the UniFi SDIO interface. | |
476 | * | |
477 | * Arguments: | |
478 | * card Pointer to card structure. | |
479 | * addr Address to write to | |
480 | * data Value to write. | |
481 | * | |
482 | * Returns: | |
483 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
484 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
485 | * CSR_RESULT_FAILURE an SDIO error occurred | |
486 | * | |
487 | * Notes: | |
488 | * The even address *must* be written second. This is because writes to | |
489 | * odd bytes are cached and not committed to memory until the preceding | |
490 | * even address is written. | |
491 | * --------------------------------------------------------------------------- | |
492 | */ | |
26a6b2e1 | 493 | CsrResult unifi_write_direct16(card_t *card, u32 addr, u16 data) |
635d2b00 GKH |
494 | { |
495 | return retrying_write16(card, card->function, addr, data); | |
496 | } /* unifi_write_direct16() */ | |
497 | ||
498 | ||
499 | /* | |
500 | * --------------------------------------------------------------------------- | |
501 | * unifi_read_direct32 | |
502 | * | |
503 | * Read a 32-bit value from the UniFi SDIO interface. | |
504 | * | |
505 | * Arguments: | |
506 | * card Pointer to card structure. | |
507 | * addr Address to read from | |
508 | * pdata Pointer in which to return data. | |
509 | * | |
510 | * Returns: | |
511 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
512 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
513 | * CSR_RESULT_FAILURE an SDIO error occurred | |
514 | * --------------------------------------------------------------------------- | |
515 | */ | |
26a6b2e1 | 516 | CsrResult unifi_read_direct32(card_t *card, u32 addr, u32 *pdata) |
635d2b00 GKH |
517 | { |
518 | CsrResult r; | |
8c87f69a | 519 | u16 w0, w1; |
635d2b00 GKH |
520 | |
521 | r = retrying_read16(card, card->function, addr, &w0); | |
522 | if (r != CSR_RESULT_SUCCESS) | |
523 | { | |
524 | return r; | |
525 | } | |
526 | ||
527 | r = retrying_read16(card, card->function, addr + 2, &w1); | |
528 | if (r != CSR_RESULT_SUCCESS) | |
529 | { | |
530 | return r; | |
531 | } | |
532 | ||
26a6b2e1 | 533 | *pdata = ((u32)w1 << 16) | (u32)w0; |
635d2b00 GKH |
534 | |
535 | return CSR_RESULT_SUCCESS; | |
536 | } /* unifi_read_direct32() */ | |
537 | ||
538 | ||
539 | /* | |
540 | * --------------------------------------------------------------------------- | |
541 | * unifi_read_directn_match | |
542 | * | |
543 | * Read multiple 8-bit values from the UniFi SDIO interface, | |
544 | * stopping when either we have read 'len' bytes or we have read | |
545 | * a octet equal to 'match'. If 'match' is not a valid octet | |
546 | * then this function is the same as 'unifi_read_directn'. | |
547 | * | |
548 | * Arguments: | |
549 | * card Pointer to card structure. | |
550 | * addr Start address to read from. | |
551 | * pdata Pointer to which to write data. | |
552 | * len Maximum umber of bytes to read | |
553 | * match The value to stop reading at. | |
554 | * num Pointer to buffer to write number of bytes read | |
555 | * | |
556 | * Returns: | |
557 | * number of octets read on success, negative error code on error: | |
558 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
559 | * CSR_RESULT_FAILURE an SDIO error occurred | |
560 | * | |
561 | * Notes: | |
562 | * The even address *must* be read first. This is because reads from | |
563 | * odd bytes are cached and read from memory when the preceding | |
564 | * even address is read. | |
565 | * --------------------------------------------------------------------------- | |
566 | */ | |
26a6b2e1 | 567 | static CsrResult unifi_read_directn_match(card_t *card, u32 addr, void *pdata, u16 len, s8 m, u32 *num) |
635d2b00 GKH |
568 | { |
569 | CsrResult r; | |
26a6b2e1 | 570 | u32 i; |
7e6f5794 | 571 | u8 *cptr; |
8c87f69a | 572 | u16 w; |
635d2b00 GKH |
573 | |
574 | *num = 0; | |
575 | ||
7e6f5794 | 576 | cptr = (u8 *)pdata; |
635d2b00 GKH |
577 | for (i = 0; i < len; i += 2) |
578 | { | |
579 | r = retrying_read16(card, card->function, addr, &w); | |
580 | if (r != CSR_RESULT_SUCCESS) | |
581 | { | |
582 | return r; | |
583 | } | |
584 | ||
7e6f5794 | 585 | *cptr++ = ((u8)w & 0xFF); |
163eb0d8 | 586 | if ((m >= 0) && (((s8)w & 0xFF) == m)) |
635d2b00 GKH |
587 | { |
588 | break; | |
589 | } | |
590 | ||
591 | if (i + 1 == len) | |
592 | { | |
593 | /* The len is odd. Ignore the last high byte */ | |
594 | break; | |
595 | } | |
596 | ||
7e6f5794 | 597 | *cptr++ = ((u8)(w >> 8) & 0xFF); |
163eb0d8 | 598 | if ((m >= 0) && (((s8)(w >> 8) & 0xFF) == m)) |
635d2b00 GKH |
599 | { |
600 | break; | |
601 | } | |
602 | ||
603 | addr += 2; | |
604 | } | |
605 | ||
95e326c2 | 606 | *num = (s32)(cptr - (u8 *)pdata); |
635d2b00 GKH |
607 | return CSR_RESULT_SUCCESS; |
608 | } | |
609 | ||
610 | ||
611 | /* | |
612 | * --------------------------------------------------------------------------- | |
613 | * unifi_read_directn | |
614 | * | |
615 | * Read multiple 8-bit values from the UniFi SDIO interface. | |
616 | * | |
617 | * Arguments: | |
618 | * card Pointer to card structure. | |
619 | * addr Start address to read from. | |
620 | * pdata Pointer to which to write data. | |
621 | * len Number of bytes to read | |
622 | * | |
623 | * Returns: | |
624 | * 0 on success, non-zero error code on error: | |
625 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
626 | * CSR_RESULT_FAILURE an SDIO error occurred | |
627 | * | |
628 | * Notes: | |
629 | * The even address *must* be read first. This is because reads from | |
630 | * odd bytes are cached and read from memory when the preceding | |
631 | * even address is read. | |
632 | * --------------------------------------------------------------------------- | |
633 | */ | |
26a6b2e1 | 634 | CsrResult unifi_read_directn(card_t *card, u32 addr, void *pdata, u16 len) |
635d2b00 | 635 | { |
26a6b2e1 | 636 | u32 num; |
635d2b00 GKH |
637 | |
638 | return unifi_read_directn_match(card, addr, pdata, len, -1, &num); | |
639 | } /* unifi_read_directn() */ | |
640 | ||
641 | ||
642 | /* | |
643 | * --------------------------------------------------------------------------- | |
644 | * unifi_write_directn | |
645 | * | |
646 | * Write multiple 8-bit values to the UniFi SDIO interface. | |
647 | * | |
648 | * Arguments: | |
649 | * card Pointer to card structure. | |
650 | * addr Start address to write to. | |
651 | * pdata Source data pointer. | |
652 | * len Number of bytes to write, must be even. | |
653 | * | |
654 | * Returns: | |
655 | * 0 on success, non-zero error code on error: | |
656 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
657 | * CSR_RESULT_FAILURE an SDIO error occurred | |
658 | * | |
659 | * Notes: | |
660 | * The UniFi has a peculiar 16-bit bus architecture. Writes are only | |
661 | * committed to memory when an even address is accessed. Writes to | |
662 | * odd addresses are cached and only committed if the next write is | |
663 | * to the preceding address. | |
664 | * This means we must write data as pairs of bytes in reverse order. | |
665 | * --------------------------------------------------------------------------- | |
666 | */ | |
26a6b2e1 | 667 | CsrResult unifi_write_directn(card_t *card, u32 addr, void *pdata, u16 len) |
635d2b00 GKH |
668 | { |
669 | CsrResult r; | |
7e6f5794 | 670 | u8 *cptr; |
ab2b8c73 | 671 | s16 signed_len; |
635d2b00 | 672 | |
7e6f5794 | 673 | cptr = (u8 *)pdata; |
ab2b8c73 | 674 | signed_len = (s16)len; |
635d2b00 GKH |
675 | while (signed_len > 0) |
676 | { | |
677 | /* This is UniFi-1 specific code. CSPI not supported so 8-bit write allowed */ | |
678 | r = retrying_write16(card, card->function, addr, *cptr); | |
679 | if (r != CSR_RESULT_SUCCESS) | |
680 | { | |
681 | return r; | |
682 | } | |
683 | ||
684 | cptr += 2; | |
685 | addr += 2; | |
686 | signed_len -= 2; | |
687 | } | |
688 | ||
689 | return CSR_RESULT_SUCCESS; | |
690 | } /* unifi_write_directn() */ | |
691 | ||
692 | ||
693 | /* | |
694 | * --------------------------------------------------------------------------- | |
695 | * set_dmem_page | |
696 | * set_pmem_page | |
697 | * | |
698 | * Set up the page register for the shared data memory window or program | |
699 | * memory window. | |
700 | * | |
701 | * Arguments: | |
702 | * card Pointer to card structure. | |
703 | * dmem_addr UniFi shared-data-memory address to access. | |
704 | * pmem_addr UniFi program memory address to access. This includes | |
705 | * External FLASH memory at 0x000000 | |
706 | * Processor program memory at 0x200000 | |
707 | * External SRAM at memory 0x400000 | |
708 | * paddr Location to write an SDIO address (24-bit) for | |
709 | * use in a unifi_read_direct or unifi_write_direct call. | |
710 | * | |
711 | * Returns: | |
712 | * CSR_RESULT_SUCCESS on success | |
713 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
714 | * CSR_RESULT_FAILURE an SDIO error occurred | |
715 | * --------------------------------------------------------------------------- | |
716 | */ | |
26a6b2e1 | 717 | static CsrResult set_dmem_page(card_t *card, u32 dmem_addr, u32 *paddr) |
635d2b00 | 718 | { |
8c87f69a | 719 | u16 page, addr; |
26a6b2e1 | 720 | u32 len; |
635d2b00 GKH |
721 | CsrResult r; |
722 | ||
723 | *paddr = 0; | |
724 | ||
725 | if (!ChipHelper_DecodeWindow(card->helper, | |
726 | CHIP_HELPER_WINDOW_3, | |
727 | CHIP_HELPER_WT_SHARED, | |
728 | dmem_addr / 2, | |
729 | &page, &addr, &len)) | |
730 | { | |
731 | unifi_error(card->ospriv, "Failed to decode SHARED_DMEM_PAGE %08lx\n", dmem_addr); | |
732 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
733 | } | |
734 | ||
735 | if (page != card->dmem_page) | |
736 | { | |
737 | unifi_trace(card->ospriv, UDBG6, "setting dmem page=0x%X, addr=0x%lX\n", page, addr); | |
738 | ||
739 | /* change page register */ | |
740 | r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW3_PAGE(card->helper) * 2, page); | |
741 | if (r != CSR_RESULT_SUCCESS) | |
742 | { | |
743 | unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n"); | |
744 | return r; | |
745 | } | |
746 | ||
747 | card->dmem_page = page; | |
748 | } | |
749 | ||
95e326c2 | 750 | *paddr = ((s32)addr * 2) + (dmem_addr & 1); |
635d2b00 GKH |
751 | |
752 | return CSR_RESULT_SUCCESS; | |
753 | } /* set_dmem_page() */ | |
754 | ||
755 | ||
26a6b2e1 GKH |
756 | static CsrResult set_pmem_page(card_t *card, u32 pmem_addr, |
757 | enum chip_helper_window_type mem_type, u32 *paddr) | |
635d2b00 | 758 | { |
8c87f69a | 759 | u16 page, addr; |
26a6b2e1 | 760 | u32 len; |
635d2b00 GKH |
761 | CsrResult r; |
762 | ||
763 | *paddr = 0; | |
764 | ||
765 | if (!ChipHelper_DecodeWindow(card->helper, | |
766 | CHIP_HELPER_WINDOW_2, | |
767 | mem_type, | |
768 | pmem_addr / 2, | |
769 | &page, &addr, &len)) | |
770 | { | |
771 | unifi_error(card->ospriv, "Failed to decode PROG MEM PAGE %08lx %d\n", pmem_addr, mem_type); | |
772 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
773 | } | |
774 | ||
775 | if (page != card->pmem_page) | |
776 | { | |
777 | unifi_trace(card->ospriv, UDBG6, "setting pmem page=0x%X, addr=0x%lX\n", page, addr); | |
778 | ||
779 | /* change page register */ | |
780 | r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, page); | |
781 | if (r != CSR_RESULT_SUCCESS) | |
782 | { | |
783 | unifi_error(card->ospriv, "Failed to write PROG MEM PAGE\n"); | |
784 | return r; | |
785 | } | |
786 | ||
787 | card->pmem_page = page; | |
788 | } | |
789 | ||
95e326c2 | 790 | *paddr = ((s32)addr * 2) + (pmem_addr & 1); |
635d2b00 GKH |
791 | |
792 | return CSR_RESULT_SUCCESS; | |
793 | } /* set_pmem_page() */ | |
794 | ||
795 | ||
796 | /* | |
797 | * --------------------------------------------------------------------------- | |
798 | * set_page | |
799 | * | |
800 | * Sets up the appropriate page register to access the given address. | |
801 | * Returns the sdio address at which the unifi address can be accessed. | |
802 | * | |
803 | * Arguments: | |
804 | * card Pointer to card structure. | |
805 | * generic_addr UniFi internal address to access, in Generic Pointer | |
806 | * format, i.e. top byte is space indicator. | |
807 | * paddr Location to write page address | |
808 | * SDIO address (24-bit) for use in a unifi_read_direct or | |
809 | * unifi_write_direct call | |
810 | * | |
811 | * Returns: | |
812 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
813 | * CSR_RESULT_FAILURE an SDIO error occurred | |
814 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE the address is invalid | |
815 | * --------------------------------------------------------------------------- | |
816 | */ | |
26a6b2e1 | 817 | static CsrResult set_page(card_t *card, u32 generic_addr, u32 *paddr) |
635d2b00 | 818 | { |
95e326c2 | 819 | s32 space; |
26a6b2e1 | 820 | u32 addr; |
635d2b00 GKH |
821 | CsrResult r = CSR_RESULT_SUCCESS; |
822 | ||
823 | if (!paddr) | |
824 | { | |
825 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
826 | } | |
827 | *paddr = 0; | |
828 | space = UNIFI_GP_SPACE(generic_addr); | |
829 | addr = UNIFI_GP_OFFSET(generic_addr); | |
830 | switch (space) | |
831 | { | |
832 | case UNIFI_SH_DMEM: | |
833 | /* Shared Data Memory is accessed via the Shared Data Memory window */ | |
834 | r = set_dmem_page(card, addr, paddr); | |
835 | if (r != CSR_RESULT_SUCCESS) | |
836 | { | |
837 | return r; | |
838 | } | |
839 | break; | |
840 | ||
841 | case UNIFI_EXT_FLASH: | |
842 | if (!ChipHelper_HasFlash(card->helper)) | |
843 | { | |
844 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
845 | generic_addr, card->helper); | |
846 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
847 | } | |
848 | /* External FLASH is accessed via the Program Memory window */ | |
849 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_FLASH, paddr); | |
850 | break; | |
851 | ||
852 | case UNIFI_EXT_SRAM: | |
853 | if (!ChipHelper_HasExtSram(card->helper)) | |
854 | { | |
855 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08l (helper=0x%x)\n", | |
856 | generic_addr, card->helper); | |
857 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
858 | } | |
859 | /* External SRAM is accessed via the Program Memory window */ | |
860 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_EXT_SRAM, paddr); | |
861 | break; | |
862 | ||
863 | case UNIFI_REGISTERS: | |
864 | /* Registers are accessed directly */ | |
865 | *paddr = addr; | |
866 | break; | |
867 | ||
868 | case UNIFI_PHY_DMEM: | |
869 | r = unifi_set_proc_select(card, UNIFI_PROC_PHY); | |
870 | if (r != CSR_RESULT_SUCCESS) | |
871 | { | |
872 | return r; | |
873 | } | |
874 | *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; | |
875 | break; | |
876 | ||
877 | case UNIFI_MAC_DMEM: | |
878 | r = unifi_set_proc_select(card, UNIFI_PROC_MAC); | |
879 | if (r != CSR_RESULT_SUCCESS) | |
880 | { | |
881 | return r; | |
882 | } | |
883 | *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; | |
884 | break; | |
885 | ||
886 | case UNIFI_BT_DMEM: | |
887 | if (!ChipHelper_HasBt(card->helper)) | |
888 | { | |
889 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
890 | generic_addr, card->helper); | |
891 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
892 | } | |
893 | r = unifi_set_proc_select(card, UNIFI_PROC_BT); | |
894 | if (r != CSR_RESULT_SUCCESS) | |
895 | { | |
896 | return r; | |
897 | } | |
898 | *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; | |
899 | break; | |
900 | ||
901 | case UNIFI_PHY_PMEM: | |
902 | r = unifi_set_proc_select(card, UNIFI_PROC_PHY); | |
903 | if (r != CSR_RESULT_SUCCESS) | |
904 | { | |
905 | return r; | |
906 | } | |
907 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); | |
908 | break; | |
909 | ||
910 | case UNIFI_MAC_PMEM: | |
911 | r = unifi_set_proc_select(card, UNIFI_PROC_MAC); | |
912 | if (r != CSR_RESULT_SUCCESS) | |
913 | { | |
914 | return r; | |
915 | } | |
916 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); | |
917 | break; | |
918 | ||
919 | case UNIFI_BT_PMEM: | |
920 | if (!ChipHelper_HasBt(card->helper)) | |
921 | { | |
922 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
923 | generic_addr, card->helper); | |
924 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
925 | } | |
926 | r = unifi_set_proc_select(card, UNIFI_PROC_BT); | |
927 | if (r != CSR_RESULT_SUCCESS) | |
928 | { | |
929 | return r; | |
930 | } | |
931 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); | |
932 | break; | |
933 | ||
934 | case UNIFI_PHY_ROM: | |
935 | if (!ChipHelper_HasRom(card->helper)) | |
936 | { | |
937 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
938 | generic_addr, card->helper); | |
939 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
940 | } | |
941 | r = unifi_set_proc_select(card, UNIFI_PROC_PHY); | |
942 | if (r != CSR_RESULT_SUCCESS) | |
943 | { | |
944 | return r; | |
945 | } | |
946 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); | |
947 | break; | |
948 | ||
949 | case UNIFI_MAC_ROM: | |
950 | if (!ChipHelper_HasRom(card->helper)) | |
951 | { | |
952 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
953 | generic_addr, card->helper); | |
954 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
955 | } | |
956 | r = unifi_set_proc_select(card, UNIFI_PROC_MAC); | |
957 | if (r != CSR_RESULT_SUCCESS) | |
958 | { | |
959 | return r; | |
960 | } | |
961 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); | |
962 | break; | |
963 | ||
964 | case UNIFI_BT_ROM: | |
965 | if (!ChipHelper_HasRom(card->helper) || !ChipHelper_HasBt(card->helper)) | |
966 | { | |
967 | unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", | |
968 | generic_addr, card->helper); | |
969 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
970 | } | |
971 | r = unifi_set_proc_select(card, UNIFI_PROC_BT); | |
972 | if (r != CSR_RESULT_SUCCESS) | |
973 | { | |
974 | return r; | |
975 | } | |
976 | r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); | |
977 | break; | |
978 | ||
979 | default: | |
980 | unifi_error(card->ospriv, "Bad address space %d in generic pointer 0x%08lX (helper=0x%x)\n", | |
981 | space, generic_addr, card->helper); | |
982 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
983 | } | |
984 | ||
985 | return r; | |
986 | } /* set_page() */ | |
987 | ||
988 | ||
989 | /* | |
990 | * --------------------------------------------------------------------------- | |
991 | * unifi_set_proc_select | |
992 | * | |
993 | * | |
994 | * Arguments: | |
995 | * card Pointer to card structure. | |
996 | * select Which XAP core to select | |
997 | * | |
998 | * Returns: | |
999 | * 0 on success, non-zero error code on error: | |
1000 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1001 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1002 | * --------------------------------------------------------------------------- | |
1003 | */ | |
1004 | CsrResult unifi_set_proc_select(card_t *card, enum unifi_dbg_processors_select select) | |
1005 | { | |
1006 | CsrResult r; | |
1007 | ||
1008 | /* Verify the the select value is allowed. */ | |
1009 | switch (select) | |
1010 | { | |
1011 | case UNIFI_PROC_MAC: | |
1012 | case UNIFI_PROC_PHY: | |
1013 | case UNIFI_PROC_BOTH: | |
1014 | break; | |
1015 | ||
1016 | ||
1017 | default: | |
1018 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
1019 | } | |
1020 | ||
26a6b2e1 | 1021 | if (card->proc_select != (u32)select) |
635d2b00 GKH |
1022 | { |
1023 | r = unifi_write_direct16(card, | |
1024 | ChipHelper_DBG_HOST_PROC_SELECT(card->helper) * 2, | |
7e6f5794 | 1025 | (u8)select); |
635d2b00 GKH |
1026 | if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) |
1027 | { | |
1028 | return r; | |
1029 | } | |
1030 | if (r != CSR_RESULT_SUCCESS) | |
1031 | { | |
1032 | unifi_error(card->ospriv, "Failed to write to Proc Select register\n"); | |
1033 | return r; | |
1034 | } | |
1035 | ||
26a6b2e1 | 1036 | card->proc_select = (u32)select; |
635d2b00 GKH |
1037 | } |
1038 | ||
1039 | return CSR_RESULT_SUCCESS; | |
1040 | } | |
1041 | ||
1042 | ||
1043 | /* | |
1044 | * --------------------------------------------------------------------------- | |
1045 | * unifi_read_8_or_16 | |
1046 | * | |
1047 | * Performs a byte read of the given address in shared data memory. | |
1048 | * Set up the shared data memory page register as required. | |
1049 | * | |
1050 | * Arguments: | |
1051 | * card Pointer to card structure. | |
1052 | * unifi_addr UniFi shared-data-memory address to access. | |
1053 | * pdata Pointer to a byte variable for the value read. | |
1054 | * | |
1055 | * Returns: | |
1056 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1057 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1058 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1059 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1060 | * --------------------------------------------------------------------------- | |
1061 | */ | |
26a6b2e1 | 1062 | CsrResult unifi_read_8_or_16(card_t *card, u32 unifi_addr, u8 *pdata) |
635d2b00 | 1063 | { |
26a6b2e1 | 1064 | u32 sdio_addr; |
635d2b00 GKH |
1065 | CsrResult r; |
1066 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
8c87f69a | 1067 | u16 w; |
635d2b00 GKH |
1068 | #endif |
1069 | ||
1070 | r = set_page(card, unifi_addr, &sdio_addr); | |
1071 | if (r != CSR_RESULT_SUCCESS) | |
1072 | { | |
1073 | return r; | |
1074 | } | |
1075 | ||
1076 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1077 | card->cmd_prof.cmd52_r8or16_count++; | |
1078 | #endif | |
1079 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
1080 | r = retrying_read16(card, card->function, sdio_addr, &w); | |
7e6f5794 | 1081 | *pdata = (u8)(w & 0xFF); |
635d2b00 GKH |
1082 | return r; |
1083 | #else | |
1084 | return retrying_read8(card, card->function, sdio_addr, pdata); | |
1085 | #endif | |
1086 | } /* unifi_read_8_or_16() */ | |
1087 | ||
1088 | ||
1089 | /* | |
1090 | * --------------------------------------------------------------------------- | |
1091 | * unifi_write_8_or_16 | |
1092 | * | |
1093 | * Performs a byte write of the given address in shared data memory. | |
1094 | * Set up the shared data memory page register as required. | |
1095 | * | |
1096 | * Arguments: | |
1097 | * card Pointer to card context struct. | |
1098 | * unifi_addr UniFi shared-data-memory address to access. | |
1099 | * data Value to write. | |
1100 | * | |
1101 | * Returns: | |
1102 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1103 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1104 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1105 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1106 | * | |
1107 | * Notes: | |
1108 | * Beware using unifi_write8() because byte writes are not safe on UniFi. | |
1109 | * Writes to odd bytes are cached, writes to even bytes perform a 16-bit | |
1110 | * write with the previously cached odd byte. | |
1111 | * --------------------------------------------------------------------------- | |
1112 | */ | |
26a6b2e1 | 1113 | CsrResult unifi_write_8_or_16(card_t *card, u32 unifi_addr, u8 data) |
635d2b00 | 1114 | { |
26a6b2e1 | 1115 | u32 sdio_addr; |
635d2b00 GKH |
1116 | CsrResult r; |
1117 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
8c87f69a | 1118 | u16 w; |
635d2b00 GKH |
1119 | #endif |
1120 | ||
1121 | r = set_page(card, unifi_addr, &sdio_addr); | |
1122 | if (r != CSR_RESULT_SUCCESS) | |
1123 | { | |
1124 | return r; | |
1125 | } | |
1126 | ||
1127 | if (sdio_addr & 1) | |
1128 | { | |
1129 | unifi_warning(card->ospriv, | |
1130 | "Warning: Byte write to an odd address (0x%lX) is dangerous\n", | |
1131 | sdio_addr); | |
1132 | } | |
1133 | ||
1134 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1135 | card->cmd_prof.cmd52_w8or16_count++; | |
1136 | #endif | |
1137 | #ifdef CSR_WIFI_TRANSPORT_CSPI | |
1138 | w = data; | |
1139 | return retrying_write16(card, card->function, sdio_addr, w); | |
1140 | #else | |
1141 | return retrying_write8(card, card->function, sdio_addr, data); | |
1142 | #endif | |
1143 | } /* unifi_write_8_or_16() */ | |
1144 | ||
1145 | ||
1146 | /* | |
1147 | * --------------------------------------------------------------------------- | |
1148 | * unifi_card_read16 | |
1149 | * | |
1150 | * Performs a 16-bit read of the given address in shared data memory. | |
1151 | * Set up the shared data memory page register as required. | |
1152 | * | |
1153 | * Arguments: | |
1154 | * card Pointer to card structure. | |
1155 | * unifi_addr UniFi shared-data-memory address to access. | |
1156 | * pdata Pointer to a 16-bit int variable for the value read. | |
1157 | * | |
1158 | * Returns: | |
1159 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1160 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1161 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1162 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1163 | * --------------------------------------------------------------------------- | |
1164 | */ | |
26a6b2e1 | 1165 | CsrResult unifi_card_read16(card_t *card, u32 unifi_addr, u16 *pdata) |
635d2b00 | 1166 | { |
26a6b2e1 | 1167 | u32 sdio_addr; |
635d2b00 GKH |
1168 | CsrResult r; |
1169 | ||
1170 | r = set_page(card, unifi_addr, &sdio_addr); | |
1171 | if (r != CSR_RESULT_SUCCESS) | |
1172 | { | |
1173 | return r; | |
1174 | } | |
1175 | ||
1176 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1177 | card->cmd_prof.cmd52_r16_count++; | |
1178 | #endif | |
1179 | return unifi_read_direct16(card, sdio_addr, pdata); | |
1180 | } /* unifi_card_read16() */ | |
1181 | ||
1182 | ||
1183 | /* | |
1184 | * --------------------------------------------------------------------------- | |
1185 | * unifi_card_write16 | |
1186 | * | |
1187 | * Performs a 16-bit write of the given address in shared data memory. | |
1188 | * Set up the shared data memory page register as required. | |
1189 | * | |
1190 | * Arguments: | |
1191 | * card Pointer to card structure. | |
1192 | * unifi_addr UniFi shared-data-memory address to access. | |
1193 | * pdata Pointer to a byte variable for the value write. | |
1194 | * | |
1195 | * Returns: | |
1196 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1197 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1198 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1199 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1200 | * --------------------------------------------------------------------------- | |
1201 | */ | |
26a6b2e1 | 1202 | CsrResult unifi_card_write16(card_t *card, u32 unifi_addr, u16 data) |
635d2b00 | 1203 | { |
26a6b2e1 | 1204 | u32 sdio_addr; |
635d2b00 GKH |
1205 | CsrResult r; |
1206 | ||
1207 | r = set_page(card, unifi_addr, &sdio_addr); | |
1208 | if (r != CSR_RESULT_SUCCESS) | |
1209 | { | |
1210 | return r; | |
1211 | } | |
1212 | ||
1213 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1214 | card->cmd_prof.cmd52_w16_count++; | |
1215 | #endif | |
1216 | return unifi_write_direct16(card, sdio_addr, data); | |
1217 | } /* unifi_card_write16() */ | |
1218 | ||
1219 | ||
1220 | /* | |
1221 | * --------------------------------------------------------------------------- | |
1222 | * unifi_read32 | |
1223 | * | |
1224 | * Performs a 32-bit read of the given address in shared data memory. | |
1225 | * Set up the shared data memory page register as required. | |
1226 | * | |
1227 | * Arguments: | |
1228 | * card Pointer to card structure. | |
1229 | * unifi_addr UniFi shared-data-memory address to access. | |
1230 | * pdata Pointer to a int variable for the value read. | |
1231 | * | |
1232 | * Returns: | |
1233 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1234 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1235 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1236 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1237 | * --------------------------------------------------------------------------- | |
1238 | */ | |
26a6b2e1 | 1239 | CsrResult unifi_read32(card_t *card, u32 unifi_addr, u32 *pdata) |
635d2b00 | 1240 | { |
26a6b2e1 | 1241 | u32 sdio_addr; |
635d2b00 GKH |
1242 | CsrResult r; |
1243 | ||
1244 | r = set_page(card, unifi_addr, &sdio_addr); | |
1245 | if (r != CSR_RESULT_SUCCESS) | |
1246 | { | |
1247 | return r; | |
1248 | } | |
1249 | ||
1250 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1251 | card->cmd_prof.cmd52_r32_count++; | |
1252 | #endif | |
1253 | return unifi_read_direct32(card, sdio_addr, pdata); | |
1254 | } /* unifi_read32() */ | |
1255 | ||
1256 | ||
1257 | /* | |
1258 | * --------------------------------------------------------------------------- | |
1259 | * unifi_card_readn | |
1260 | * unifi_readnz | |
1261 | * | |
1262 | * Read multiple 8-bit values from the UniFi SDIO interface. | |
1263 | * This function interprets the address as a GenericPointer as | |
1264 | * defined in the UniFi Host Interface Protocol Specification. | |
1265 | * The readnz version of this function will stop when it reads a | |
1266 | * zero octet. | |
1267 | * | |
1268 | * Arguments: | |
1269 | * card Pointer to card structure. | |
1270 | * unifi_addr UniFi shared-data-memory address to access. | |
1271 | * pdata Pointer to which to write data. | |
1272 | * len Number of bytes to read | |
1273 | * | |
1274 | * Returns: | |
1275 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1276 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1277 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1278 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified | |
1279 | * --------------------------------------------------------------------------- | |
1280 | */ | |
26a6b2e1 | 1281 | CsrResult unifi_readn_match(card_t *card, u32 unifi_addr, void *pdata, u16 len, s8 match) |
635d2b00 | 1282 | { |
26a6b2e1 | 1283 | u32 sdio_addr; |
635d2b00 | 1284 | CsrResult r; |
26a6b2e1 | 1285 | u32 num; |
635d2b00 GKH |
1286 | |
1287 | r = set_page(card, unifi_addr, &sdio_addr); | |
1288 | if (r != CSR_RESULT_SUCCESS) | |
1289 | { | |
1290 | return r; | |
1291 | } | |
1292 | ||
1293 | r = unifi_read_directn_match(card, sdio_addr, pdata, len, match, &num); | |
1294 | return r; | |
1295 | } /* unifi_readn_match() */ | |
1296 | ||
1297 | ||
26a6b2e1 | 1298 | CsrResult unifi_card_readn(card_t *card, u32 unifi_addr, void *pdata, u16 len) |
635d2b00 GKH |
1299 | { |
1300 | return unifi_readn_match(card, unifi_addr, pdata, len, -1); | |
1301 | } /* unifi_card_readn() */ | |
1302 | ||
1303 | ||
26a6b2e1 | 1304 | CsrResult unifi_readnz(card_t *card, u32 unifi_addr, void *pdata, u16 len) |
635d2b00 GKH |
1305 | { |
1306 | return unifi_readn_match(card, unifi_addr, pdata, len, 0); | |
1307 | } /* unifi_readnz() */ | |
1308 | ||
1309 | ||
1310 | /* | |
1311 | * --------------------------------------------------------------------------- | |
1312 | * unifi_read_shared_count | |
1313 | * | |
1314 | * Read signal count locations, checking for an SDIO error. The | |
1315 | * signal count locations only contain a valid number if the | |
1316 | * highest bit isn't set. | |
1317 | * | |
1318 | * Arguments: | |
1319 | * card Pointer to card context structure. | |
1320 | * addr Shared-memory address to read. | |
1321 | * | |
1322 | * Returns: | |
1323 | * Value read from memory (0-127) or -1 on error | |
1324 | * --------------------------------------------------------------------------- | |
1325 | */ | |
95e326c2 | 1326 | s32 unifi_read_shared_count(card_t *card, u32 addr) |
635d2b00 | 1327 | { |
7e6f5794 | 1328 | u8 b; |
635d2b00 GKH |
1329 | /* I've increased this count, because I have seen cases where |
1330 | * there were three reads in a row with the top bit set. I'm not | |
1331 | * sure why this might have happened, but I can't see a problem | |
1332 | * with increasing this limit. It's better to take a while to | |
1333 | * recover than to fail. */ | |
1334 | #define SHARED_READ_RETRY_LIMIT 10 | |
95e326c2 | 1335 | s32 i; |
635d2b00 GKH |
1336 | |
1337 | /* | |
1338 | * Get the to-host-signals-written count. | |
1339 | * The top-bit will be set if the firmware was in the process of | |
1340 | * changing the value, in which case we read again. | |
1341 | */ | |
1342 | /* Limit the number of repeats so we don't freeze */ | |
1343 | for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) | |
1344 | { | |
1345 | CsrResult r; | |
1346 | r = unifi_read_8_or_16(card, addr, &b); | |
1347 | if (r != CSR_RESULT_SUCCESS) | |
1348 | { | |
1349 | return -1; | |
1350 | } | |
1351 | if (!(b & 0x80)) | |
1352 | { | |
1353 | /* There is a chance that the MSB may have contained invalid data | |
1354 | * (overflow) at the time it was read. Therefore mask off the MSB. | |
1355 | * This avoids a race between driver read and firmware write of the | |
1356 | * word, the value we need is in the lower 8 bits anway. | |
1357 | */ | |
95e326c2 | 1358 | return (s32)(b & 0xff); |
635d2b00 GKH |
1359 | } |
1360 | } | |
1361 | ||
1362 | return -1; /* this function has changed in WMM mods */ | |
1363 | } /* unifi_read_shared_count() */ | |
1364 | ||
1365 | ||
1366 | /* | |
1367 | * --------------------------------------------------------------------------- | |
1368 | * unifi_writen | |
1369 | * | |
1370 | * Write multiple 8-bit values to the UniFi SDIO interface using CMD52 | |
1371 | * This function interprets the address as a GenericPointer as | |
1372 | * defined in the UniFi Host Interface Protocol Specification. | |
1373 | * | |
1374 | * Arguments: | |
1375 | * card Pointer to card structure. | |
1376 | * unifi_addr UniFi shared-data-memory address to access. | |
1377 | * pdata Pointer to which to write data. | |
1378 | * len Number of bytes to write | |
1379 | * | |
1380 | * Returns: | |
1381 | * 0 on success, non-zero error code on error: | |
1382 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1383 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1384 | * CSR_WIFI_HIP_RESULT_INVALID_VALUE an odd length or length too big. | |
1385 | * --------------------------------------------------------------------------- | |
1386 | */ | |
26a6b2e1 | 1387 | CsrResult unifi_writen(card_t *card, u32 unifi_addr, void *pdata, u16 len) |
635d2b00 | 1388 | { |
26a6b2e1 | 1389 | u32 sdio_addr; |
635d2b00 GKH |
1390 | CsrResult r; |
1391 | ||
1392 | r = set_page(card, unifi_addr, &sdio_addr); | |
1393 | if (r != CSR_RESULT_SUCCESS) | |
1394 | { | |
1395 | return r; | |
1396 | } | |
1397 | ||
1398 | return unifi_write_directn(card, sdio_addr, pdata, len); | |
1399 | } /* unifi_writen() */ | |
1400 | ||
1401 | ||
ab2b8c73 | 1402 | static CsrResult csr_sdio_block_rw(card_t *card, s16 funcnum, |
26a6b2e1 | 1403 | u32 addr, u8 *pdata, |
ab2b8c73 | 1404 | u16 count, s16 dir_is_write) |
635d2b00 GKH |
1405 | { |
1406 | CsrResult csrResult; | |
1407 | ||
1408 | if (dir_is_write == UNIFI_SDIO_READ) | |
1409 | { | |
1410 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
1411 | unifi_debug_log_to_buf("r@%02X#%X=", addr, count); | |
1412 | #endif | |
1413 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1414 | unifi_debug_log_to_buf("R"); | |
1415 | #endif | |
1416 | csrResult = CsrSdioRead(card->sdio_if, addr, pdata, count); | |
1417 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1418 | unifi_debug_log_to_buf("<"); | |
1419 | #endif | |
1420 | } | |
1421 | else | |
1422 | { | |
1423 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
1424 | unifi_debug_log_to_buf("w@%02X#%X=", addr, count); | |
1425 | unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); | |
1426 | #endif | |
1427 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1428 | unifi_debug_log_to_buf("W"); | |
1429 | #endif | |
1430 | csrResult = CsrSdioWrite(card->sdio_if, addr, pdata, count); | |
1431 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) | |
1432 | unifi_debug_log_to_buf(">"); | |
1433 | #endif | |
1434 | } | |
1435 | #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE | |
1436 | card->cmd_prof.cmd53_count++; | |
1437 | #endif | |
1438 | #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) | |
1439 | if (csrResult != CSR_RESULT_SUCCESS) | |
1440 | { | |
1441 | unifi_debug_log_to_buf("error=%X", csrResult); | |
1442 | } | |
1443 | else if (dir_is_write == UNIFI_SDIO_READ) | |
1444 | { | |
1445 | unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); | |
1446 | } | |
1447 | unifi_debug_string_to_buf("\n"); | |
1448 | #endif | |
1449 | return csrResult; /* CSR SDIO (not HIP) error code */ | |
1450 | } | |
1451 | ||
1452 | ||
1453 | /* | |
1454 | * --------------------------------------------------------------------------- | |
1455 | * unifi_bulk_rw | |
1456 | * | |
1457 | * Transfer bulk data to or from the UniFi SDIO interface. | |
1458 | * This function is used to read or write signals and bulk data. | |
1459 | * | |
1460 | * Arguments: | |
1461 | * card Pointer to card structure. | |
1462 | * handle Value to put in the Register Address field of the CMD53 req. | |
1463 | * data Pointer to data to write. | |
1464 | * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE | |
1465 | * | |
1466 | * Returns: | |
1467 | * CSR_RESULT_SUCCESS on success, non-zero error code on error: | |
1468 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1469 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1470 | * | |
1471 | * Notes: | |
1472 | * This function uses SDIO CMD53, which is the block transfer mode. | |
1473 | * --------------------------------------------------------------------------- | |
1474 | */ | |
26a6b2e1 GKH |
1475 | CsrResult unifi_bulk_rw(card_t *card, u32 handle, void *pdata, |
1476 | u32 len, s16 direction) | |
635d2b00 GKH |
1477 | { |
1478 | #define CMD53_RETRIES 3 | |
1479 | /* | |
1480 | * Ideally instead of sleeping, we want to busy wait. | |
1481 | * Currently there is no framework API to do this. When it becomes available, | |
1482 | * we can use it to busy wait using usecs | |
1483 | */ | |
1484 | #define REWIND_RETRIES 15 /* when REWIND_DELAY==1msec, or 250 when REWIND_DELAY==50usecs */ | |
1485 | #define REWIND_POLLING_RETRIES 5 | |
1486 | #define REWIND_DELAY 1 /* msec or 50usecs */ | |
1487 | CsrResult csrResult; /* SDIO error code */ | |
1488 | CsrResult r = CSR_RESULT_SUCCESS; /* HIP error code */ | |
ab2b8c73 GKH |
1489 | s16 retries = CMD53_RETRIES; |
1490 | s16 stat_retries; | |
7e6f5794 | 1491 | u8 stat; |
ab2b8c73 | 1492 | s16 dump_read; |
635d2b00 | 1493 | #ifdef UNIFI_DEBUG |
7e6f5794 | 1494 | u8 *pdata_lsb = ((u8 *)&pdata) + card->lsb; |
635d2b00 GKH |
1495 | #endif |
1496 | #ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS | |
ab2b8c73 | 1497 | static s16 fake_error; |
635d2b00 GKH |
1498 | #endif |
1499 | ||
1500 | dump_read = 0; | |
1501 | #ifdef UNIFI_DEBUG | |
1502 | if (*pdata_lsb & 1) | |
1503 | { | |
1504 | unifi_notice(card->ospriv, "CD53 request on a unaligned buffer (addr: 0x%X) dir %s-Host\n", | |
1505 | pdata, (direction == UNIFI_SDIO_READ)?"To" : "From"); | |
1506 | if (direction == UNIFI_SDIO_WRITE) | |
1507 | { | |
8c87f69a | 1508 | dump(pdata, (u16)len); |
635d2b00 GKH |
1509 | } |
1510 | else | |
1511 | { | |
1512 | dump_read = 1; | |
1513 | } | |
1514 | } | |
1515 | #endif | |
1516 | ||
1517 | /* Defensive checks */ | |
1518 | if (!pdata) | |
1519 | { | |
1520 | unifi_error(card->ospriv, "Null pdata for unifi_bulk_rw() len: %d\n", len); | |
1521 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
1522 | } | |
1523 | if ((len & 1) || (len > 0xffff)) | |
1524 | { | |
1525 | unifi_error(card->ospriv, "Impossible CMD53 length requested: %d\n", len); | |
1526 | return CSR_WIFI_HIP_RESULT_INVALID_VALUE; | |
1527 | } | |
1528 | ||
1529 | while (1) | |
1530 | { | |
1531 | csrResult = csr_sdio_block_rw(card, card->function, handle, | |
8c87f69a | 1532 | (u8 *)pdata, (u16)len, |
635d2b00 GKH |
1533 | direction); |
1534 | if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) | |
1535 | { | |
1536 | return CSR_WIFI_HIP_RESULT_NO_DEVICE; | |
1537 | } | |
1538 | #ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS | |
1539 | if (++fake_error > 100) | |
1540 | { | |
1541 | fake_error = 90; | |
1542 | unifi_warning(card->ospriv, "Faking a CMD53 error,\n"); | |
1543 | if (csrResult == CSR_RESULT_SUCCESS) | |
1544 | { | |
1545 | csrResult = CSR_RESULT_FAILURE; | |
1546 | } | |
1547 | } | |
1548 | #endif | |
1549 | if (csrResult == CSR_RESULT_SUCCESS) | |
1550 | { | |
1551 | if (dump_read) | |
1552 | { | |
8c87f69a | 1553 | dump(pdata, (u16)len); |
635d2b00 GKH |
1554 | } |
1555 | break; | |
1556 | } | |
1557 | ||
1558 | /* | |
1559 | * At this point the SDIO driver should have written the I/O Abort | |
1560 | * register to notify UniFi that the command has failed. | |
1561 | * UniFi-1 and UniFi-2 (not UF6xxx) use the same register to store the | |
1562 | * Deep Sleep State. This means we have to restore the Deep Sleep | |
1563 | * State (AWAKE in any case since we can not perform a CD53 in any other | |
1564 | * state) by rewriting the I/O Abort register to its previous value. | |
1565 | */ | |
1566 | if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) | |
1567 | { | |
95edd09e | 1568 | (void)unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); |
635d2b00 GKH |
1569 | } |
1570 | ||
1571 | /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted | |
1572 | * then stop retrying | |
1573 | */ | |
1574 | if (!retryable_sdio_error(csrResult)) | |
1575 | { | |
1576 | unifi_error(card->ospriv, "Fatal error in a CMD53 transfer\n"); | |
1577 | break; | |
1578 | } | |
1579 | ||
1580 | /* | |
1581 | * These happen from time to time, try again | |
1582 | */ | |
1583 | if (--retries == 0) | |
1584 | { | |
1585 | break; | |
1586 | } | |
1587 | ||
1588 | unifi_trace(card->ospriv, UDBG4, | |
1589 | "Error in a CMD53 transfer, retrying (h:%d,l:%u)...\n", | |
ab2b8c73 | 1590 | (s16)handle & 0xff, len); |
635d2b00 GKH |
1591 | |
1592 | /* The transfer failed, rewind and try again */ | |
1593 | r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 8, | |
7e6f5794 | 1594 | (u8)(handle & 0xff)); |
635d2b00 GKH |
1595 | if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) |
1596 | { | |
1597 | return r; | |
1598 | } | |
1599 | if (r != CSR_RESULT_SUCCESS) | |
1600 | { | |
1601 | /* | |
1602 | * If we can't even do CMD52 (register read/write) then | |
1603 | * stop here. | |
1604 | */ | |
1605 | unifi_error(card->ospriv, "Failed to write REWIND cmd\n"); | |
1606 | return r; | |
1607 | } | |
1608 | ||
1609 | /* Signal the UniFi to look for the rewind request. */ | |
1610 | r = CardGenInt(card); | |
1611 | if (r != CSR_RESULT_SUCCESS) | |
1612 | { | |
1613 | return r; | |
1614 | } | |
1615 | ||
1616 | /* Wait for UniFi to acknowledge the rewind */ | |
1617 | stat_retries = REWIND_RETRIES; | |
1618 | while (1) | |
1619 | { | |
1620 | r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 8, &stat); | |
1621 | if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) | |
1622 | { | |
1623 | return r; | |
1624 | } | |
1625 | if (r != CSR_RESULT_SUCCESS) | |
1626 | { | |
1627 | unifi_error(card->ospriv, "Failed to read REWIND status\n"); | |
1628 | return CSR_RESULT_FAILURE; | |
1629 | } | |
1630 | ||
1631 | if (stat == 0) | |
1632 | { | |
1633 | break; | |
1634 | } | |
1635 | if (--stat_retries == 0) | |
1636 | { | |
1637 | unifi_error(card->ospriv, "Timeout waiting for REWIND ready\n"); | |
1638 | return CSR_RESULT_FAILURE; | |
1639 | } | |
1640 | ||
1641 | /* Poll for the ack a few times */ | |
1642 | if (stat_retries < REWIND_RETRIES - REWIND_POLLING_RETRIES) | |
1643 | { | |
1644 | CsrThreadSleep(REWIND_DELAY); | |
1645 | } | |
1646 | } | |
1647 | } | |
1648 | ||
1649 | /* The call to csr_sdio_block_rw() still failed after retrying */ | |
1650 | if (csrResult != CSR_RESULT_SUCCESS) | |
1651 | { | |
1652 | unifi_error(card->ospriv, "Block %s failed after %d retries\n", | |
1653 | (direction == UNIFI_SDIO_READ)?"read" : "write", | |
1654 | CMD53_RETRIES - retries); | |
1655 | /* Report any SDIO error as a general i/o error */ | |
1656 | return CSR_RESULT_FAILURE; | |
1657 | } | |
1658 | ||
1659 | /* Collect some stats */ | |
1660 | if (direction == UNIFI_SDIO_READ) | |
1661 | { | |
1662 | card->sdio_bytes_read += len; | |
1663 | } | |
1664 | else | |
1665 | { | |
1666 | card->sdio_bytes_written += len; | |
1667 | } | |
1668 | ||
1669 | return CSR_RESULT_SUCCESS; | |
1670 | } /* unifi_bulk_rw() */ | |
1671 | ||
1672 | ||
1673 | /* | |
1674 | * --------------------------------------------------------------------------- | |
1675 | * unifi_bulk_rw_noretry | |
1676 | * | |
1677 | * Transfer bulk data to or from the UniFi SDIO interface. | |
1678 | * This function is used to read or write signals and bulk data. | |
1679 | * | |
1680 | * Arguments: | |
1681 | * card Pointer to card structure. | |
1682 | * handle Value to put in the Register Address field of | |
1683 | * the CMD53 req. | |
1684 | * data Pointer to data to write. | |
1685 | * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE | |
1686 | * | |
1687 | * Returns: | |
1688 | * 0 on success, non-zero error code on error: | |
1689 | * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected | |
1690 | * CSR_RESULT_FAILURE an SDIO error occurred | |
1691 | * | |
1692 | * Notes: | |
1693 | * This function uses SDIO CMD53, which is the block transfer mode. | |
1694 | * --------------------------------------------------------------------------- | |
1695 | */ | |
26a6b2e1 GKH |
1696 | CsrResult unifi_bulk_rw_noretry(card_t *card, u32 handle, void *pdata, |
1697 | u32 len, s16 direction) | |
635d2b00 GKH |
1698 | { |
1699 | CsrResult csrResult; | |
1700 | ||
1701 | csrResult = csr_sdio_block_rw(card, card->function, handle, | |
8c87f69a | 1702 | (u8 *)pdata, (u16)len, direction); |
635d2b00 GKH |
1703 | if (csrResult != CSR_RESULT_SUCCESS) |
1704 | { | |
1705 | unifi_error(card->ospriv, "Block %s failed\n", | |
1706 | (direction == UNIFI_SDIO_READ)?"read" : "write"); | |
1707 | return csrResult; | |
1708 | } | |
1709 | ||
1710 | return CSR_RESULT_SUCCESS; | |
1711 | } /* unifi_bulk_rw_noretry() */ | |
1712 | ||
1713 |