162306a36Sopenharmony_ci/* SPDX-License-Identifier: ISC */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2005-2011 Atheros Communications Inc. 462306a36Sopenharmony_ci * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef _BMI_H_ 862306a36Sopenharmony_ci#define _BMI_H_ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "core.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci * Bootloader Messaging Interface (BMI) 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * BMI is a very simple messaging interface used during initialization 1662306a36Sopenharmony_ci * to read memory, write memory, execute code, and to define an 1762306a36Sopenharmony_ci * application entry PC. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * It is used to download an application to QCA988x, to provide 2062306a36Sopenharmony_ci * patches to code that is already resident on QCA988x, and generally 2162306a36Sopenharmony_ci * to examine and modify state. The Host has an opportunity to use 2262306a36Sopenharmony_ci * BMI only once during bootup. Once the Host issues a BMI_DONE 2362306a36Sopenharmony_ci * command, this opportunity ends. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * The Host writes BMI requests to mailbox0, and reads BMI responses 2662306a36Sopenharmony_ci * from mailbox0. BMI requests all begin with a command 2762306a36Sopenharmony_ci * (see below for specific commands), and are followed by 2862306a36Sopenharmony_ci * command-specific data. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Flow control: 3162306a36Sopenharmony_ci * The Host can only issue a command once the Target gives it a 3262306a36Sopenharmony_ci * "BMI Command Credit", using AR8K Counter #4. As soon as the 3362306a36Sopenharmony_ci * Target has completed a command, it issues another BMI Command 3462306a36Sopenharmony_ci * Credit (so the Host can issue the next command). 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * BMI handles all required Target-side cache flushing. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* Maximum data size used for BMI transfers */ 4062306a36Sopenharmony_ci#define BMI_MAX_DATA_SIZE 256 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* len = cmd + addr + length */ 4362306a36Sopenharmony_ci#define BMI_MAX_CMDBUF_SIZE (BMI_MAX_DATA_SIZE + \ 4462306a36Sopenharmony_ci sizeof(u32) + \ 4562306a36Sopenharmony_ci sizeof(u32) + \ 4662306a36Sopenharmony_ci sizeof(u32)) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* Maximum data size used for large BMI transfers */ 4962306a36Sopenharmony_ci#define BMI_MAX_LARGE_DATA_SIZE 2048 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* len = cmd + addr + length */ 5262306a36Sopenharmony_ci#define BMI_MAX_LARGE_CMDBUF_SIZE (BMI_MAX_LARGE_DATA_SIZE + \ 5362306a36Sopenharmony_ci sizeof(u32) + \ 5462306a36Sopenharmony_ci sizeof(u32) + \ 5562306a36Sopenharmony_ci sizeof(u32)) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* BMI Commands */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cienum bmi_cmd_id { 6062306a36Sopenharmony_ci BMI_NO_COMMAND = 0, 6162306a36Sopenharmony_ci BMI_DONE = 1, 6262306a36Sopenharmony_ci BMI_READ_MEMORY = 2, 6362306a36Sopenharmony_ci BMI_WRITE_MEMORY = 3, 6462306a36Sopenharmony_ci BMI_EXECUTE = 4, 6562306a36Sopenharmony_ci BMI_SET_APP_START = 5, 6662306a36Sopenharmony_ci BMI_READ_SOC_REGISTER = 6, 6762306a36Sopenharmony_ci BMI_READ_SOC_WORD = 6, 6862306a36Sopenharmony_ci BMI_WRITE_SOC_REGISTER = 7, 6962306a36Sopenharmony_ci BMI_WRITE_SOC_WORD = 7, 7062306a36Sopenharmony_ci BMI_GET_TARGET_ID = 8, 7162306a36Sopenharmony_ci BMI_GET_TARGET_INFO = 8, 7262306a36Sopenharmony_ci BMI_ROMPATCH_INSTALL = 9, 7362306a36Sopenharmony_ci BMI_ROMPATCH_UNINSTALL = 10, 7462306a36Sopenharmony_ci BMI_ROMPATCH_ACTIVATE = 11, 7562306a36Sopenharmony_ci BMI_ROMPATCH_DEACTIVATE = 12, 7662306a36Sopenharmony_ci BMI_LZ_STREAM_START = 13, /* should be followed by LZ_DATA */ 7762306a36Sopenharmony_ci BMI_LZ_DATA = 14, 7862306a36Sopenharmony_ci BMI_NVRAM_PROCESS = 15, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define BMI_NVRAM_SEG_NAME_SZ 16 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10 8462306a36Sopenharmony_ci#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000 8562306a36Sopenharmony_ci#define BMI_PARAM_FLASH_SECTION_ALL 0x10000 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* Dual-band Extended Board ID */ 8862306a36Sopenharmony_ci#define BMI_PARAM_GET_EXT_BOARD_ID 0x40000 8962306a36Sopenharmony_ci#define ATH10K_BMI_EXT_BOARD_ID_SUPPORT 0x40000 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00 9262306a36Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000 9562306a36Sopenharmony_ci#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff 9862306a36Sopenharmony_ci#define ATH10K_BMI_EBOARD_ID_STATUS_MASK 0xff 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistruct bmi_cmd { 10162306a36Sopenharmony_ci __le32 id; /* enum bmi_cmd_id */ 10262306a36Sopenharmony_ci union { 10362306a36Sopenharmony_ci struct { 10462306a36Sopenharmony_ci } done; 10562306a36Sopenharmony_ci struct { 10662306a36Sopenharmony_ci __le32 addr; 10762306a36Sopenharmony_ci __le32 len; 10862306a36Sopenharmony_ci } read_mem; 10962306a36Sopenharmony_ci struct { 11062306a36Sopenharmony_ci __le32 addr; 11162306a36Sopenharmony_ci __le32 len; 11262306a36Sopenharmony_ci u8 payload[]; 11362306a36Sopenharmony_ci } write_mem; 11462306a36Sopenharmony_ci struct { 11562306a36Sopenharmony_ci __le32 addr; 11662306a36Sopenharmony_ci __le32 param; 11762306a36Sopenharmony_ci } execute; 11862306a36Sopenharmony_ci struct { 11962306a36Sopenharmony_ci __le32 addr; 12062306a36Sopenharmony_ci } set_app_start; 12162306a36Sopenharmony_ci struct { 12262306a36Sopenharmony_ci __le32 addr; 12362306a36Sopenharmony_ci } read_soc_reg; 12462306a36Sopenharmony_ci struct { 12562306a36Sopenharmony_ci __le32 addr; 12662306a36Sopenharmony_ci __le32 value; 12762306a36Sopenharmony_ci } write_soc_reg; 12862306a36Sopenharmony_ci struct { 12962306a36Sopenharmony_ci } get_target_info; 13062306a36Sopenharmony_ci struct { 13162306a36Sopenharmony_ci __le32 rom_addr; 13262306a36Sopenharmony_ci __le32 ram_addr; /* or value */ 13362306a36Sopenharmony_ci __le32 size; 13462306a36Sopenharmony_ci __le32 activate; /* 0=install, but dont activate */ 13562306a36Sopenharmony_ci } rompatch_install; 13662306a36Sopenharmony_ci struct { 13762306a36Sopenharmony_ci __le32 patch_id; 13862306a36Sopenharmony_ci } rompatch_uninstall; 13962306a36Sopenharmony_ci struct { 14062306a36Sopenharmony_ci __le32 count; 14162306a36Sopenharmony_ci __le32 patch_ids[]; /* length of @count */ 14262306a36Sopenharmony_ci } rompatch_activate; 14362306a36Sopenharmony_ci struct { 14462306a36Sopenharmony_ci __le32 count; 14562306a36Sopenharmony_ci __le32 patch_ids[]; /* length of @count */ 14662306a36Sopenharmony_ci } rompatch_deactivate; 14762306a36Sopenharmony_ci struct { 14862306a36Sopenharmony_ci __le32 addr; 14962306a36Sopenharmony_ci } lz_start; 15062306a36Sopenharmony_ci struct { 15162306a36Sopenharmony_ci __le32 len; /* max BMI_MAX_DATA_SIZE */ 15262306a36Sopenharmony_ci u8 payload[]; /* length of @len */ 15362306a36Sopenharmony_ci } lz_data; 15462306a36Sopenharmony_ci struct { 15562306a36Sopenharmony_ci u8 name[BMI_NVRAM_SEG_NAME_SZ]; 15662306a36Sopenharmony_ci } nvram_process; 15762306a36Sopenharmony_ci u8 payload[BMI_MAX_CMDBUF_SIZE]; 15862306a36Sopenharmony_ci }; 15962306a36Sopenharmony_ci} __packed; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciunion bmi_resp { 16262306a36Sopenharmony_ci struct { 16362306a36Sopenharmony_ci DECLARE_FLEX_ARRAY(u8, payload); 16462306a36Sopenharmony_ci } read_mem; 16562306a36Sopenharmony_ci struct { 16662306a36Sopenharmony_ci __le32 result; 16762306a36Sopenharmony_ci } execute; 16862306a36Sopenharmony_ci struct { 16962306a36Sopenharmony_ci __le32 value; 17062306a36Sopenharmony_ci } read_soc_reg; 17162306a36Sopenharmony_ci struct { 17262306a36Sopenharmony_ci __le32 len; 17362306a36Sopenharmony_ci __le32 version; 17462306a36Sopenharmony_ci __le32 type; 17562306a36Sopenharmony_ci } get_target_info; 17662306a36Sopenharmony_ci struct { 17762306a36Sopenharmony_ci __le32 patch_id; 17862306a36Sopenharmony_ci } rompatch_install; 17962306a36Sopenharmony_ci struct { 18062306a36Sopenharmony_ci __le32 patch_id; 18162306a36Sopenharmony_ci } rompatch_uninstall; 18262306a36Sopenharmony_ci struct { 18362306a36Sopenharmony_ci /* 0 = nothing executed 18462306a36Sopenharmony_ci * otherwise = NVRAM segment return value 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci __le32 result; 18762306a36Sopenharmony_ci } nvram_process; 18862306a36Sopenharmony_ci u8 payload[BMI_MAX_CMDBUF_SIZE]; 18962306a36Sopenharmony_ci} __packed; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistruct bmi_target_info { 19262306a36Sopenharmony_ci u32 version; 19362306a36Sopenharmony_ci u32 type; 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistruct bmi_segmented_file_header { 19762306a36Sopenharmony_ci __le32 magic_num; 19862306a36Sopenharmony_ci __le32 file_flags; 19962306a36Sopenharmony_ci u8 data[]; 20062306a36Sopenharmony_ci}; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistruct bmi_segmented_metadata { 20362306a36Sopenharmony_ci __le32 addr; 20462306a36Sopenharmony_ci __le32 length; 20562306a36Sopenharmony_ci u8 data[]; 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define BMI_SGMTFILE_MAGIC_NUM 0x544d4753 /* "SGMT" */ 20962306a36Sopenharmony_ci#define BMI_SGMTFILE_FLAG_COMPRESS 1 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* Special values for bmi_segmented_metadata.length (all have high bit set) */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* end of segmented data */ 21462306a36Sopenharmony_ci#define BMI_SGMTFILE_DONE 0xffffffff 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* Board Data segment */ 21762306a36Sopenharmony_ci#define BMI_SGMTFILE_BDDATA 0xfffffffe 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* set beginning address */ 22062306a36Sopenharmony_ci#define BMI_SGMTFILE_BEGINADDR 0xfffffffd 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/* immediate function execution */ 22362306a36Sopenharmony_ci#define BMI_SGMTFILE_EXEC 0xfffffffc 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/* in jiffies */ 22662306a36Sopenharmony_ci#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ) 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#define BMI_CE_NUM_TO_TARG 0 22962306a36Sopenharmony_ci#define BMI_CE_NUM_TO_HOST 1 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_civoid ath10k_bmi_start(struct ath10k *ar); 23262306a36Sopenharmony_ciint ath10k_bmi_done(struct ath10k *ar); 23362306a36Sopenharmony_ciint ath10k_bmi_get_target_info(struct ath10k *ar, 23462306a36Sopenharmony_ci struct bmi_target_info *target_info); 23562306a36Sopenharmony_ciint ath10k_bmi_get_target_info_sdio(struct ath10k *ar, 23662306a36Sopenharmony_ci struct bmi_target_info *target_info); 23762306a36Sopenharmony_ciint ath10k_bmi_read_memory(struct ath10k *ar, u32 address, 23862306a36Sopenharmony_ci void *buffer, u32 length); 23962306a36Sopenharmony_ciint ath10k_bmi_write_memory(struct ath10k *ar, u32 address, 24062306a36Sopenharmony_ci const void *buffer, u32 length); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci#define ath10k_bmi_read32(ar, item, val) \ 24362306a36Sopenharmony_ci ({ \ 24462306a36Sopenharmony_ci int ret; \ 24562306a36Sopenharmony_ci u32 addr; \ 24662306a36Sopenharmony_ci __le32 tmp; \ 24762306a36Sopenharmony_ci \ 24862306a36Sopenharmony_ci addr = host_interest_item_address(HI_ITEM(item)); \ 24962306a36Sopenharmony_ci ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \ 25062306a36Sopenharmony_ci if (!ret) \ 25162306a36Sopenharmony_ci *val = __le32_to_cpu(tmp); \ 25262306a36Sopenharmony_ci ret; \ 25362306a36Sopenharmony_ci }) 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci#define ath10k_bmi_write32(ar, item, val) \ 25662306a36Sopenharmony_ci ({ \ 25762306a36Sopenharmony_ci int ret; \ 25862306a36Sopenharmony_ci u32 address; \ 25962306a36Sopenharmony_ci __le32 v = __cpu_to_le32(val); \ 26062306a36Sopenharmony_ci \ 26162306a36Sopenharmony_ci address = host_interest_item_address(HI_ITEM(item)); \ 26262306a36Sopenharmony_ci ret = ath10k_bmi_write_memory(ar, address, \ 26362306a36Sopenharmony_ci (u8 *)&v, sizeof(v)); \ 26462306a36Sopenharmony_ci ret; \ 26562306a36Sopenharmony_ci }) 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ciint ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result); 26862306a36Sopenharmony_ciint ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address); 26962306a36Sopenharmony_ciint ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciint ath10k_bmi_fast_download(struct ath10k *ar, u32 address, 27262306a36Sopenharmony_ci const void *buffer, u32 length); 27362306a36Sopenharmony_ciint ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val); 27462306a36Sopenharmony_ciint ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val); 27562306a36Sopenharmony_ciint ath10k_bmi_set_start(struct ath10k *ar, u32 address); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci#endif /* _BMI_H_ */ 278