mirror of
https://github.com/RinCat/RTL88x2BU-Linux-Driver.git
synced 2024-11-14 03:02:50 +00:00
317 lines
8.5 KiB
C
317 lines
8.5 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2017 - 2018 Realtek Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "halmac_flash_88xx.h"
|
|
#include "halmac_88xx_cfg.h"
|
|
#include "halmac_common_88xx.h"
|
|
|
|
#if HALMAC_88XX_SUPPORT
|
|
|
|
/**
|
|
* download_flash_88xx() -download firmware to flash
|
|
* @adapter : the adapter of halmac
|
|
* @fw_bin : pointer to fw
|
|
* @size : fw size
|
|
* @rom_addr : flash start address where fw should be download
|
|
* Author : Pablo Chiu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
download_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
|
|
u32 rom_addr)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_ret_status rc;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
u8 value8;
|
|
u8 restore[3];
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
|
|
u16 seq_num = 0;
|
|
u16 h2c_info_offset;
|
|
u32 pkt_size;
|
|
u32 mem_offset;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
value8 = HALMAC_REG_R8(REG_CR + 1);
|
|
restore[0] = value8;
|
|
value8 = (u8)(value8 | BIT(0));
|
|
HALMAC_REG_W8(REG_CR + 1, value8);
|
|
|
|
value8 = HALMAC_REG_R8(REG_BCN_CTRL);
|
|
restore[1] = value8;
|
|
value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
|
|
HALMAC_REG_W8(REG_BCN_CTRL, value8);
|
|
|
|
value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
|
|
restore[2] = value8;
|
|
value8 = (u8)(value8 & ~(BIT(6)));
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
|
|
|
|
/* Download FW to Flash flow */
|
|
h2c_info_offset = adapter->txff_alloc.rsvd_h2c_info_addr -
|
|
adapter->txff_alloc.rsvd_boundary;
|
|
mem_offset = 0;
|
|
|
|
while (size != 0) {
|
|
if (size >= (DL_FLASH_RSVDPG_SIZE - 48))
|
|
pkt_size = DL_FLASH_RSVDPG_SIZE - 48;
|
|
else
|
|
pkt_size = size;
|
|
|
|
rc = dl_rsvd_page_88xx(adapter,
|
|
adapter->txff_alloc.rsvd_h2c_info_addr,
|
|
fw_bin + mem_offset, pkt_size);
|
|
if (rc != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
|
|
return rc;
|
|
}
|
|
|
|
DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x02);
|
|
DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_info_offset);
|
|
DOWNLOAD_FLASH_SET_SIZE(h2c_buf, pkt_size);
|
|
DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, rom_addr);
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
|
|
hdr_info.content_size = 20;
|
|
hdr_info.ack = _TRUE;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
rc = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (rc != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
return rc;
|
|
}
|
|
|
|
value8 = HALMAC_REG_R8(REG_MCUTST_I);
|
|
value8 |= BIT(0);
|
|
HALMAC_REG_W8(REG_MCUTST_I, value8);
|
|
|
|
rom_addr += pkt_size;
|
|
mem_offset += pkt_size;
|
|
size -= pkt_size;
|
|
|
|
while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
|
|
PLTFM_DELAY_US(1000);
|
|
|
|
if (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0) {
|
|
PLTFM_MSG_ERR("[ERR]dl flash!!\n");
|
|
return HALMAC_RET_DLFW_FAIL;
|
|
}
|
|
}
|
|
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
|
|
HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
|
|
HALMAC_REG_W8(REG_CR + 1, restore[0]);
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* read_flash_88xx() -read data from flash
|
|
* @adapter : the adapter of halmac
|
|
* @addr : flash start address where fw should be read
|
|
* Author : Pablo Chiu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
read_flash_88xx(struct halmac_adapter *adapter, u32 addr)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_ret_status status;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
u8 value8;
|
|
u8 restore[3];
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
|
|
u16 seq_num = 0;
|
|
u16 h2c_info_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
value8 = HALMAC_REG_R8(REG_CR + 1);
|
|
restore[0] = value8;
|
|
value8 = (u8)(value8 | BIT(0));
|
|
HALMAC_REG_W8(REG_CR + 1, value8);
|
|
|
|
value8 = HALMAC_REG_R8(REG_BCN_CTRL);
|
|
restore[1] = value8;
|
|
value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
|
|
HALMAC_REG_W8(REG_BCN_CTRL, value8);
|
|
|
|
value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
|
|
restore[2] = value8;
|
|
value8 = (u8)(value8 & ~(BIT(6)));
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
|
|
|
|
HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, h2c_info_addr);
|
|
value8 = HALMAC_REG_R8(REG_MCUTST_I);
|
|
value8 |= BIT(0);
|
|
HALMAC_REG_W8(REG_MCUTST_I, value8);
|
|
|
|
/* Construct H2C Content */
|
|
DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, 0x03);
|
|
DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, h2c_info_addr - rsvd_pg_addr);
|
|
DOWNLOAD_FLASH_SET_SIZE(h2c_buf, 4096);
|
|
DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
|
|
|
|
/* Fill in H2C Header */
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
|
|
hdr_info.content_size = 16;
|
|
hdr_info.ack = _TRUE;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
/* Send H2C Cmd Packet */
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
return status;
|
|
}
|
|
|
|
while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0)
|
|
PLTFM_DELAY_US(1000);
|
|
|
|
HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, rsvd_pg_addr);
|
|
HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[2]);
|
|
HALMAC_REG_W8(REG_BCN_CTRL, restore[1]);
|
|
HALMAC_REG_W8(REG_CR + 1, restore[0]);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* erase_flash_88xx() -erase flash data
|
|
* @adapter : the adapter of halmac
|
|
* @erase_cmd : erase command
|
|
* @addr : flash start address where fw should be erased
|
|
* Author : Pablo Chiu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
erase_flash_88xx(struct halmac_adapter *adapter, u8 erase_cmd, u32 addr)
|
|
{
|
|
enum halmac_ret_status status;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
u8 value8;
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = {0};
|
|
u16 seq_num = 0;
|
|
u32 cnt;
|
|
|
|
/* Construct H2C Content */
|
|
DOWNLOAD_FLASH_SET_SPI_CMD(h2c_buf, erase_cmd);
|
|
DOWNLOAD_FLASH_SET_LOCATION(h2c_buf, 0);
|
|
DOWNLOAD_FLASH_SET_START_ADDR(h2c_buf, addr);
|
|
DOWNLOAD_FLASH_SET_SIZE(h2c_buf, 0);
|
|
|
|
value8 = HALMAC_REG_R8(REG_MCUTST_I);
|
|
value8 |= BIT(0);
|
|
HALMAC_REG_W8(REG_MCUTST_I, value8);
|
|
|
|
/* Fill in H2C Header */
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_DOWNLOAD_FLASH;
|
|
hdr_info.content_size = 16;
|
|
hdr_info.ack = _TRUE;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
/* Send H2C Cmd Packet */
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
PLTFM_MSG_ERR("[ERR]send h2c!!\n");
|
|
|
|
cnt = 5000;
|
|
while (((HALMAC_REG_R8(REG_MCUTST_I)) & BIT(0)) != 0 && cnt != 0) {
|
|
PLTFM_DELAY_US(1000);
|
|
cnt--;
|
|
}
|
|
|
|
if (cnt == 0)
|
|
return HALMAC_RET_FAIL;
|
|
else
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* check_flash_88xx() -check flash data
|
|
* @adapter : the adapter of halmac
|
|
* @fw_bin : pointer to fw
|
|
* @size : fw size
|
|
* @addr : flash start address where fw should be checked
|
|
* Author : Pablo Chiu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
check_flash_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
|
|
u32 addr)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
u8 value8;
|
|
u16 i;
|
|
u16 residue;
|
|
u16 pg_addr;
|
|
u32 pkt_size;
|
|
u32 start_page;
|
|
u32 cnt;
|
|
|
|
pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
|
|
|
|
while (size != 0) {
|
|
start_page = ((pg_addr << 7) >> 12) + 0x780;
|
|
residue = (pg_addr << 7) & (4096 - 1);
|
|
|
|
if (size >= DL_FLASH_RSVDPG_SIZE)
|
|
pkt_size = DL_FLASH_RSVDPG_SIZE;
|
|
else
|
|
pkt_size = size;
|
|
|
|
read_flash_88xx(adapter, addr);
|
|
|
|
cnt = 0;
|
|
while (cnt < pkt_size) {
|
|
HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)(start_page));
|
|
for (i = 0x8000 + residue; i <= 0x8FFF; i++) {
|
|
value8 = HALMAC_REG_R8(i);
|
|
if (*fw_bin != value8) {
|
|
PLTFM_MSG_ERR("[ERR]check flash!!\n");
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
fw_bin++;
|
|
cnt++;
|
|
if (cnt == pkt_size)
|
|
break;
|
|
}
|
|
residue = 0;
|
|
start_page++;
|
|
}
|
|
addr += pkt_size;
|
|
size -= pkt_size;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
#endif /* HALMAC_88XX_SUPPORT */
|