summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/eswin/sdio/fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/eswin/sdio/fw.c')
-rw-r--r--drivers/net/wireless/eswin/sdio/fw.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/drivers/net/wireless/eswin/sdio/fw.c b/drivers/net/wireless/eswin/sdio/fw.c
new file mode 100644
index 000000000000..9d6bab28d7e8
--- /dev/null
+++ b/drivers/net/wireless/eswin/sdio/fw.c
@@ -0,0 +1,158 @@
+/**
+******************************************************************************
+*
+* @file fw.c
+*
+* @brief ecrnx sdio firmware download functions
+*
+* Copyright (C) ESWIN 2015-2020
+*
+******************************************************************************
+*/
+
+#include <linux/firmware.h>
+#include "core.h"
+#include "sdio.h"
+#include "fw_head_check.h"
+
+extern char *fw_name;
+
+
+void eswin_fw_file_download(struct eswin *tr)
+{
+ int ret;
+ unsigned int length_all;
+ unsigned char length_str[9]={0};
+ unsigned int lengthLeft, lengthSend, offset = HEAD_SIZE;
+ const u8 * dataAddr;
+ struct sk_buff *skb;
+ int file_num = 0;
+ unsigned int file_load_addr[3] = {0x10000U, 0x60800U, 0x80000U}; // ilm addr; dlm addr offset 0x800 for bootrom log; iram0 addr
+
+ char str_sync[4] = {0x63, 0x6E, 0x79, 0x73};
+ char str_cfg[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}; // default for sync
+
+ skb = dev_alloc_skb(1024);
+
+ ECRNX_PRINT("%s entry!!", __func__);
+
+
+ /* 1 sync */
+ memcpy(skb->data, str_sync, 4);
+ tr->ops->write(tr, skb->data, 4);
+ ret = tr->ops->wait_ack(tr);
+ ECRNX_PRINT("dl-fw >> sync, ret: %d\n", ret);
+
+
+ dataAddr = tr->fw->data;
+ length_all = tr->fw->size - offset;
+
+ while(length_all)
+ {
+ memcpy(length_str, dataAddr + offset, 8);
+ ECRNX_PRINT("-------------------------------------%s\n", length_str);
+ offset+=8;
+ length_all-=8;
+ ret = kstrtol(length_str, 10, (long*)&lengthLeft);
+ //ECRNX_PRINT("dl-fw >> file len, ret: %d len:%d\n", ret, lengthLeft);
+ if(ret==0 && lengthLeft)
+ {
+ length_all-=lengthLeft;
+
+ /* 2 cfg addr and length */
+ str_cfg[4] = (char)((file_load_addr[file_num]) & 0xFF);
+ str_cfg[5] = (char)(((file_load_addr[file_num])>>8) & 0xFF);
+ str_cfg[6] = (char)(((file_load_addr[file_num])>>16) & 0xFF);
+ str_cfg[7] = (char)(((file_load_addr[file_num])>>24) & 0xFF);
+ file_num++;
+ str_cfg[8] = (char)((lengthLeft) & 0xFF);
+ str_cfg[9] = (char)(((lengthLeft)>>8) & 0xFF);
+ str_cfg[10] = (char)(((lengthLeft)>>16) & 0xFF);
+ str_cfg[11] = (char)(((lengthLeft)>>24) & 0xFF);
+
+
+ memcpy(skb->data, &str_cfg[0], 12);
+ tr->ops->write(tr, skb->data, 12);
+ ret = tr->ops->wait_ack(tr);
+ //ECRNX_PRINT("dl-fw >> cfg, ret: %d\n", ret);
+
+
+ /* 3 load fw */
+ do {
+ lengthSend = (lengthLeft >= 1024) ? 1024 : lengthLeft; //ECO3 supprot 64K buff
+ if(lengthLeft%512==0)
+ {
+ memcpy(skb->data, dataAddr + offset, lengthSend);
+ tr->ops->write(tr, skb->data, lengthSend);
+
+ //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
+
+ ret = tr->ops->wait_ack(tr);
+ }
+ else
+ {
+ memcpy(skb->data, dataAddr + offset, lengthSend&0xFFFFFE00U);
+ tr->ops->write(tr, skb->data, lengthSend&0xFFFFFE00U);
+ //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
+ ret = tr->ops->wait_ack(tr);
+
+ memcpy(skb->data, dataAddr + offset + (int)(lengthLeft&0xFFFFFE00U), lengthSend&0x1FFU);
+ tr->ops->write(tr, skb->data, lengthSend&0x1FFU);
+ //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
+ ret = tr->ops->wait_ack(tr);
+ }
+
+ //ECRNX_PRINT("dl-fw >> ld-ack(%d), ret: %d\n", offset/1024, ret);
+ offset += lengthSend;
+ lengthLeft -= lengthSend;
+ } while(lengthLeft);
+ //ECRNX_PRINT("dl-fw >> ld, ret: %d\n", ret);
+ }
+ }
+
+ /* 4 start up */
+ memset(skb->data, 0, 12);
+ tr->ops->write(tr, skb->data, 12);
+ tr->ops->wait_ack(tr);
+
+ dev_kfree_skb(skb);
+}
+
+
+
+
+
+bool eswin_fw_file_chech(struct eswin *tr)
+{
+ int status;
+
+ if (fw_name == NULL)
+ goto err_fw;
+
+ if (tr->fw)
+ return true;
+
+ ECRNX_PRINT("%s, Checking firmware... (%s)\n", __func__, fw_name);
+
+ status = request_firmware((const struct firmware **)&tr->fw, fw_name, tr->dev);
+ if (status != 0) {
+ ECRNX_PRINT("%s, error status = %d\n", __func__, status);
+ goto err_fw;
+ }
+
+ ECRNX_PRINT("%s, request fw OK and size is %d\n",
+ __func__, tr->fw->size);
+
+ if(fw_check_head(tr) == false)
+ {
+ goto err_fw;
+ }
+ return true;
+
+
+err_fw:
+ tr->fw = NULL;
+ return false;
+}
+
+