2 * ***************************************************************************
5 * PURPOSE: putest related functions.
7 * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd.
9 * Refer to LICENSE.txt included with this source code for details on
12 * ***************************************************************************
15 #include <linux/vmalloc.h>
16 #include <linux/firmware.h>
18 #include "unifi_priv.h"
19 #include "csr_wifi_hip_chiphelper.h"
21 #define UNIFI_PROC_BOTH 3
24 int unifi_putest_cmd52_read(unifi_priv_t
*priv
, unsigned char *arg
)
26 struct unifi_putest_cmd52 cmd52_params
;
28 unsigned int cmd_param_size
;
31 unsigned char ret_buffer
[32];
35 arg_pos
= (u8
*)(((unifi_putest_command_t
*)arg
) + 1);
36 if (get_user(cmd_param_size
, (int*)arg_pos
)) {
38 "unifi_putest_cmd52_read: Failed to get the argument\n");
42 if (cmd_param_size
!= sizeof(struct unifi_putest_cmd52
)) {
44 "unifi_putest_cmd52_read: cmd52 struct mismatch\n");
48 arg_pos
+= sizeof(unsigned int);
49 if (copy_from_user(&cmd52_params
,
51 sizeof(struct unifi_putest_cmd52
))) {
53 "unifi_putest_cmd52_read: Failed to get the cmd52 params\n");
57 unifi_trace(priv
, UDBG2
, "cmd52r: func=%d addr=0x%x ",
58 cmd52_params
.funcnum
, cmd52_params
.addr
);
61 CsrSdioClaim(priv
->sdio
);
63 if (cmd52_params
.funcnum
== 0) {
64 csrResult
= CsrSdioF0Read8(priv
->sdio
, cmd52_params
.addr
, &cmd52_params
.data
);
66 csrResult
= CsrSdioRead8(priv
->sdio
, cmd52_params
.addr
, &cmd52_params
.data
);
68 } while (--retries
&& ((csrResult
== CSR_SDIO_RESULT_CRC_ERROR
) || (csrResult
== CSR_SDIO_RESULT_TIMEOUT
)));
69 CsrSdioRelease(priv
->sdio
);
71 if (csrResult
!= CSR_RESULT_SUCCESS
) {
73 "\nunifi_putest_cmd52_read: Read8() failed (csrResult=0x%x)\n", csrResult
);
76 unifi_trace(priv
, UDBG2
, "data=%d\n", cmd52_params
.data
);
78 /* Copy the info to the out buffer */
79 *(unifi_putest_command_t
*)ret_buffer
= UNIFI_PUTEST_CMD52_READ
;
80 ret_buffer_pos
= (u8
*)(((unifi_putest_command_t
*)ret_buffer
) + 1);
81 *(unsigned int*)ret_buffer_pos
= sizeof(struct unifi_putest_cmd52
);
82 ret_buffer_pos
+= sizeof(unsigned int);
83 memcpy(ret_buffer_pos
, &cmd52_params
, sizeof(struct unifi_putest_cmd52
));
84 ret_buffer_pos
+= sizeof(struct unifi_putest_cmd52
);
86 r
= copy_to_user((void*)arg
,
88 ret_buffer_pos
- ret_buffer
);
91 "unifi_putest_cmd52_read: Failed to return the data\n");
99 int unifi_putest_cmd52_write(unifi_priv_t
*priv
, unsigned char *arg
)
101 struct unifi_putest_cmd52 cmd52_params
;
103 unsigned int cmd_param_size
;
107 arg_pos
= (u8
*)(((unifi_putest_command_t
*)arg
) + 1);
108 if (get_user(cmd_param_size
, (int*)arg_pos
)) {
110 "unifi_putest_cmd52_write: Failed to get the argument\n");
114 if (cmd_param_size
!= sizeof(struct unifi_putest_cmd52
)) {
116 "unifi_putest_cmd52_write: cmd52 struct mismatch\n");
120 arg_pos
+= sizeof(unsigned int);
121 if (copy_from_user(&cmd52_params
,
123 sizeof(struct unifi_putest_cmd52
))) {
125 "unifi_putest_cmd52_write: Failed to get the cmd52 params\n");
129 unifi_trace(priv
, UDBG2
, "cmd52w: func=%d addr=0x%x data=%d\n",
130 cmd52_params
.funcnum
, cmd52_params
.addr
, cmd52_params
.data
);
133 CsrSdioClaim(priv
->sdio
);
135 if (cmd52_params
.funcnum
== 0) {
136 csrResult
= CsrSdioF0Write8(priv
->sdio
, cmd52_params
.addr
, cmd52_params
.data
);
138 csrResult
= CsrSdioWrite8(priv
->sdio
, cmd52_params
.addr
, cmd52_params
.data
);
140 } while (--retries
&& ((csrResult
== CSR_SDIO_RESULT_CRC_ERROR
) || (csrResult
== CSR_SDIO_RESULT_TIMEOUT
)));
141 CsrSdioRelease(priv
->sdio
);
143 if (csrResult
!= CSR_RESULT_SUCCESS
) {
145 "unifi_putest_cmd52_write: Write8() failed (csrResult=0x%x)\n", csrResult
);
152 int unifi_putest_gp_read16(unifi_priv_t
*priv
, unsigned char *arg
)
154 struct unifi_putest_gp_rw16 gp_r16_params
;
156 unsigned int cmd_param_size
;
159 unsigned char ret_buffer
[32];
162 arg_pos
= (u8
*)(((unifi_putest_command_t
*)arg
) + 1);
163 if (get_user(cmd_param_size
, (int*)arg_pos
)) {
165 "unifi_putest_gp_read16: Failed to get the argument\n");
169 if (cmd_param_size
!= sizeof(struct unifi_putest_gp_rw16
)) {
171 "unifi_putest_gp_read16: struct mismatch\n");
175 arg_pos
+= sizeof(unsigned int);
176 if (copy_from_user(&gp_r16_params
,
178 sizeof(struct unifi_putest_gp_rw16
))) {
180 "unifi_putest_gp_read16: Failed to get the params\n");
183 CsrSdioClaim(priv
->sdio
);
184 csrResult
= unifi_card_read16(priv
->card
, gp_r16_params
.addr
, &gp_r16_params
.data
);
185 CsrSdioRelease(priv
->sdio
);
186 if (csrResult
!= CSR_RESULT_SUCCESS
) {
188 "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params
.addr
, csrResult
);
192 unifi_trace(priv
, UDBG2
, "gp_r16: GP=0x%08x, data=0x%04x\n", gp_r16_params
.addr
, gp_r16_params
.data
);
194 /* Copy the info to the out buffer */
195 *(unifi_putest_command_t
*)ret_buffer
= UNIFI_PUTEST_GP_READ16
;
196 ret_buffer_pos
= (u8
*)(((unifi_putest_command_t
*)ret_buffer
) + 1);
197 *(unsigned int*)ret_buffer_pos
= sizeof(struct unifi_putest_gp_rw16
);
198 ret_buffer_pos
+= sizeof(unsigned int);
199 memcpy(ret_buffer_pos
, &gp_r16_params
, sizeof(struct unifi_putest_gp_rw16
));
200 ret_buffer_pos
+= sizeof(struct unifi_putest_gp_rw16
);
202 r
= copy_to_user((void*)arg
,
204 ret_buffer_pos
- ret_buffer
);
207 "unifi_putest_gp_read16: Failed to return the data\n");
214 int unifi_putest_gp_write16(unifi_priv_t
*priv
, unsigned char *arg
)
216 struct unifi_putest_gp_rw16 gp_w16_params
;
218 unsigned int cmd_param_size
;
221 arg_pos
= (u8
*)(((unifi_putest_command_t
*)arg
) + 1);
222 if (get_user(cmd_param_size
, (int*)arg_pos
)) {
224 "unifi_putest_gp_write16: Failed to get the argument\n");
228 if (cmd_param_size
!= sizeof(struct unifi_putest_gp_rw16
)) {
230 "unifi_putest_gp_write16: struct mismatch\n");
234 arg_pos
+= sizeof(unsigned int);
235 if (copy_from_user(&gp_w16_params
,
237 sizeof(struct unifi_putest_gp_rw16
))) {
239 "unifi_putest_gp_write16: Failed to get the params\n");
243 unifi_trace(priv
, UDBG2
, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params
.addr
, gp_w16_params
.data
);
244 CsrSdioClaim(priv
->sdio
);
245 csrResult
= unifi_card_write16(priv
->card
, gp_w16_params
.addr
, gp_w16_params
.data
);
246 CsrSdioRelease(priv
->sdio
);
247 if (csrResult
!= CSR_RESULT_SUCCESS
) {
249 "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params
.addr
, csrResult
);
256 int unifi_putest_set_sdio_clock(unifi_priv_t
*priv
, unsigned char *arg
)
258 int sdio_clock_speed
;
261 if (get_user(sdio_clock_speed
, (int*)(((unifi_putest_command_t
*)arg
) + 1))) {
263 "unifi_putest_set_sdio_clock: Failed to get the argument\n");
267 unifi_trace(priv
, UDBG2
, "set sdio clock: %d KHz\n", sdio_clock_speed
);
269 CsrSdioClaim(priv
->sdio
);
270 csrResult
= CsrSdioMaxBusClockFrequencySet(priv
->sdio
, sdio_clock_speed
* 1000);
271 CsrSdioRelease(priv
->sdio
);
272 if (csrResult
!= CSR_RESULT_SUCCESS
) {
274 "unifi_putest_set_sdio_clock: Set clock failed (csrResult=0x%x)\n", csrResult
);
282 int unifi_putest_start(unifi_priv_t
*priv
, unsigned char *arg
)
286 int already_in_test
= priv
->ptest_mode
;
288 /* Ensure that sme_sys_suspend() doesn't power down the chip because:
289 * 1) Power is needed anyway for ptest.
290 * 2) The app code uses the START ioctl as a reset, so it gets called
291 * multiple times. If the app stops the XAPs, but the power_down/up
292 * sequence doesn't actually power down the chip, there can be problems
293 * resetting, because part of the power_up sequence disables function 1
295 priv
->ptest_mode
= 1;
297 /* Suspend the SME and UniFi */
299 r
= sme_sys_suspend(priv
);
302 "unifi_putest_start: failed to suspend UniFi\n");
307 /* Application may have stopped the XAPs, but they are needed for reset */
308 if (already_in_test
) {
309 CsrSdioClaim(priv
->sdio
);
310 csrResult
= unifi_start_processors(priv
->card
);
311 CsrSdioRelease(priv
->sdio
);
312 if (csrResult
!= CSR_RESULT_SUCCESS
) {
313 unifi_error(priv
, "Failed to start XAPs. Hard reset required.\n");
316 /* Ensure chip is powered for the case where there's no unifi_helper */
317 CsrSdioClaim(priv
->sdio
);
318 csrResult
= CsrSdioPowerOn(priv
->sdio
);
319 CsrSdioRelease(priv
->sdio
);
320 if (csrResult
!= CSR_RESULT_SUCCESS
) {
321 unifi_error(priv
, "CsrSdioPowerOn csrResult = %d\n", csrResult
);
324 CsrSdioClaim(priv
->sdio
);
325 csrResult
= unifi_init(priv
->card
);
326 CsrSdioRelease(priv
->sdio
);
327 if (csrResult
!= CSR_RESULT_SUCCESS
) {
329 "unifi_putest_start: failed to init UniFi\n");
330 return CsrHipResultToStatus(csrResult
);
337 int unifi_putest_stop(unifi_priv_t
*priv
, unsigned char *arg
)
342 /* Application may have stopped the XAPs, but they are needed for reset */
343 CsrSdioClaim(priv
->sdio
);
344 csrResult
= unifi_start_processors(priv
->card
);
345 CsrSdioRelease(priv
->sdio
);
346 if (csrResult
!= CSR_RESULT_SUCCESS
) {
347 unifi_error(priv
, "Failed to start XAPs. Hard reset required.\n");
350 /* PUTEST_STOP is also used to resume the XAPs after SME coredump.
351 * Don't power off the chip, leave that to the normal wifi-off which is
352 * about to carry on. No need to resume the SME either, as it wasn't suspended.
354 if (priv
->coredump_mode
) {
355 priv
->coredump_mode
= 0;
359 /* At this point function 1 is enabled and the XAPs are running, so it is
360 * safe to let the card power down. Power is restored later, asynchronously,
361 * during the wifi_on requested by the SME.
363 CsrSdioClaim(priv
->sdio
);
364 CsrSdioPowerOff(priv
->sdio
);
365 CsrSdioRelease(priv
->sdio
);
367 /* Resume the SME and UniFi */
369 r
= sme_sys_resume(priv
);
372 "unifi_putest_stop: failed to resume SME\n");
375 priv
->ptest_mode
= 0;
381 int unifi_putest_dl_fw(unifi_priv_t
*priv
, unsigned char *arg
)
383 #define UF_PUTEST_MAX_FW_FILE_NAME 16
384 #define UNIFI_MAX_FW_PATH_LEN 32
385 unsigned int fw_name_length
;
386 unsigned char fw_name
[UF_PUTEST_MAX_FW_FILE_NAME
+1];
387 unsigned char *name_buffer
;
389 char fw_path
[UNIFI_MAX_FW_PATH_LEN
];
390 const struct firmware
*fw_entry
;
391 struct dlpriv temp_fw_sta
;
395 /* Get the f/w file name length */
396 if (get_user(fw_name_length
, (unsigned int*)(((unifi_putest_command_t
*)arg
) + 1))) {
398 "unifi_putest_dl_fw: Failed to get the length argument\n");
402 unifi_trace(priv
, UDBG2
, "unifi_putest_dl_fw: file name size = %d\n", fw_name_length
);
404 /* Sanity check for the f/w file name length */
405 if (fw_name_length
> UF_PUTEST_MAX_FW_FILE_NAME
) {
407 "unifi_putest_dl_fw: F/W file name is too long\n");
411 /* Get the f/w file name */
412 name_buffer
= ((unsigned char*)arg
) + sizeof(unifi_putest_command_t
) + sizeof(unsigned int);
413 if (copy_from_user(fw_name
, (void*)name_buffer
, fw_name_length
)) {
414 unifi_error(priv
, "unifi_putest_dl_fw: Failed to get the file name\n");
417 fw_name
[fw_name_length
] = '\0';
418 unifi_trace(priv
, UDBG2
, "unifi_putest_dl_fw: file = %s\n", fw_name
);
420 /* Keep the existing f/w to a temp, we need to restore it later */
421 temp_fw_sta
= priv
->fw_sta
;
423 /* Get the putest f/w */
424 postfix
= priv
->instance
;
425 scnprintf(fw_path
, UNIFI_MAX_FW_PATH_LEN
, "unifi-sdio-%d/%s",
427 r
= request_firmware(&fw_entry
, fw_path
, priv
->unifi_device
);
429 priv
->fw_sta
.fw_desc
= (void *)fw_entry
;
430 priv
->fw_sta
.dl_data
= fw_entry
->data
;
431 priv
->fw_sta
.dl_len
= fw_entry
->size
;
433 unifi_error(priv
, "Firmware file not available\n");
437 /* Application may have stopped the XAPs, but they are needed for reset */
438 CsrSdioClaim(priv
->sdio
);
439 csrResult
= unifi_start_processors(priv
->card
);
440 CsrSdioRelease(priv
->sdio
);
441 if (csrResult
!= CSR_RESULT_SUCCESS
) {
442 unifi_error(priv
, "Failed to start XAPs. Hard reset required.\n");
445 /* Download the f/w. On UF6xxx this will cause the f/w file to convert
446 * into patch format and download via the ROM boot loader
448 CsrSdioClaim(priv
->sdio
);
449 csrResult
= unifi_download(priv
->card
, 0x0c00);
450 CsrSdioRelease(priv
->sdio
);
451 if (csrResult
!= CSR_RESULT_SUCCESS
) {
453 "unifi_putest_dl_fw: failed to download the f/w\n");
457 /* Free the putest f/w... */
459 uf_release_firmware(priv
, &priv
->fw_sta
);
460 /* ... and restore the original f/w */
461 priv
->fw_sta
= temp_fw_sta
;
463 return CsrHipResultToStatus(csrResult
);
467 int unifi_putest_dl_fw_buff(unifi_priv_t
*priv
, unsigned char *arg
)
469 unsigned int fw_length
;
470 unsigned char *fw_buf
= NULL
;
471 unsigned char *fw_user_ptr
;
472 struct dlpriv temp_fw_sta
;
475 /* Get the f/w buffer length */
476 if (get_user(fw_length
, (unsigned int*)(((unifi_putest_command_t
*)arg
) + 1))) {
478 "unifi_putest_dl_fw_buff: Failed to get the length arg\n");
482 unifi_trace(priv
, UDBG2
, "unifi_putest_dl_fw_buff: size = %d\n", fw_length
);
484 /* Sanity check for the buffer length */
485 if (fw_length
== 0 || fw_length
> 0xfffffff) {
487 "unifi_putest_dl_fw_buff: buffer length bad %u\n", fw_length
);
491 /* Buffer for kernel copy of the f/w image */
492 fw_buf
= kmalloc(fw_length
, GFP_KERNEL
);
494 unifi_error(priv
, "unifi_putest_dl_fw_buff: malloc fail\n");
498 /* Get the f/w image */
499 fw_user_ptr
= ((unsigned char*)arg
) + sizeof(unifi_putest_command_t
) + sizeof(unsigned int);
500 if (copy_from_user(fw_buf
, (void*)fw_user_ptr
, fw_length
)) {
501 unifi_error(priv
, "unifi_putest_dl_fw_buff: Failed to get the buffer\n");
506 /* Save the existing f/w to a temp, we need to restore it later */
507 temp_fw_sta
= priv
->fw_sta
;
509 /* Setting fw_desc NULL indicates to the core that no f/w file was loaded
510 * via the kernel request_firmware() mechanism. This indicates to the core
511 * that it shouldn't call release_firmware() after the download is done.
513 priv
->fw_sta
.fw_desc
= NULL
; /* No OS f/w resource */
514 priv
->fw_sta
.dl_data
= fw_buf
;
515 priv
->fw_sta
.dl_len
= fw_length
;
517 /* Application may have stopped the XAPs, but they are needed for reset */
518 CsrSdioClaim(priv
->sdio
);
519 csrResult
= unifi_start_processors(priv
->card
);
520 CsrSdioRelease(priv
->sdio
);
521 if (csrResult
!= CSR_RESULT_SUCCESS
) {
522 unifi_error(priv
, "Failed to start XAPs. Hard reset required.\n");
525 /* Download the f/w. On UF6xxx this will cause the f/w file to convert
526 * into patch format and download via the ROM boot loader
528 CsrSdioClaim(priv
->sdio
);
529 csrResult
= unifi_download(priv
->card
, 0x0c00);
530 CsrSdioRelease(priv
->sdio
);
531 if (csrResult
!= CSR_RESULT_SUCCESS
) {
533 "unifi_putest_dl_fw_buff: failed to download the f/w\n");
538 /* Finished with the putest f/w, so restore the station f/w */
539 priv
->fw_sta
= temp_fw_sta
;
542 return CsrHipResultToStatus(csrResult
);
546 int unifi_putest_coredump_prepare(unifi_priv_t
*priv
, unsigned char *arg
)
552 unifi_info(priv
, "Preparing for SDIO coredump\n");
553 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE)
554 unifi_debug_buf_dump();
557 /* Sanity check that userspace hasn't called a PUTEST_START, because that
558 * would have reset UniFi, potentially power cycling it and losing context
560 if (priv
->ptest_mode
) {
561 unifi_error(priv
, "PUTEST_START shouldn't be used before a coredump\n");
564 /* Flag that the userspace has requested coredump. Even if this preparation
565 * fails, the SME will call PUTEST_STOP to tidy up.
567 priv
->coredump_mode
= 1;
569 for (i
= 0; i
< 3; i
++) {
570 CsrSdioClaim(priv
->sdio
);
571 r
= CsrSdioRead16(priv
->sdio
, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION
*2, &data_u16
);
572 CsrSdioRelease(priv
->sdio
);
573 if (r
!= CSR_RESULT_SUCCESS
) {
574 unifi_info(priv
, "Failed to read chip version! Try %d\n", i
);
576 /* First try, re-enable function which may have been disabled by f/w panic */
578 unifi_info(priv
, "Try function enable\n");
579 CsrSdioClaim(priv
->sdio
);
580 r
= CsrSdioFunctionEnable(priv
->sdio
);
581 CsrSdioRelease(priv
->sdio
);
582 if (r
!= CSR_RESULT_SUCCESS
) {
583 unifi_error(priv
, "CsrSdioFunctionEnable failed %d\n", r
);
588 /* Subsequent tries, reset */
590 /* Set clock speed low */
591 CsrSdioClaim(priv
->sdio
);
592 r
= CsrSdioMaxBusClockFrequencySet(priv
->sdio
, UNIFI_SDIO_CLOCK_SAFE_HZ
);
593 CsrSdioRelease(priv
->sdio
);
594 if (r
!= CSR_RESULT_SUCCESS
) {
595 unifi_error(priv
, "CsrSdioMaxBusClockFrequencySet() failed %d\n", r
);
598 /* Card software reset */
599 CsrSdioClaim(priv
->sdio
);
600 r
= unifi_card_hard_reset(priv
->card
);
601 CsrSdioRelease(priv
->sdio
);
602 if (r
!= CSR_RESULT_SUCCESS
) {
603 unifi_error(priv
, "unifi_card_hard_reset() failed %d\n", r
);
606 unifi_info(priv
, "Read chip version of 0x%04x\n", data_u16
);
611 if (r
!= CSR_RESULT_SUCCESS
) {
612 unifi_error(priv
, "Failed to prepare chip\n");
616 /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at
617 * Raw SDIO deinit, to resume them.
619 CsrSdioClaim(priv
->sdio
);
620 r
= unifi_card_stop_processor(priv
->card
, UNIFI_PROC_BOTH
);
621 CsrSdioRelease(priv
->sdio
);
622 if (r
!= CSR_RESULT_SUCCESS
) {
623 unifi_error(priv
, "Failed to stop processors\n");
629 int unifi_putest_cmd52_block_read(unifi_priv_t
*priv
, unsigned char *arg
)
631 struct unifi_putest_block_cmd52_r block_cmd52
;
633 unsigned int cmd_param_size
;
635 u8
*block_local_buffer
;
637 arg_pos
= (u8
*)(((unifi_putest_command_t
*)arg
) + 1);
638 if (get_user(cmd_param_size
, (int*)arg_pos
)) {
640 "cmd52r_block: Failed to get the argument\n");
644 if (cmd_param_size
!= sizeof(struct unifi_putest_block_cmd52_r
)) {
646 "cmd52r_block: cmd52 struct mismatch\n");
650 arg_pos
+= sizeof(unsigned int);
651 if (copy_from_user(&block_cmd52
,
653 sizeof(struct unifi_putest_block_cmd52_r
))) {
655 "cmd52r_block: Failed to get the cmd52 params\n");
659 unifi_trace(priv
, UDBG2
, "cmd52r_block: func=%d addr=0x%x len=0x%x ",
660 block_cmd52
.funcnum
, block_cmd52
.addr
, block_cmd52
.length
);
662 block_local_buffer
= vmalloc(block_cmd52
.length
);
663 if (block_local_buffer
== NULL
) {
664 unifi_error(priv
, "cmd52r_block: Failed to allocate buffer\n");
668 CsrSdioClaim(priv
->sdio
);
669 r
= unifi_card_readn(priv
->card
, block_cmd52
.addr
, block_local_buffer
, block_cmd52
.length
);
670 CsrSdioRelease(priv
->sdio
);
671 if (r
!= CSR_RESULT_SUCCESS
) {
672 unifi_error(priv
, "cmd52r_block: unifi_readn failed\n");
676 if (copy_to_user((void*)block_cmd52
.data
,
678 block_cmd52
.length
)) {
680 "cmd52r_block: Failed to return the data\n");