• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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