xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/ath/carl9170/fwdesc.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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