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