net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / sdio / fw.c
1 /**
2 ******************************************************************************
3 *
4 * @file fw.c
5 *
6 * @brief ecrnx sdio firmware download functions
7 *
8 * Copyright (C) ESWIN 2015-2020
9 *
10 ******************************************************************************
11 */
12
13 #include <linux/firmware.h>
14 #include "core.h"
15 #include "sdio.h"
16 #include "fw_head_check.h"
17
18 extern char *fw_name;
19
20
21 void eswin_fw_file_download(struct eswin *tr)
22 {
23         int ret;
24         unsigned int length_all;
25         unsigned char length_str[9]={0};
26         unsigned int lengthLeft, lengthSend, offset = HEAD_SIZE;
27         const u8 * dataAddr;
28         struct sk_buff *skb;
29         int file_num = 0;
30         unsigned int file_load_addr[3] = {0x10000U, 0x60800U, 0x80000U};  // ilm addr; dlm addr offset 0x800 for bootrom log; iram0 addr
31
32         char str_sync[4] = {0x63, 0x6E, 0x79, 0x73};            
33         char str_cfg[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00};  // default for sync
34
35         skb = dev_alloc_skb(1024);
36
37         ECRNX_PRINT("%s entry!!", __func__);
38
39
40         /* 1 sync */
41         memcpy(skb->data, str_sync, 4);
42         tr->ops->write(tr, skb->data, 4);
43         ret = tr->ops->wait_ack(tr);
44         ECRNX_PRINT("dl-fw >> sync, ret: %d\n", ret);
45
46         
47         dataAddr = tr->fw->data;
48         length_all = tr->fw->size - offset;
49         
50         while(length_all)
51         {
52                 memcpy(length_str, dataAddr + offset, 8);
53                 ECRNX_PRINT("-------------------------------------%s\n", length_str);
54                 offset+=8; 
55                 length_all-=8;
56                 ret = kstrtol(length_str, 10, (long*)&lengthLeft);
57                 //ECRNX_PRINT("dl-fw >> file len, ret: %d  len:%d\n", ret, lengthLeft);
58                 if(ret==0 && lengthLeft)
59                 {
60                         length_all-=lengthLeft;
61
62                         /* 2 cfg addr and length */
63                         str_cfg[4] = (char)((file_load_addr[file_num]) & 0xFF);
64                         str_cfg[5] = (char)(((file_load_addr[file_num])>>8) & 0xFF);
65                         str_cfg[6] = (char)(((file_load_addr[file_num])>>16) & 0xFF);
66                         str_cfg[7] = (char)(((file_load_addr[file_num])>>24) & 0xFF);
67                         file_num++;
68                         str_cfg[8] = (char)((lengthLeft) & 0xFF);
69                         str_cfg[9] = (char)(((lengthLeft)>>8) & 0xFF);
70                         str_cfg[10] = (char)(((lengthLeft)>>16) & 0xFF);
71                         str_cfg[11] = (char)(((lengthLeft)>>24) & 0xFF);
72
73
74                         memcpy(skb->data, &str_cfg[0], 12);
75                         tr->ops->write(tr, skb->data, 12);
76                         ret = tr->ops->wait_ack(tr);
77                         //ECRNX_PRINT("dl-fw >> cfg, ret: %d\n", ret);
78
79
80                         /* 3 load fw */
81                         do {
82                                 lengthSend = (lengthLeft >= 1024) ? 1024 : lengthLeft; //ECO3 supprot 64K buff
83                                 if(lengthLeft%512==0)
84                                 {
85                                         memcpy(skb->data, dataAddr + offset, lengthSend);
86                                         tr->ops->write(tr, skb->data, lengthSend);
87
88                                         //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
89
90                                         ret = tr->ops->wait_ack(tr);
91                                 }
92                                 else
93                                 {       
94                                         memcpy(skb->data, dataAddr + offset, lengthSend&0xFFFFFE00U);
95                                         tr->ops->write(tr, skb->data, lengthSend&0xFFFFFE00U);
96                                         //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
97                                         ret = tr->ops->wait_ack(tr);
98                                         
99                                         memcpy(skb->data, dataAddr + offset + (int)(lengthLeft&0xFFFFFE00U), lengthSend&0x1FFU);
100                                         tr->ops->write(tr, skb->data, lengthSend&0x1FFU);
101                                         //ECRNX_PRINT("dl-fw >> ld(%d), ret: %d\n", offset/1024, ret);
102                                         ret = tr->ops->wait_ack(tr);
103                                 }
104
105                                 //ECRNX_PRINT("dl-fw >> ld-ack(%d), ret: %d\n", offset/1024, ret);
106                                 offset += lengthSend;   
107                                 lengthLeft -= lengthSend;
108                         } while(lengthLeft);    
109                         //ECRNX_PRINT("dl-fw >> ld, ret: %d\n", ret);
110                 }
111         }
112
113         /* 4 start up */
114         memset(skb->data, 0, 12);
115         tr->ops->write(tr, skb->data, 12);
116         tr->ops->wait_ack(tr);
117
118         dev_kfree_skb(skb);
119 }
120
121
122
123
124
125 bool eswin_fw_file_chech(struct eswin *tr)
126 {
127         int status;
128
129         if (fw_name == NULL)
130                 goto err_fw;
131
132         if (tr->fw)
133                 return true;
134
135         ECRNX_PRINT("%s, Checking firmware... (%s)\n",  __func__, fw_name);
136
137         status = request_firmware((const struct firmware **)&tr->fw, fw_name, tr->dev);
138         if (status != 0) {
139                 ECRNX_PRINT("%s, error status = %d\n",  __func__, status);
140                 goto err_fw;
141         }
142
143         ECRNX_PRINT("%s, request fw OK and size is %d\n",
144                         __func__, tr->fw->size);
145
146     if(fw_check_head(tr) == false)
147     {
148         goto err_fw;
149     }
150         return true;
151
152
153 err_fw:
154         tr->fw = NULL;
155         return false;
156 }
157
158