1 /******************************************************************************
2 *
3 * Copyright(c) 2017 - 2019 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
download_flash_88xx(struct halmac_adapter * adapter,u8 * fw_bin,u32 size,u32 rom_addr)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 u32 cnt;
47
48 PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
49
50 value8 = HALMAC_REG_R8(REG_CR + 1);
51 restore[0] = value8;
52 value8 = (u8)(value8 | BIT(0));
53 HALMAC_REG_W8(REG_CR + 1, value8);
54
55 value8 = HALMAC_REG_R8(REG_BCN_CTRL);
56 restore[1] = value8;
57 value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
58 HALMAC_REG_W8(REG_BCN_CTRL, value8);
59
60 value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
61 restore[2] = value8;
62 value8 = (u8)(value8 & ~(BIT(6)));
63 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
64
65 /* Download FW to Flash flow */
66 h2c_info_offset = adapter->txff_alloc.rsvd_h2c_info_addr -
67 adapter->txff_alloc.rsvd_boundary;
68 mem_offset = 0;
69
70 while (size != 0) {
71 if (size >= (DL_FLASH_RSVDPG_SIZE - 48))
72 pkt_size = DL_FLASH_RSVDPG_SIZE - 48;
73 else
74 pkt_size = size;
75
76 rc = dl_rsvd_page_88xx(adapter,
77 adapter->txff_alloc.rsvd_h2c_info_addr,
78 fw_bin + mem_offset, pkt_size);
79 if (rc != HALMAC_RET_SUCCESS) {
80 PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
81 return rc;
82 }
83
84 DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x02);
85 DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_info_offset);
86 DOWNLOAD_FLASH_SET_SIZE(h2c_buf, pkt_size);
87 DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, rom_addr);
88
89 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
90 hdr_info.content_size = 20;
91 hdr_info.ack = 1;
92 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
93
94 rc = send_h2c_pkt_88xx(adapter, h2c_buf);
95
96 if (rc != HALMAC_RET_SUCCESS) {
97 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
98 return rc;
99 }
100
101 value8 = HALMAC_REG_R8(REG_MCUTST_I);
102 value8 |= BIT(0);
103 HALMAC_REG_W8(REG_MCUTST_I, value8);
104
105 rom_addr += pkt_size;
106 mem_offset += pkt_size;
107 size -= pkt_size;
108
109 cnt = 1000;
110 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0) {
111 if (cnt == 0) {
112 PLTFM_MSG_ERR("[ERR]dl flash!!\n");
113 return HALMAC_RET_DLFW_FAIL;
114 }
115 cnt--;
116 PLTFM_DELAY_US(1000);
117 }
118 }
119
120 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
121 HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
122 HALMAC_REG_W8(REG_CR + 1, restore[0]);
123 PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
124
125 return HALMAC_RET_SUCCESS;
126 }
127
128 /**
129 * read_flash_88xx() -read data from flash
130 * @adapter : the adapter of halmac
131 * @addr : flash start address where fw should be read
132 * Author : Pablo Chiu
133 * Return : enum halmac_ret_status
134 * More details of status code can be found in prototype document
135 */
136 enum halmac_ret_status
read_flash_88xx(struct halmac_adapter * adapter,u32 addr,u32 length,u8 * data)137 read_flash_88xx(struct halmac_adapter *adapter, u32 addr, u32 length, u8 *data)
138 {
139 struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
140 enum halmac_ret_status status;
141 struct halmac_h2c_header_info hdr_info;
142 u8 value8;
143 u8 restore[3];
144 u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
145 u16 seq_num = 0;
146 u16 h2c_pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
147 u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
148 u16 h2c_info_addr;
149 u32 cnt;
150
151 PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
152
153 value8 = HALMAC_REG_R8(REG_CR + 1);
154 restore[0] = value8;
155 value8 = (u8)(value8 | BIT(0));
156 HALMAC_REG_W8(REG_CR + 1, value8);
157
158 value8 = HALMAC_REG_R8(REG_BCN_CTRL);
159 restore[1] = value8;
160 value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
161 HALMAC_REG_W8(REG_BCN_CTRL, value8);
162
163 value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
164 restore[2] = value8;
165 value8 = (u8)(value8 & ~(BIT(6)));
166 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
167
168 HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, h2c_pg_addr);
169 value8 = HALMAC_REG_R8(REG_MCUTST_I);
170 value8 |= BIT(0);
171 HALMAC_REG_W8(REG_MCUTST_I, value8);
172
173 /* Construct H2C Content */
174 DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x03);
175 DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_pg_addr - rsvd_pg_addr);
176 DOWNLOAD_FLASH_SET_SIZE(h2c_buf, length);
177 DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
178
179 /* Fill in H2C Header */
180 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
181 hdr_info.content_size = 16;
182 hdr_info.ack = 1;
183 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
184
185 /* Send H2C Cmd Packet */
186 status = send_h2c_pkt_88xx(adapter, h2c_buf);
187
188 if (status != HALMAC_RET_SUCCESS) {
189 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
190 return status;
191 }
192
193 cnt = 5000;
194 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0) {
195 if (cnt == 0) {
196 PLTFM_MSG_ERR("[ERR]read flash!!\n");
197 return HALMAC_RET_FAIL;
198 }
199 cnt--;
200 PLTFM_DELAY_US(1000);
201 }
202
203 HALMAC_REG_W8_CLR(REG_MCUTST_I, BIT(0));
204
205 HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, rsvd_pg_addr);
206 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
207 HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
208 HALMAC_REG_W8(REG_CR + 1, restore[0]);
209
210 h2c_info_addr = h2c_pg_addr << TX_PAGE_SIZE_SHIFT_88XX;
211 status = dump_fifo_88xx(adapter, HAL_FIFO_SEL_TX, h2c_info_addr,
212 length, data);
213 if (status != HALMAC_RET_SUCCESS) {
214 PLTFM_MSG_ERR("[ERR]dump fifo!!\n");
215 return status;
216 }
217 PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
218
219 return HALMAC_RET_SUCCESS;
220 }
221
222 /**
223 * erase_flash_88xx() -erase flash data
224 * @adapter : the adapter of halmac
225 * @erase_cmd : erase command
226 * @addr : flash start address where fw should be erased
227 * Author : Pablo Chiu
228 * Return : enum halmac_ret_status
229 * More details of status code can be found in prototype document
230 */
231 enum halmac_ret_status
erase_flash_88xx(struct halmac_adapter * adapter,u8 erase_cmd,u32 addr)232 erase_flash_88xx(struct halmac_adapter *adapter, u8 erase_cmd, u32 addr)
233 {
234 enum halmac_ret_status status;
235 struct halmac_h2c_header_info hdr_info;
236 struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
237 u8 value8;
238 u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
239 u16 seq_num = 0;
240 u32 cnt;
241
242 /* Construct H2C Content */
243 DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, erase_cmd);
244 DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, 0);
245 DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
246 DOWNLOAD_FLASH_SET_SIZE(h2c_buf, 0);
247
248 value8 = HALMAC_REG_R8(REG_MCUTST_I);
249 value8 |= BIT(0);
250 HALMAC_REG_W8(REG_MCUTST_I, value8);
251
252 /* Fill in H2C Header */
253 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
254 hdr_info.content_size = 16;
255 hdr_info.ack = 1;
256 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
257
258 /* Send H2C Cmd Packet */
259 status = send_h2c_pkt_88xx(adapter, h2c_buf);
260
261 if (status != HALMAC_RET_SUCCESS)
262 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
263
264 cnt = 5000;
265 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0 && cnt != 0) {
266 PLTFM_DELAY_US(1000);
267 cnt--;
268 }
269
270 if (cnt == 0)
271 return HALMAC_RET_FAIL;
272 else
273 return HALMAC_RET_SUCCESS;
274 }
275
276 /**
277 * check_flash_88xx() -check flash data
278 * @adapter : the adapter of halmac
279 * @fw_bin : pointer to fw
280 * @size : fw size
281 * @addr : flash start address where fw should be checked
282 * Author : Pablo Chiu
283 * Return : enum halmac_ret_status
284 * More details of status code can be found in prototype document
285 */
286 enum halmac_ret_status
check_flash_88xx(struct halmac_adapter * adapter,u8 * fw_bin,u32 size,u32 addr)287 check_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
288 u32 addr)
289 {
290 struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
291 u8 value8;
292 u16 i;
293 u16 residue;
294 u16 pg_addr;
295 u32 pkt_size;
296 u32 start_page;
297 u32 cnt;
298 u8 *data;
299
300 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
301
302 data = (u8 *)PLTFM_MALLOC(4096);
303
304 while (size != 0) {
305 start_page = ((pg_addr << 7) >> 12) + 0x780;
306 residue = (pg_addr << 7) & (4096 - 1);
307
308 if (size >= DL_FLASH_RSVDPG_SIZE)
309 pkt_size = DL_FLASH_RSVDPG_SIZE;
310 else
311 pkt_size = size;
312
313 read_flash_88xx(adapter, addr, 4096, data);
314
315 cnt = 0;
316 while (cnt < pkt_size) {
317 HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)(start_page));
318 for (i = 0x8000 + residue; i <= 0x8FFF; i++) {
319 value8 = HALMAC_REG_R8(i);
320 if (*fw_bin != value8) {
321 PLTFM_MSG_ERR("[ERR]check flash!!\n");
322 PLTFM_FREE(data, 4096);
323 return HALMAC_RET_FAIL;
324 }
325
326 fw_bin++;
327 cnt++;
328 if (cnt == pkt_size)
329 break;
330 }
331 residue = 0;
332 start_page++;
333 }
334 addr += pkt_size;
335 size -= pkt_size;
336 }
337
338 PLTFM_FREE(data, 4096);
339
340 return HALMAC_RET_SUCCESS;
341 }
342
343 #endif /* HALMAC_88XX_SUPPORT */
344