summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath10k/bmi.h
blob: 0685c0d2d4ea035c11932facb91bb81a91ac58fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/* SPDX-License-Identifier: ISC */
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc.
 */

#ifndef _BMI_H_
#define _BMI_H_

#include "core.h"

/*
 * Bootloader Messaging Interface (BMI)
 *
 * BMI is a very simple messaging interface used during initialization
 * to read memory, write memory, execute code, and to define an
 * application entry PC.
 *
 * It is used to download an application to QCA988x, to provide
 * patches to code that is already resident on QCA988x, and generally
 * to examine and modify state.  The Host has an opportunity to use
 * BMI only once during bootup.  Once the Host issues a BMI_DONE
 * command, this opportunity ends.
 *
 * The Host writes BMI requests to mailbox0, and reads BMI responses
 * from mailbox0.   BMI requests all begin with a command
 * (see below for specific commands), and are followed by
 * command-specific data.
 *
 * Flow control:
 * The Host can only issue a command once the Target gives it a
 * "BMI Command Credit", using AR8K Counter #4.  As soon as the
 * Target has completed a command, it issues another BMI Command
 * Credit (so the Host can issue the next command).
 *
 * BMI handles all required Target-side cache flushing.
 */

/* Maximum data size used for BMI transfers */
#define BMI_MAX_DATA_SIZE	256

/* len = cmd + addr + length */
#define BMI_MAX_CMDBUF_SIZE (BMI_MAX_DATA_SIZE + \
			sizeof(u32) + \
			sizeof(u32) + \
			sizeof(u32))

/* Maximum data size used for large BMI transfers */
#define BMI_MAX_LARGE_DATA_SIZE	2048

/* len = cmd + addr + length */
#define BMI_MAX_LARGE_CMDBUF_SIZE (BMI_MAX_LARGE_DATA_SIZE + \
			sizeof(u32) + \
			sizeof(u32) + \
			sizeof(u32))

/* BMI Commands */

enum bmi_cmd_id {
	BMI_NO_COMMAND          = 0,
	BMI_DONE                = 1,
	BMI_READ_MEMORY         = 2,
	BMI_WRITE_MEMORY        = 3,
	BMI_EXECUTE             = 4,
	BMI_SET_APP_START       = 5,
	BMI_READ_SOC_REGISTER   = 6,
	BMI_READ_SOC_WORD       = 6,
	BMI_WRITE_SOC_REGISTER  = 7,
	BMI_WRITE_SOC_WORD      = 7,
	BMI_GET_TARGET_ID       = 8,
	BMI_GET_TARGET_INFO     = 8,
	BMI_ROMPATCH_INSTALL    = 9,
	BMI_ROMPATCH_UNINSTALL  = 10,
	BMI_ROMPATCH_ACTIVATE   = 11,
	BMI_ROMPATCH_DEACTIVATE = 12,
	BMI_LZ_STREAM_START     = 13, /* should be followed by LZ_DATA */
	BMI_LZ_DATA             = 14,
	BMI_NVRAM_PROCESS       = 15,
};

#define BMI_NVRAM_SEG_NAME_SZ 16

#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10
#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000
#define BMI_PARAM_FLASH_SECTION_ALL 0x10000

/* Dual-band Extended Board ID */
#define BMI_PARAM_GET_EXT_BOARD_ID 0x40000
#define ATH10K_BMI_EXT_BOARD_ID_SUPPORT 0x40000

#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK   0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB    10

#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK    0x18000
#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB     15

#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff
#define ATH10K_BMI_EBOARD_ID_STATUS_MASK 0xff

