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
|
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2014,2016 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#ifndef __WIL_FW_H__
#define __WIL_FW_H__
#define WIL_FW_SIGNATURE (0x36323130) /* '0126' */
#define WIL_FW_FMT_VERSION (1) /* format version driver supports */
enum wil_fw_record_type {
wil_fw_type_comment = 1,
wil_fw_type_data = 2,
wil_fw_type_fill = 3,
wil_fw_type_action = 4,
wil_fw_type_verify = 5,
wil_fw_type_file_header = 6,
wil_fw_type_direct_write = 7,
wil_fw_type_gateway_data = 8,
wil_fw_type_gateway_data4 = 9,
};
struct wil_fw_record_head {
__le16 type; /* enum wil_fw_record_type */
__le16 flags; /* to be defined */
__le32 size; /* whole record, bytes after head */
} __packed;
/* data block. write starting from @addr
* data_size inferred from the @head.size. For this case,
* data_size = @head.size - offsetof(struct wil_fw_record_data, data)
*/
struct wil_fw_record_data { /* type == wil_fw_type_data */
__le32 addr;
__le32 data[]; /* [data_size], see above */
} __packed;
/* fill with constant @value, @size bytes starting from @addr */
struct wil_fw_record_fill { /* type == wil_fw_type_fill */
__le32 addr;
__le32 value;
__le32 size;
} __packed;
/* free-form comment
* for informational purpose, data_size is @head.size from record header
*/
struct wil_fw_record_comment { /* type == wil_fw_type_comment */
DECLARE_FLEX_ARRAY(u8, data); /* free-form data [data_size], see above */
} __packed;
/* Comment header - common for all comment record types */
struct wil_fw_record_comment_hdr {
__le32 magic;
};
/* FW capabilities encoded inside a comment record */
#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba)
struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */
/* identifies capabilities record */
struct wil_fw_record_comment_hdr hdr;
/* capabilities (variable size), see enum wmi_fw_capability */
u8 capabilities[];
} __packed;
/* FW VIF concurrency encoded inside a comment record
* Format is similar to wiphy->iface_combinations
*/
#define WIL_FW_CONCURRENCY_MAGIC (0xfedccdef)
#define WIL_FW_CONCURRENCY_REC_VER 1
struct wil_fw_concurrency_limit {
__le16 max; /* maximum number of interfaces of these types */
__le16 types; /* interface types (bit mask of enum nl80211_iftype) */
} __packed;
struct wil_fw_concurrency_combo {
u8 n_limits; /* number of wil_fw_concurrency_limit entries */
u8 max_interfaces; /* max number of concurrent interfaces allowed */
u8 n_diff_channels; /* total number of different channels allowed */
u8 same_bi; /* for APs, 1 if all APs must have same BI */
/* keep last - concurrency limits, variable size by n_limits */
struct wil_fw_concurrency_limit limits[];
} __packed;
struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */
/* identifies concurrency record */
__le32 magic;
/* structure version, currently always 1 */
u8 version;
/* maximum number of supported MIDs _in addition_ to MID 0 */
u8 n_mids;
/* number of concurrency combinations that follow */
__le16 n_combos;
/* keep last - combinations, variable size by n_combos */
} __packed;
/* brd file info encoded inside a comment record */
#define WIL_BRD_FILE_MAGIC (0xabcddcbb)
struct brd_info {
__le32 base_addr;
__le32 max_size_bytes;
} __packed;
struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */
/* identifies brd file record */
struct wil_fw_record_comment_hdr hdr;
__le32 version;
struct brd_info brd_info[];
} __packed;
/* perform action
* data_size = @head.size - offsetof(struct wil_fw_record_action, data)
*/
struct wil_fw_record_action { /* type == wil_fw_type_action */
__le32 action; /* action to perform: reset, wait for fw ready etc. */
__le32 data[]; /* action specific, [data_size], see above */
} __packed;
/* data block for struct wil_fw_record_direct_write */
struct wil_fw_data_dwrite {
__le32 addr;
__le32 value;
__le32 mask;
} __packed;
/* write @value to the @addr,
* preserve original bits accordingly to the @mask
* data_size is @head.size where @head is record header
*/
struct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */
DECLARE_FLEX_ARRAY(struct wil_fw_data_dwrite, data);
} __packed;
/* verify condition: [@addr] & @mask == @value
* if condition not met, firmware download fails
*/
struct wil_fw_record_verify { /* type == wil_fw_verify */
__le32 addr; /* read from this address */
__le32 value; /* reference value */
__le32 mask; /* mask for verification */
} __packed;
/* file header
* First record of every file
*/
/* the FW version prefix in the comment */
#define WIL_FW_VERSION_PREFIX "FW version: "
#define WIL_FW_VERSION_PREFIX_LEN (sizeof(WIL_FW_VERSION_PREFIX) - 1)
struct wil_fw_record_file_header {
__le32 signature ; /* Wilocity signature */
__le32 reserved;
__le32 crc; /* crc32 of the following data */
__le32 version; /* format version */
__le32 data_len; /* total data in file, including this record */
u8 comment[32]; /* short description */
} __packed;
/* 1-dword gateway */
/* data block for the struct wil_fw_record_gateway_data */
struct wil_fw_data_gw {
__le32 addr;
__le32 value;
} __packed;
/* gateway write block.
* write starting address and values from the data buffer
* through the gateway
* data_size inferred from the @head.size. For this case,
* data_size = @head.size - offsetof(struct wil_fw_record_gateway_data, data)
*/
struct wil_fw_record_gateway_data { /* type == wil_fw_type_gateway_data */
__le32 gateway_addr_addr;
__le32 gateway_value_addr;
__le32 gateway_cmd_addr;
__le32 gateway_ctrl_address;
#define WIL_FW_GW_CTL_BUSY BIT(29) /* gateway busy performing operation */
#define WIL_FW_GW_CTL_RUN BIT(30) /* start gateway operation */
__le32 command;
struct wil_fw_data_gw data[]; /* total size [data_size], see above */
} __packed;
/* 4-dword gateway */
/* data block for the struct wil_fw_record_gateway_data4 */
struct wil_fw_data_gw4 {
__le32 addr;
__le32 value[4];
} __packed;
/* gateway write block.
* write starting address and values from the data buffer
* through the gateway
* data_size inferred from the @head.size. For this case,
* data_size = @head.size - offsetof(struct wil_fw_record_gateway_data4, data)
*/
struct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */
__le32 gateway_addr_addr;
__le32 gateway_value_addr[4];
__le32 gateway_cmd_addr;
__le32 gateway_ctrl_address; /* same logic as for 1-dword gw */
__le32 command;
struct wil_fw_data_gw4 data[]; /* total size [data_size], see above */
} __packed;
#endif /* __WIL_FW_H__ */
|