diff options
Diffstat (limited to 'drivers/staging/csr/init_hw.c')
-rw-r--r-- | drivers/staging/csr/init_hw.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/staging/csr/init_hw.c b/drivers/staging/csr/init_hw.c new file mode 100644 index 000000000000..3b8a4babf9a6 --- /dev/null +++ b/drivers/staging/csr/init_hw.c @@ -0,0 +1,108 @@ +/* + * --------------------------------------------------------------------------- + * FILE: init_hw.c + * + * PURPOSE: + * Use the HIP core lib to initialise the UniFi chip. + * It is part of the porting exercise in Linux. + * + * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + +#define MAX_INIT_ATTEMPTS 4 + +extern int led_mask; + + +/* + * --------------------------------------------------------------------------- + * uf_init_hw + * + * Resets hardware, downloads and initialises f/w. + * This function demonstrates how to use the HIP core lib API + * to implement the SME unifi_sys_wifi_on_req() part of the SYS API. + * + * In a simple implementation, all this function needs to do is call + * unifi_init_card() and then unifi_card_info(). + * In the Linux implementation, it will retry to initialise UniFi or + * try to debug the reasons if unifi_init_card() returns an error. + * + * Arguments: + * ospriv Pointer to OS driver structure for the device. + * + * Returns: + * O on success, non-zero otherwise. + * + * --------------------------------------------------------------------------- + */ +int +uf_init_hw(unifi_priv_t *priv) +{ + int attempts = 0; + int priv_instance; + CsrResult csrResult = CSR_RESULT_FAILURE; + + priv_instance = uf_find_priv(priv); + if (priv_instance == -1) { + unifi_warning(priv, "uf_init_hw: Unknown priv instance, will use fw_init[0]\n"); + priv_instance = 0; + } + + while (1) { + if (attempts > MAX_INIT_ATTEMPTS) { + unifi_error(priv, "Failed to initialise UniFi after %d attempts, " + "giving up.\n", + attempts); + break; + } + attempts++; + + unifi_info(priv, "Initialising UniFi, attempt %d\n", attempts); + + if (fw_init[priv_instance] > 0) { + unifi_notice(priv, "f/w init prevented by module parameter\n"); + break; + } else if (fw_init[priv_instance] == 0) { + fw_init[priv_instance] ++; + } + + /* + * Initialise driver core. This will perform a reset of UniFi + * internals, but not the SDIO CCCR. + */ + CsrSdioClaim(priv->sdio); + csrResult = unifi_init_card(priv->card, led_mask); + CsrSdioRelease(priv->sdio); + + if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) { + return CsrHipResultToStatus(csrResult); + } + if (csrResult == CSR_WIFI_HIP_RESULT_NOT_FOUND) { + unifi_error(priv, "Firmware file required, but not found.\n"); + return CsrHipResultToStatus(csrResult); + } + if (csrResult != CSR_RESULT_SUCCESS) { + /* failed. Reset h/w and try again */ + unifi_error(priv, "Failed to initialise UniFi chip.\n"); + continue; + } + + /* Get the version information from the lib_hip */ + unifi_card_info(priv->card, &priv->card_info); + + return CsrHipResultToStatus(csrResult); + } + + return CsrHipResultToStatus(csrResult); + +} /* uf_init_hw */ + + |