struct bmi_cmd {
	__le32 id; /* enum bmi_cmd_id */
	union {
		struct {
		} done;
		struct {
			__le32 addr;
			__le32 len;
		} read_mem;
		struct {
			__le32 addr;
			__le32 len;
			u8 payload[];
		} write_mem;
		struct {
			__le32 addr;
			__le32 param;
		} execute;
		struct {
			__le32 addr;
		} set_app_start;
		struct {
			__le32 addr;
		} read_soc_reg;
		struct {
			__le32 addr;
			__le32 value;
		} write_soc_reg;
		struct {
		} get_target_info;
		struct {
			__le32 rom_addr;
			__le32 ram_addr; /* or value */
			__le32 size;
			__le32 activate; /* 0=install, but dont activate */
		} rompatch_install;
		struct {
			__le32 patch_id;
		} rompatch_uninstall;
		struct {
			__le32 count;
			__le32 patch_ids[]; /* length of @count */
		} rompatch_activate;
		struct {
			__le32 count;
			__le32 patch_ids[]; /* length of @count */
		} rompatch_deactivate;
		struct {
			__le32 addr;
		} lz_start;
		struct {
			__le32 len; /* max BMI_MAX_DATA_SIZE */
			u8 payload[]; /* length of @len */
		} lz_data;
		struct {
			u8 name[BMI_NVRAM_SEG_NAME_SZ];
		} nvram_process;
		u8 payload[BMI_MAX_CMDBUF_SIZE];
	};
} __packed;

union bmi_resp {
	struct {
		DECLARE_FLEX_ARRAY(u8, payload);
	} read_mem;
	struct {
		__le32 result;
	} execute;
	struct {
		__le32 value;
	} read_soc_reg;
	struct {
		__le32 len;
		__le32 version;
		__le32 type;
	} get_target_info;
	struct {
		__le32 patch_id;
	} rompatch_install;
	struct {
		__le32 patch_id;
	} rompatch_uninstall;
	struct {
		/* 0 = nothing executed
		 * otherwise = NVRAM segment return value
		 */
		__le32 result;
	} nvram_process;
	u8 payload[BMI_MAX_CMDBUF_SIZE];
} __packed;

struct bmi_target_info {
	u32 version;
	u32 type;
};

struct bmi_segmented_file_header {
	__le32 magic_num;
	__le32 file_flags;
	u8 data[];
};

struct bmi_segmented_metadata {
	__le32 addr;
	__le32 length;
	u8 data[];
};

#define BMI_SGMTFILE_MAGIC_NUM          0x544d4753 /* "SGMT" */
#define BMI_SGMTFILE_FLAG_COMPRESS      1

/* Special values for bmi_segmented_metadata.length (all have high bit set) */

/* end of segmented data */
#define BMI_SGMTFILE_DONE               0xffffffff

/* Board Data segment */
#define BMI_SGMTFILE_BDDATA             0xfffffffe

/* set beginning address */
#define BMI_SGMTFILE_BEGINADDR          0xfffffffd

/* immediate function execution */
#define BMI_SGMTFILE_EXEC               0xfffffffc

/* in jiffies */
#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ)

#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1

void ath10k_bmi_start(struct ath10k *ar);
int ath10k_bmi_done(struct ath10k *ar);
int ath10k_bmi_get_target_info(struct ath10k *ar,
			       struct bmi_target_info *target_info);
int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
				    struct bmi_target_info *target_info);
int ath10k_bmi_read_memory(struct ath10k *ar, u32 address,
			   void *buffer, u32 length);
int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
			    const void *buffer, u32 length);

#define ath10k_bmi_read32(ar, item, val)				\
	({								\
		int ret;						\
		u32 addr;						\
		__le32 tmp;						\
									\
		addr = host_interest_item_address(HI_ITEM(item));	\
		ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \
		if (!ret)						\
			*val = __le32_to_cpu(tmp);			\
		ret;							\
	 })

#define ath10k_bmi_write32(ar, item, val)				\
	({								\
		int ret;						\
		u32 address;						\
		__le32 v = __cpu_to_le32(val);				\
									\
		address = host_interest_item_address(HI_ITEM(item));	\
		ret = ath10k_bmi_write_memory(ar, address,		\
					      (u8 *)&v, sizeof(v));	\
		ret;							\
	})

int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result);
int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address);
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);

int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
			     const void *buffer, u32 length);
int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val);
int ath10k_bmi_set_start(struct ath10k *ar, u32 address);

#endif /* _BMI_H_ */