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