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