18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: ISC */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2005-2011 Atheros Communications Inc. 48c2ecf20Sopenharmony_ci * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef _BMI_H_ 88c2ecf20Sopenharmony_ci#define _BMI_H_ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "core.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* 138c2ecf20Sopenharmony_ci * Bootloader Messaging Interface (BMI) 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * BMI is a very simple messaging interface used during initialization 168c2ecf20Sopenharmony_ci * to read memory, write memory, execute code, and to define an 178c2ecf20Sopenharmony_ci * application entry PC. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * It is used to download an application to QCA988x, to provide 208c2ecf20Sopenharmony_ci * patches to code that is already resident on QCA988x, and generally 218c2ecf20Sopenharmony_ci * to examine and modify state. The Host has an opportunity to use 228c2ecf20Sopenharmony_ci * BMI only once during bootup. Once the Host issues a BMI_DONE 238c2ecf20Sopenharmony_ci * command, this opportunity ends. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * The Host writes BMI requests to mailbox0, and reads BMI responses 268c2ecf20Sopenharmony_ci * from mailbox0. BMI requests all begin with a command 278c2ecf20Sopenharmony_ci * (see below for specific commands), and are followed by 288c2ecf20Sopenharmony_ci * command-specific data. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * Flow control: 318c2ecf20Sopenharmony_ci * The Host can only issue a command once the Target gives it a 328c2ecf20Sopenharmony_ci * "BMI Command Credit", using AR8K Counter #4. As soon as the 338c2ecf20Sopenharmony_ci * Target has completed a command, it issues another BMI Command 348c2ecf20Sopenharmony_ci * Credit (so the Host can issue the next command). 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * BMI handles all required Target-side cache flushing. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* Maximum data size used for BMI transfers */ 408c2ecf20Sopenharmony_ci#define BMI_MAX_DATA_SIZE 256 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* len = cmd + addr + length */ 438c2ecf20Sopenharmony_ci#define BMI_MAX_CMDBUF_SIZE (BMI_MAX_DATA_SIZE + \ 448c2ecf20Sopenharmony_ci sizeof(u32) + \ 458c2ecf20Sopenharmony_ci sizeof(u32) + \ 468c2ecf20Sopenharmony_ci sizeof(u32)) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* Maximum data size used for large BMI transfers */ 498c2ecf20Sopenharmony_ci#define BMI_MAX_LARGE_DATA_SIZE 2048 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* len = cmd + addr + length */ 528c2ecf20Sopenharmony_ci#define BMI_MAX_LARGE_CMDBUF_SIZE (BMI_MAX_LARGE_DATA_SIZE + \ 538c2ecf20Sopenharmony_ci sizeof(u32) + \ 548c2ecf20Sopenharmony_ci sizeof(u32) + \ 558c2ecf20Sopenharmony_ci sizeof(u32)) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* BMI Commands */ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cienum bmi_cmd_id { 608c2ecf20Sopenharmony_ci BMI_NO_COMMAND = 0, 618c2ecf20Sopenharmony_ci BMI_DONE = 1, 628c2ecf20Sopenharmony_ci BMI_READ_MEMORY = 2, 638c2ecf20Sopenharmony_ci BMI_WRITE_MEMORY = 3, 648c2ecf20Sopenharmony_ci BMI_EXECUTE = 4, 658c2ecf20Sopenharmony_ci BMI_SET_APP_START = 5, 668c2ecf20Sopenharmony_ci BMI_READ_SOC_REGISTER = 6, 678c2ecf20Sopenharmony_ci BMI_READ_SOC_WORD = 6, 688c2ecf20Sopenharmony_ci BMI_WRITE_SOC_REGISTER = 7, 698c2ecf20Sopenharmony_ci BMI_WRITE_SOC_WORD = 7, 708c2ecf20Sopenharmony_ci BMI_GET_TARGET_ID = 8, 718c2ecf20Sopenharmony_ci BMI_GET_TARGET_INFO = 8, 728c2ecf20Sopenharmony_ci BMI_ROMPATCH_INSTALL = 9, 738c2ecf20Sopenharmony_ci BMI_ROMPATCH_UNINSTALL = 10, 748c2ecf20Sopenharmony_ci BMI_ROMPATCH_ACTIVATE = 11, 758c2ecf20Sopenharmony_ci BMI_ROMPATCH_DEACTIVATE = 12, 768c2ecf20Sopenharmony_ci BMI_LZ_STREAM_START = 13, /* should be followed by LZ_DATA */ 778c2ecf20Sopenharmony_ci BMI_LZ_DATA = 14, 788c2ecf20Sopenharmony_ci BMI_NVRAM_PROCESS = 15, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define BMI_NVRAM_SEG_NAME_SZ 16 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10 848c2ecf20Sopenharmony_ci#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000 858c2ecf20Sopenharmony_ci#define BMI_PARAM_FLASH_SECTION_ALL 0x10000 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* Dual-band Extended Board ID */ 888c2ecf20Sopenharmony_ci#define BMI_PARAM_GET_EXT_BOARD_ID 0x40000 898c2ecf20Sopenharmony_ci#define ATH10K_BMI_EXT_BOARD_ID_SUPPORT 0x40000 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00 928c2ecf20Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000 958c2ecf20Sopenharmony_ci#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff 988c2ecf20Sopenharmony_ci#define ATH10K_BMI_EBOARD_ID_STATUS_MASK 0xff 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistruct bmi_cmd { 1018c2ecf20Sopenharmony_ci __le32 id; /* enum bmi_cmd_id */ 1028c2ecf20Sopenharmony_ci union { 1038c2ecf20Sopenharmony_ci struct { 1048c2ecf20Sopenharmony_ci } done; 1058c2ecf20Sopenharmony_ci struct { 1068c2ecf20Sopenharmony_ci __le32 addr; 1078c2ecf20Sopenharmony_ci __le32 len; 1088c2ecf20Sopenharmony_ci } read_mem; 1098c2ecf20Sopenharmony_ci struct { 1108c2ecf20Sopenharmony_ci __le32 addr; 1118c2ecf20Sopenharmony_ci __le32 len; 1128c2ecf20Sopenharmony_ci u8 payload[0]; 1138c2ecf20Sopenharmony_ci } write_mem; 1148c2ecf20Sopenharmony_ci struct { 1158c2ecf20Sopenharmony_ci __le32 addr; 1168c2ecf20Sopenharmony_ci __le32 param; 1178c2ecf20Sopenharmony_ci } execute; 1188c2ecf20Sopenharmony_ci struct { 1198c2ecf20Sopenharmony_ci __le32 addr; 1208c2ecf20Sopenharmony_ci } set_app_start; 1218c2ecf20Sopenharmony_ci struct { 1228c2ecf20Sopenharmony_ci __le32 addr; 1238c2ecf20Sopenharmony_ci } read_soc_reg; 1248c2ecf20Sopenharmony_ci struct { 1258c2ecf20Sopenharmony_ci __le32 addr; 1268c2ecf20Sopenharmony_ci __le32 value; 1278c2ecf20Sopenharmony_ci } write_soc_reg; 1288c2ecf20Sopenharmony_ci struct { 1298c2ecf20Sopenharmony_ci } get_target_info; 1308c2ecf20Sopenharmony_ci struct { 1318c2ecf20Sopenharmony_ci __le32 rom_addr; 1328c2ecf20Sopenharmony_ci __le32 ram_addr; /* or value */ 1338c2ecf20Sopenharmony_ci __le32 size; 1348c2ecf20Sopenharmony_ci __le32 activate; /* 0=install, but dont activate */ 1358c2ecf20Sopenharmony_ci } rompatch_install; 1368c2ecf20Sopenharmony_ci struct { 1378c2ecf20Sopenharmony_ci __le32 patch_id; 1388c2ecf20Sopenharmony_ci } rompatch_uninstall; 1398c2ecf20Sopenharmony_ci struct { 1408c2ecf20Sopenharmony_ci __le32 count; 1418c2ecf20Sopenharmony_ci __le32 patch_ids[0]; /* length of @count */ 1428c2ecf20Sopenharmony_ci } rompatch_activate; 1438c2ecf20Sopenharmony_ci struct { 1448c2ecf20Sopenharmony_ci __le32 count; 1458c2ecf20Sopenharmony_ci __le32 patch_ids[0]; /* length of @count */ 1468c2ecf20Sopenharmony_ci } rompatch_deactivate; 1478c2ecf20Sopenharmony_ci struct { 1488c2ecf20Sopenharmony_ci __le32 addr; 1498c2ecf20Sopenharmony_ci } lz_start; 1508c2ecf20Sopenharmony_ci struct { 1518c2ecf20Sopenharmony_ci __le32 len; /* max BMI_MAX_DATA_SIZE */ 1528c2ecf20Sopenharmony_ci u8 payload[0]; /* length of @len */ 1538c2ecf20Sopenharmony_ci } lz_data; 1548c2ecf20Sopenharmony_ci struct { 1558c2ecf20Sopenharmony_ci u8 name[BMI_NVRAM_SEG_NAME_SZ]; 1568c2ecf20Sopenharmony_ci } nvram_process; 1578c2ecf20Sopenharmony_ci u8 payload[BMI_MAX_CMDBUF_SIZE]; 1588c2ecf20Sopenharmony_ci }; 1598c2ecf20Sopenharmony_ci} __packed; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ciunion bmi_resp { 1628c2ecf20Sopenharmony_ci struct { 1638c2ecf20Sopenharmony_ci u8 payload[0]; 1648c2ecf20Sopenharmony_ci } read_mem; 1658c2ecf20Sopenharmony_ci struct { 1668c2ecf20Sopenharmony_ci __le32 result; 1678c2ecf20Sopenharmony_ci } execute; 1688c2ecf20Sopenharmony_ci struct { 1698c2ecf20Sopenharmony_ci __le32 value; 1708c2ecf20Sopenharmony_ci } read_soc_reg; 1718c2ecf20Sopenharmony_ci struct { 1728c2ecf20Sopenharmony_ci __le32 len; 1738c2ecf20Sopenharmony_ci __le32 version; 1748c2ecf20Sopenharmony_ci __le32 type; 1758c2ecf20Sopenharmony_ci } get_target_info; 1768c2ecf20Sopenharmony_ci struct { 1778c2ecf20Sopenharmony_ci __le32 patch_id; 1788c2ecf20Sopenharmony_ci } rompatch_install; 1798c2ecf20Sopenharmony_ci struct { 1808c2ecf20Sopenharmony_ci __le32 patch_id; 1818c2ecf20Sopenharmony_ci } rompatch_uninstall; 1828c2ecf20Sopenharmony_ci struct { 1838c2ecf20Sopenharmony_ci /* 0 = nothing executed 1848c2ecf20Sopenharmony_ci * otherwise = NVRAM segment return value 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_ci __le32 result; 1878c2ecf20Sopenharmony_ci } nvram_process; 1888c2ecf20Sopenharmony_ci u8 payload[BMI_MAX_CMDBUF_SIZE]; 1898c2ecf20Sopenharmony_ci} __packed; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistruct bmi_target_info { 1928c2ecf20Sopenharmony_ci u32 version; 1938c2ecf20Sopenharmony_ci u32 type; 1948c2ecf20Sopenharmony_ci}; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistruct bmi_segmented_file_header { 1978c2ecf20Sopenharmony_ci __le32 magic_num; 1988c2ecf20Sopenharmony_ci __le32 file_flags; 1998c2ecf20Sopenharmony_ci u8 data[]; 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistruct bmi_segmented_metadata { 2038c2ecf20Sopenharmony_ci __le32 addr; 2048c2ecf20Sopenharmony_ci __le32 length; 2058c2ecf20Sopenharmony_ci u8 data[]; 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_MAGIC_NUM 0x544d4753 /* "SGMT" */ 2098c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_FLAG_COMPRESS 1 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* Special values for bmi_segmented_metadata.length (all have high bit set) */ 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/* end of segmented data */ 2148c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_DONE 0xffffffff 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/* Board Data segment */ 2178c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_BDDATA 0xfffffffe 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* set beginning address */ 2208c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_BEGINADDR 0xfffffffd 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* immediate function execution */ 2238c2ecf20Sopenharmony_ci#define BMI_SGMTFILE_EXEC 0xfffffffc 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* in jiffies */ 2268c2ecf20Sopenharmony_ci#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ) 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define BMI_CE_NUM_TO_TARG 0 2298c2ecf20Sopenharmony_ci#define BMI_CE_NUM_TO_HOST 1 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_civoid ath10k_bmi_start(struct ath10k *ar); 2328c2ecf20Sopenharmony_ciint ath10k_bmi_done(struct ath10k *ar); 2338c2ecf20Sopenharmony_ciint ath10k_bmi_get_target_info(struct ath10k *ar, 2348c2ecf20Sopenharmony_ci struct bmi_target_info *target_info); 2358c2ecf20Sopenharmony_ciint ath10k_bmi_get_target_info_sdio(struct ath10k *ar, 2368c2ecf20Sopenharmony_ci struct bmi_target_info *target_info); 2378c2ecf20Sopenharmony_ciint ath10k_bmi_read_memory(struct ath10k *ar, u32 address, 2388c2ecf20Sopenharmony_ci void *buffer, u32 length); 2398c2ecf20Sopenharmony_ciint ath10k_bmi_write_memory(struct ath10k *ar, u32 address, 2408c2ecf20Sopenharmony_ci const void *buffer, u32 length); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci#define ath10k_bmi_read32(ar, item, val) \ 2438c2ecf20Sopenharmony_ci ({ \ 2448c2ecf20Sopenharmony_ci int ret; \ 2458c2ecf20Sopenharmony_ci u32 addr; \ 2468c2ecf20Sopenharmony_ci __le32 tmp; \ 2478c2ecf20Sopenharmony_ci \ 2488c2ecf20Sopenharmony_ci addr = host_interest_item_address(HI_ITEM(item)); \ 2498c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \ 2508c2ecf20Sopenharmony_ci if (!ret) \ 2518c2ecf20Sopenharmony_ci *val = __le32_to_cpu(tmp); \ 2528c2ecf20Sopenharmony_ci ret; \ 2538c2ecf20Sopenharmony_ci }) 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci#define ath10k_bmi_write32(ar, item, val) \ 2568c2ecf20Sopenharmony_ci ({ \ 2578c2ecf20Sopenharmony_ci int ret; \ 2588c2ecf20Sopenharmony_ci u32 address; \ 2598c2ecf20Sopenharmony_ci __le32 v = __cpu_to_le32(val); \ 2608c2ecf20Sopenharmony_ci \ 2618c2ecf20Sopenharmony_ci address = host_interest_item_address(HI_ITEM(item)); \ 2628c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_memory(ar, address, \ 2638c2ecf20Sopenharmony_ci (u8 *)&v, sizeof(v)); \ 2648c2ecf20Sopenharmony_ci ret; \ 2658c2ecf20Sopenharmony_ci }) 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciint ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result); 2688c2ecf20Sopenharmony_ciint ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address); 2698c2ecf20Sopenharmony_ciint ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciint ath10k_bmi_fast_download(struct ath10k *ar, u32 address, 2728c2ecf20Sopenharmony_ci const void *buffer, u32 length); 2738c2ecf20Sopenharmony_ciint ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val); 2748c2ecf20Sopenharmony_ciint ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val); 2758c2ecf20Sopenharmony_ciint ath10k_bmi_set_start(struct ath10k *ar, u32 address); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci#endif /* _BMI_H_ */ 278