OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / halmac / halmac_88xx / halmac_flash_88xx.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2017 - 2018 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15
16 #include "halmac_flash_88xx.h"
17 #include "halmac_88xx_cfg.h"
18 #include "halmac_common_88xx.h"
19
20 #if HALMAC_88XX_SUPPORT
21
22 /**
23  * download_flash_88xx() -download firmware to flash
24  * @adapter : the adapter of halmac
25  * @fw_bin : pointer to fw
26  * @size : fw size
27  * @rom_addr : flash start address where fw should be download
28  * Author : Pablo Chiu
29  * Return : enum halmac_ret_status
30  * More details of status code can be found in prototype document
31  */
32 enum halmac_ret_status
33 download_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
34                     u32 rom_addr)
35 {
36         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
37         enum halmac_ret_status rc;
38         struct halmac_h2c_header_info hdr_info;
39         u8 value8;
40         u8 restore[3];
41         u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
42         u16 seq_num = 0;
43         u16 h2c_info_offset;
44         u32 pkt_size;
45         u32 mem_offset;
46
47         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
48
49         value8 = HALMAC_REG_R8(REG_CR + 1);
50         restore[0] = value8;
51         value8 = (u8)(value8 | BIT(0));
52         HALMAC_REG_W8(REG_CR + 1, value8);
53
54         value8 = HALMAC_REG_R8(REG_BCN_CTRL);
55         restore[1] = value8;
56         value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
57         HALMAC_REG_W8(REG_BCN_CTRL, value8);
58
59         value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
60         restore[2] = value8;
61         value8 = (u8)(value8 & ~(BIT(6)));
62         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
63
64         /* Download FW to Flash flow */
65         h2c_info_offset = adapter->txff_alloc.rsvd_h2c_info_addr -
66                                         adapter->txff_alloc.rsvd_boundary;
67         mem_offset = 0;
68
69         while (size != 0) {
70                 if (size >= (DL_FLASH_RSVDPG_SIZE - 48))
71                         pkt_size = DL_FLASH_RSVDPG_SIZE - 48;
72                 else
73                         pkt_size = size;
74
75                 rc = dl_rsvd_page_88xx(adapter,
76                                        adapter->txff_alloc.rsvd_h2c_info_addr,
77                                        fw_bin + mem_offset, pkt_size);
78                 if (rc != HALMAC_RET_SUCCESS) {
79                         PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
80                         return rc;
81                 }
82
83                 DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x02);
84                 DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_info_offset);
85                 DOWNLOAD_FLASH_SET_SIZE(h2c_buf, pkt_size);
86                 DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, rom_addr);
87
88                 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
89                 hdr_info.content_size = 20;
90                 hdr_info.ack = 1;
91                 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
92
93                 rc = send_h2c_pkt_88xx(adapter, h2c_buf);
94
95                 if (rc != HALMAC_RET_SUCCESS) {
96                         PLTFM_MSG_ERR("[ERR]send h2c!!\n");
97                         return rc;
98                 }
99
100                 value8 = HALMAC_REG_R8(REG_MCUTST_I);
101                 value8 |= BIT(0);
102                 HALMAC_REG_W8(REG_MCUTST_I, value8);
103
104                 rom_addr += pkt_size;
105                 mem_offset += pkt_size;
106                 size -= pkt_size;
107
108                 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
109                         PLTFM_DELAY_US(1000);
110
111                 if (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0) {
112                         PLTFM_MSG_ERR("[ERR]dl flash!!\n");
113                         return  HALMAC_RET_DLFW_FAIL;
114                 }
115         }
116
117         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
118         HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
119         HALMAC_REG_W8(REG_CR + 1, restore[0]);
120         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
121
122         return HALMAC_RET_SUCCESS;
123 }
124
125 /**
126  * read_flash_88xx() -read data from flash
127  * @adapter : the adapter of halmac
128  * @addr : flash start address where fw should be read
129  * Author : Pablo Chiu
130  * Return : enum halmac_ret_status
131  * More details of status code can be found in prototype document
132  */
133 enum halmac_ret_status
134 read_flash_88xx(struct halmac_adapter *adapter, u32 addr, u32 length)
135 {
136         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
137         enum halmac_ret_status status;
138         struct halmac_h2c_header_info hdr_info;
139         u8 value8;
140         u8 restore[3];
141         u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
142         u16 seq_num = 0;
143         u16 h2c_info_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
144         u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
145
146         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
147
148         value8 = HALMAC_REG_R8(REG_CR + 1);
149         restore[0] = value8;
150         value8 = (u8)(value8 | BIT(0));
151         HALMAC_REG_W8(REG_CR + 1, value8);
152
153         value8 = HALMAC_REG_R8(REG_BCN_CTRL);
154         restore[1] = value8;
155         value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
156         HALMAC_REG_W8(REG_BCN_CTRL, value8);
157
158         value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
159         restore[2] = value8;
160         value8 = (u8)(value8 & ~(BIT(6)));
161         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
162
163         HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, h2c_info_addr);
164         value8 = HALMAC_REG_R8(REG_MCUTST_I);
165         value8 |= BIT(0);
166         HALMAC_REG_W8(REG_MCUTST_I, value8);
167
168         /* Construct H2C Content */
169         DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x03);
170         DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_info_addr - rsvd_pg_addr);
171         DOWNLOAD_FLASH_SET_SIZE(h2c_buf, length);
172         DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
173
174         /* Fill in H2C Header */
175         hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
176         hdr_info.content_size = 16;
177         hdr_info.ack = 1;
178         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
179
180         /* Send H2C Cmd Packet */
181         status = send_h2c_pkt_88xx(adapter, h2c_buf);
182
183         if (status != HALMAC_RET_SUCCESS) {
184                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
185                 return status;
186         }
187
188         while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
189                 PLTFM_DELAY_US(1000);
190
191         HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, rsvd_pg_addr);
192         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
193         HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
194         HALMAC_REG_W8(REG_CR + 1, restore[0]);
195
196         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
197
198         return HALMAC_RET_SUCCESS;
199 }
200
201 /**
202  * erase_flash_88xx() -erase flash data
203  * @adapter : the adapter of halmac
204  * @erase_cmd : erase command
205  * @addr : flash start address where fw should be erased
206  * Author : Pablo Chiu
207  * Return : enum halmac_ret_status
208  * More details of status code can be found in prototype document
209  */
210 enum halmac_ret_status
211 erase_flash_88xx(struct halmac_adapter *adapter, u8 erase_cmd, u32 addr)
212 {
213         enum halmac_ret_status status;
214         struct halmac_h2c_header_info hdr_info;
215         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
216         u8 value8;
217         u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
218         u16 seq_num = 0;
219         u32 cnt;
220
221         /* Construct H2C Content */
222         DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, erase_cmd);
223         DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, 0);
224         DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
225         DOWNLOAD_FLASH_SET_SIZE(h2c_buf, 0);
226
227         value8 = HALMAC_REG_R8(REG_MCUTST_I);
228         value8 |= BIT(0);
229         HALMAC_REG_W8(REG_MCUTST_I, value8);
230
231         /* Fill in H2C Header */
232         hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
233         hdr_info.content_size = 16;
234         hdr_info.ack = 1;
235         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
236
237         /* Send H2C Cmd Packet */
238         status = send_h2c_pkt_88xx(adapter, h2c_buf);
239
240         if (status != HALMAC_RET_SUCCESS)
241                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
242
243         cnt = 5000;
244         while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0 && cnt != 0) {
245                 PLTFM_DELAY_US(1000);
246                 cnt--;
247         }
248
249         if (cnt == 0)
250                 return HALMAC_RET_FAIL;
251         else
252                 return HALMAC_RET_SUCCESS;
253 }
254
255 /**
256  * check_flash_88xx() -check flash data
257  * @adapter : the adapter of halmac
258  * @fw_bin : pointer to fw
259  * @size : fw size
260  * @addr : flash start address where fw should be checked
261  * Author : Pablo Chiu
262  * Return : enum halmac_ret_status
263  * More details of status code can be found in prototype document
264  */
265 enum halmac_ret_status
266 check_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
267                  u32 addr)
268 {
269         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
270         u8 value8;
271         u16 i;
272         u16 residue;
273         u16 pg_addr;
274         u32 pkt_size;
275         u32 start_page;
276         u32 cnt;
277
278         pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
279
280         while (size != 0) {
281                 start_page = ((pg_addr << 7) >> 12) + 0x780;
282                 residue = (pg_addr << 7) & (4096 - 1);
283
284                 if (size >= DL_FLASH_RSVDPG_SIZE)
285                         pkt_size = DL_FLASH_RSVDPG_SIZE;
286                 else
287                         pkt_size = size;
288
289                 read_flash_88xx(adapter, addr, 4096);
290
291                 cnt = 0;
292                 while (cnt < pkt_size) {
293                         HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)(start_page));
294                         for (i = 0x8000 + residue; i <= 0x8FFF; i++) {
295                                 value8 = HALMAC_REG_R8(i);
296                                 if (*fw_bin != value8) {
297                                         PLTFM_MSG_ERR("[ERR]check flash!!\n");
298                                         return HALMAC_RET_FAIL;
299                                 }
300
301                                 fw_bin++;
302                                 cnt++;
303                                 if (cnt == pkt_size)
304                                         break;
305                         }
306                         residue = 0;
307                         start_page++;
308                 }
309                 addr += pkt_size;
310                 size -= pkt_size;
311         }
312
313         return HALMAC_RET_SUCCESS;
314 }
315
316 #endif /* HALMAC_88XX_SUPPORT */