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
diff --git a/rtl8821ce/hal/halmac/halmac_88xx/halmac_flash_88xx.c b/rtl8821ce/hal/halmac/halmac_88xx/halmac_flash_88xx.c
new file mode 100644 (file)
index 0000000..24bc5b6
--- /dev/null
@@ -0,0 +1,316 @@
+/******************************************************************************
+ *
+ * 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 = 1;
+               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, u32 length)
+{
+       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, length);
+       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 = 1;
+       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 = 1;
+       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, 4096);
+
+               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 */