1 /******************************************************************************
3 * Copyright(c) 2017 - 2018 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
16 #include "halmac_flash_88xx.h"
17 #include "halmac_88xx_cfg.h"
18 #include "halmac_common_88xx.h"
20 #if HALMAC_88XX_SUPPORT
23 * download_flash_88xx() -download firmware to flash
24 * @adapter : the adapter of halmac
25 * @fw_bin : pointer to fw
27 * @rom_addr : flash start address where fw should be download
29 * Return : enum halmac_ret_status
30 * More details of status code can be found in prototype document
32 enum halmac_ret_status
33 download_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
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;
41 u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
47 PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
49 value8 = HALMAC_REG_R8(REG_CR + 1);
51 value8 = (u8)(value8 | BIT(0));
52 HALMAC_REG_W8(REG_CR + 1, value8);
54 value8 = HALMAC_REG_R8(REG_BCN_CTRL);
56 value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
57 HALMAC_REG_W8(REG_BCN_CTRL, value8);
59 value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
61 value8 = (u8)(value8 & ~(BIT(6)));
62 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
64 /* Download FW to Flash flow */
65 h2c_info_offset = adapter->txff_alloc.rsvd_h2c_info_addr -
66 adapter->txff_alloc.rsvd_boundary;
70 if (size >= (DL_FLASH_RSVDPG_SIZE - 48))
71 pkt_size = DL_FLASH_RSVDPG_SIZE - 48;
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");
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);
88 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
89 hdr_info.content_size = 20;
91 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
93 rc = send_h2c_pkt_88xx(adapter, h2c_buf);
95 if (rc != HALMAC_RET_SUCCESS) {
96 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
100 value8 = HALMAC_REG_R8(REG_MCUTST_I);
102 HALMAC_REG_W8(REG_MCUTST_I, value8);
104 rom_addr += pkt_size;
105 mem_offset += pkt_size;
108 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
109 PLTFM_DELAY_US(1000);
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;
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__);
122 return HALMAC_RET_SUCCESS;
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
133 enum halmac_ret_status
134 read_flash_88xx(struct halmac_adapter *adapter, u32 addr, u32 length)
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;
141 u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
143 u16 h2c_info_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
144 u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
146 PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
148 value8 = HALMAC_REG_R8(REG_CR + 1);
150 value8 = (u8)(value8 | BIT(0));
151 HALMAC_REG_W8(REG_CR + 1, value8);
153 value8 = HALMAC_REG_R8(REG_BCN_CTRL);
155 value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
156 HALMAC_REG_W8(REG_BCN_CTRL, value8);
158 value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
160 value8 = (u8)(value8 & ~(BIT(6)));
161 HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
163 HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, h2c_info_addr);
164 value8 = HALMAC_REG_R8(REG_MCUTST_I);
166 HALMAC_REG_W8(REG_MCUTST_I, value8);
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);
174 /* Fill in H2C Header */
175 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
176 hdr_info.content_size = 16;
178 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
180 /* Send H2C Cmd Packet */
181 status = send_h2c_pkt_88xx(adapter, h2c_buf);
183 if (status != HALMAC_RET_SUCCESS) {
184 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
188 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
189 PLTFM_DELAY_US(1000);
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]);
196 PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
198 return HALMAC_RET_SUCCESS;
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
210 enum halmac_ret_status
211 erase_flash_88xx(struct halmac_adapter *adapter, u8 erase_cmd, u32 addr)
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;
217 u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
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);
227 value8 = HALMAC_REG_R8(REG_MCUTST_I);
229 HALMAC_REG_W8(REG_MCUTST_I, value8);
231 /* Fill in H2C Header */
232 hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
233 hdr_info.content_size = 16;
235 set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
237 /* Send H2C Cmd Packet */
238 status = send_h2c_pkt_88xx(adapter, h2c_buf);
240 if (status != HALMAC_RET_SUCCESS)
241 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
244 while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0 && cnt != 0) {
245 PLTFM_DELAY_US(1000);
250 return HALMAC_RET_FAIL;
252 return HALMAC_RET_SUCCESS;
256 * check_flash_88xx() -check flash data
257 * @adapter : the adapter of halmac
258 * @fw_bin : pointer to fw
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
265 enum halmac_ret_status
266 check_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
269 struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
278 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
281 start_page = ((pg_addr << 7) >> 12) + 0x780;
282 residue = (pg_addr << 7) & (4096 - 1);
284 if (size >= DL_FLASH_RSVDPG_SIZE)
285 pkt_size = DL_FLASH_RSVDPG_SIZE;
289 read_flash_88xx(adapter, addr, 4096);
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;
313 return HALMAC_RET_SUCCESS;
316 #endif /* HALMAC_88XX_SUPPORT */