1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Shared CARL9170 Header |
4 | * |
5 | * Firmware descriptor format |
6 | * |
7 | * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com> |
8 | */ |
9 | |
10 | #ifndef __CARL9170_SHARED_FWDESC_H |
11 | #define __CARL9170_SHARED_FWDESC_H |
12 | |
13 | /* NOTE: Don't mess with the order of the flags! */ |
14 | enum carl9170fw_feature_list { |
15 | /* Always set */ |
16 | CARL9170FW_DUMMY_FEATURE, |
17 | |
18 | /* |
19 | * Indicates that this image has special boot block which prevents |
20 | * legacy drivers to drive the firmware. |
21 | */ |
22 | CARL9170FW_MINIBOOT, |
23 | |
24 | /* usb registers are initialized by the firmware */ |
25 | CARL9170FW_USB_INIT_FIRMWARE, |
26 | |
27 | /* command traps & notifications are send through EP2 */ |
28 | CARL9170FW_USB_RESP_EP2, |
29 | |
30 | /* usb download (app -> fw) stream */ |
31 | CARL9170FW_USB_DOWN_STREAM, |
32 | |
33 | /* usb upload (fw -> app) stream */ |
34 | CARL9170FW_USB_UP_STREAM, |
35 | |
36 | /* unusable - reserved to flag non-functional debug firmwares */ |
37 | CARL9170FW_UNUSABLE, |
38 | |
39 | /* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */ |
40 | CARL9170FW_COMMAND_PHY, |
41 | |
42 | /* AR9170_CMD_EKEY, AR9170_CMD_DKEY */ |
43 | CARL9170FW_COMMAND_CAM, |
44 | |
45 | /* Firmware has a software Content After Beacon Queueing mechanism */ |
46 | CARL9170FW_WLANTX_CAB, |
47 | |
48 | /* The firmware is capable of responding to incoming BAR frames */ |
49 | CARL9170FW_HANDLE_BACK_REQ, |
50 | |
51 | /* GPIO Interrupt | CARL9170_RSP_GPIO */ |
52 | CARL9170FW_GPIO_INTERRUPT, |
53 | |
54 | /* Firmware PSM support | CARL9170_CMD_PSM */ |
55 | CARL9170FW_PSM, |
56 | |
57 | /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ |
58 | CARL9170FW_RX_FILTER, |
59 | |
60 | /* Wake up on WLAN */ |
61 | CARL9170FW_WOL, |
62 | |
63 | /* Firmware supports PSM in the 5GHZ Band */ |
64 | CARL9170FW_FIXED_5GHZ_PSM, |
65 | |
66 | /* HW (ANI, CCA, MIB) tally counters */ |
67 | CARL9170FW_HW_COUNTERS, |
68 | |
69 | /* Firmware will pass BA when BARs are queued */ |
70 | CARL9170FW_RX_BA_FILTER, |
71 | |
72 | /* Firmware has support to write a byte at a time */ |
73 | CARL9170FW_HAS_WREGB_CMD, |
74 | |
75 | /* Pattern generator */ |
76 | CARL9170FW_PATTERN_GENERATOR, |
77 | |
78 | /* KEEP LAST */ |
79 | __CARL9170FW_FEATURE_NUM |
80 | }; |
81 | |
82 | #define OTUS_MAGIC "OTAR" |
83 | #define MOTD_MAGIC "MOTD" |
84 | #define FIX_MAGIC "FIX\0" |
85 | #define DBG_MAGIC "DBG\0" |
86 | #define CHK_MAGIC "CHK\0" |
87 | #define TXSQ_MAGIC "TXSQ" |
88 | #define WOL_MAGIC "WOL\0" |
89 | #define LAST_MAGIC "LAST" |
90 | |
91 | #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) |
92 | #define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31) |
93 | #define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372) |
94 | |
95 | #define CARL9170FW_GET_DAY(d) (((d) % 31) + 1) |
96 | #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) |
97 | #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) |
98 | |
99 | #define CARL9170FW_MAGIC_SIZE 4 |
100 | |
101 | struct carl9170fw_desc_head { |
102 | u8 magic[CARL9170FW_MAGIC_SIZE]; |
103 | __le16 length; |
104 | u8 min_ver; |
105 | u8 cur_ver; |
106 | } __packed; |
107 | #define CARL9170FW_DESC_HEAD_SIZE \ |
108 | (sizeof(struct carl9170fw_desc_head)) |
109 | |
110 | #define CARL9170FW_OTUS_DESC_MIN_VER 6 |
111 | #define CARL9170FW_OTUS_DESC_CUR_VER 7 |
112 | struct carl9170fw_otus_desc { |
113 | struct carl9170fw_desc_head head; |
114 | __le32 feature_set; |
115 | __le32 fw_address; |
116 | __le32 bcn_addr; |
117 | __le16 bcn_len; |
118 | __le16 miniboot_size; |
119 | __le16 tx_frag_len; |
120 | __le16 rx_max_frame_len; |
121 | u8 tx_descs; |
122 | u8 cmd_bufs; |
123 | u8 api_ver; |
124 | u8 vif_num; |
125 | } __packed; |
126 | #define CARL9170FW_OTUS_DESC_SIZE \ |
127 | (sizeof(struct carl9170fw_otus_desc)) |
128 | |
129 | #define CARL9170FW_MOTD_STRING_LEN 24 |
130 | #define CARL9170FW_MOTD_RELEASE_LEN 20 |
131 | #define CARL9170FW_MOTD_DESC_MIN_VER 1 |
132 | #define CARL9170FW_MOTD_DESC_CUR_VER 2 |
133 | struct carl9170fw_motd_desc { |
134 | struct carl9170fw_desc_head head; |
135 | __le32 fw_year_month_day; |
136 | char desc[CARL9170FW_MOTD_STRING_LEN]; |
137 | char release[CARL9170FW_MOTD_RELEASE_LEN]; |
138 | } __packed; |
139 | #define CARL9170FW_MOTD_DESC_SIZE \ |
140 | (sizeof(struct carl9170fw_motd_desc)) |
141 | |
142 | #define CARL9170FW_FIX_DESC_MIN_VER 1 |
143 | #define CARL9170FW_FIX_DESC_CUR_VER 2 |
144 | struct carl9170fw_fix_entry { |
145 | __le32 address; |
146 | __le32 mask; |
147 | __le32 value; |
148 | } __packed; |
149 | |
150 | struct carl9170fw_fix_desc { |
151 | struct carl9170fw_desc_head head; |
152 | struct carl9170fw_fix_entry data[]; |
153 | } __packed; |
154 | #define CARL9170FW_FIX_DESC_SIZE \ |
155 | (sizeof(struct carl9170fw_fix_desc)) |
156 | |
157 | #define CARL9170FW_DBG_DESC_MIN_VER 1 |
158 | #define CARL9170FW_DBG_DESC_CUR_VER 3 |
159 | struct carl9170fw_dbg_desc { |
160 | struct carl9170fw_desc_head head; |
161 | |
162 | __le32 bogoclock_addr; |
163 | __le32 counter_addr; |
164 | __le32 rx_total_addr; |
165 | __le32 rx_overrun_addr; |
166 | __le32 rx_filter; |
167 | |
168 | /* Put your debugging definitions here */ |
169 | } __packed; |
170 | #define CARL9170FW_DBG_DESC_SIZE \ |
171 | (sizeof(struct carl9170fw_dbg_desc)) |
172 | |
173 | #define CARL9170FW_CHK_DESC_MIN_VER 1 |
174 | #define CARL9170FW_CHK_DESC_CUR_VER 2 |
175 | struct carl9170fw_chk_desc { |
176 | struct carl9170fw_desc_head head; |
177 | __le32 fw_crc32; |
178 | __le32 hdr_crc32; |
179 | } __packed; |
180 | #define CARL9170FW_CHK_DESC_SIZE \ |
181 | (sizeof(struct carl9170fw_chk_desc)) |
182 | |
183 | #define CARL9170FW_TXSQ_DESC_MIN_VER 1 |
184 | #define CARL9170FW_TXSQ_DESC_CUR_VER 1 |
185 | struct carl9170fw_txsq_desc { |
186 | struct carl9170fw_desc_head head; |
187 | |
188 | __le32 seq_table_addr; |
189 | } __packed; |
190 | #define CARL9170FW_TXSQ_DESC_SIZE \ |
191 | (sizeof(struct carl9170fw_txsq_desc)) |
192 | |
193 | #define CARL9170FW_WOL_DESC_MIN_VER 1 |
194 | #define CARL9170FW_WOL_DESC_CUR_VER 1 |
195 | struct carl9170fw_wol_desc { |
196 | struct carl9170fw_desc_head head; |
197 | |
198 | __le32 supported_triggers; /* CARL9170_WOL_ */ |
199 | } __packed; |
200 | #define CARL9170FW_WOL_DESC_SIZE \ |
201 | (sizeof(struct carl9170fw_wol_desc)) |
202 | |
203 | #define CARL9170FW_LAST_DESC_MIN_VER 1 |
204 | #define CARL9170FW_LAST_DESC_CUR_VER 2 |
205 | struct carl9170fw_last_desc { |
206 | struct carl9170fw_desc_head head; |
207 | } __packed; |
208 | #define CARL9170FW_LAST_DESC_SIZE \ |
209 | (sizeof(struct carl9170fw_fix_desc)) |
210 | |
211 | #define CARL9170FW_DESC_MAX_LENGTH 8192 |
212 | |
213 | #define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \ |
214 | .head = { \ |
215 | .magic = _magic, \ |
216 | .length = cpu_to_le16(_length), \ |
217 | .min_ver = _min_ver, \ |
218 | .cur_ver = _cur_ver, \ |
219 | } |
220 | |
221 | static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, |
222 | u8 magic[CARL9170FW_MAGIC_SIZE], |
223 | __le16 length, u8 min_ver, u8 cur_ver) |
224 | { |
225 | head->magic[0] = magic[0]; |
226 | head->magic[1] = magic[1]; |
227 | head->magic[2] = magic[2]; |
228 | head->magic[3] = magic[3]; |
229 | |
230 | head->length = length; |
231 | head->min_ver = min_ver; |
232 | head->cur_ver = cur_ver; |
233 | } |
234 | |
235 | #define carl9170fw_for_each_hdr(desc, fw_desc) \ |
236 | for (desc = fw_desc; \ |
237 | memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) && \ |
238 | le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ |
239 | le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ |
240 | desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) |
241 | |
242 | #define CHECK_HDR_VERSION(head, _min_ver) \ |
243 | (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \ |
244 | |
245 | static inline bool carl9170fw_supports(__le32 list, u8 feature) |
246 | { |
247 | return le32_to_cpu(list) & BIT(feature); |
248 | } |
249 | |
250 | static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, |
251 | const u8 descid[CARL9170FW_MAGIC_SIZE], |
252 | u16 min_len, u8 compatible_revision) |
253 | { |
254 | if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && |
255 | descid[2] == head->magic[2] && descid[3] == head->magic[3] && |
256 | !CHECK_HDR_VERSION(head, compatible_revision) && |
257 | (le16_to_cpu(head->length) >= min_len)) |
258 | return true; |
259 | |
260 | return false; |
261 | } |
262 | |
263 | #define CARL9170FW_MIN_SIZE 32 |
264 | #define CARL9170FW_MAX_SIZE 16384 |
265 | |
266 | static inline bool carl9170fw_size_check(unsigned int len) |
267 | { |
268 | return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE); |
269 | } |
270 | |
271 | #endif /* __CARL9170_SHARED_FWDESC_H */ |
272 | |