18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: ISC */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. 48c2ecf20Sopenharmony_ci * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#ifndef __WIL_FW_H__ 78c2ecf20Sopenharmony_ci#define __WIL_FW_H__ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define WIL_FW_SIGNATURE (0x36323130) /* '0126' */ 108c2ecf20Sopenharmony_ci#define WIL_FW_FMT_VERSION (1) /* format version driver supports */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cienum wil_fw_record_type { 138c2ecf20Sopenharmony_ci wil_fw_type_comment = 1, 148c2ecf20Sopenharmony_ci wil_fw_type_data = 2, 158c2ecf20Sopenharmony_ci wil_fw_type_fill = 3, 168c2ecf20Sopenharmony_ci wil_fw_type_action = 4, 178c2ecf20Sopenharmony_ci wil_fw_type_verify = 5, 188c2ecf20Sopenharmony_ci wil_fw_type_file_header = 6, 198c2ecf20Sopenharmony_ci wil_fw_type_direct_write = 7, 208c2ecf20Sopenharmony_ci wil_fw_type_gateway_data = 8, 218c2ecf20Sopenharmony_ci wil_fw_type_gateway_data4 = 9, 228c2ecf20Sopenharmony_ci}; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct wil_fw_record_head { 258c2ecf20Sopenharmony_ci __le16 type; /* enum wil_fw_record_type */ 268c2ecf20Sopenharmony_ci __le16 flags; /* to be defined */ 278c2ecf20Sopenharmony_ci __le32 size; /* whole record, bytes after head */ 288c2ecf20Sopenharmony_ci} __packed; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* data block. write starting from @addr 318c2ecf20Sopenharmony_ci * data_size inferred from the @head.size. For this case, 328c2ecf20Sopenharmony_ci * data_size = @head.size - offsetof(struct wil_fw_record_data, data) 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_cistruct wil_fw_record_data { /* type == wil_fw_type_data */ 358c2ecf20Sopenharmony_ci __le32 addr; 368c2ecf20Sopenharmony_ci __le32 data[]; /* [data_size], see above */ 378c2ecf20Sopenharmony_ci} __packed; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* fill with constant @value, @size bytes starting from @addr */ 408c2ecf20Sopenharmony_cistruct wil_fw_record_fill { /* type == wil_fw_type_fill */ 418c2ecf20Sopenharmony_ci __le32 addr; 428c2ecf20Sopenharmony_ci __le32 value; 438c2ecf20Sopenharmony_ci __le32 size; 448c2ecf20Sopenharmony_ci} __packed; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* free-form comment 478c2ecf20Sopenharmony_ci * for informational purpose, data_size is @head.size from record header 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistruct wil_fw_record_comment { /* type == wil_fw_type_comment */ 508c2ecf20Sopenharmony_ci u8 data[0]; /* free-form data [data_size], see above */ 518c2ecf20Sopenharmony_ci} __packed; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* Comment header - common for all comment record types */ 548c2ecf20Sopenharmony_cistruct wil_fw_record_comment_hdr { 558c2ecf20Sopenharmony_ci __le32 magic; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* FW capabilities encoded inside a comment record */ 598c2ecf20Sopenharmony_ci#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba) 608c2ecf20Sopenharmony_cistruct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ 618c2ecf20Sopenharmony_ci /* identifies capabilities record */ 628c2ecf20Sopenharmony_ci struct wil_fw_record_comment_hdr hdr; 638c2ecf20Sopenharmony_ci /* capabilities (variable size), see enum wmi_fw_capability */ 648c2ecf20Sopenharmony_ci u8 capabilities[]; 658c2ecf20Sopenharmony_ci} __packed; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* FW VIF concurrency encoded inside a comment record 688c2ecf20Sopenharmony_ci * Format is similar to wiphy->iface_combinations 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci#define WIL_FW_CONCURRENCY_MAGIC (0xfedccdef) 718c2ecf20Sopenharmony_ci#define WIL_FW_CONCURRENCY_REC_VER 1 728c2ecf20Sopenharmony_cistruct wil_fw_concurrency_limit { 738c2ecf20Sopenharmony_ci __le16 max; /* maximum number of interfaces of these types */ 748c2ecf20Sopenharmony_ci __le16 types; /* interface types (bit mask of enum nl80211_iftype) */ 758c2ecf20Sopenharmony_ci} __packed; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistruct wil_fw_concurrency_combo { 788c2ecf20Sopenharmony_ci u8 n_limits; /* number of wil_fw_concurrency_limit entries */ 798c2ecf20Sopenharmony_ci u8 max_interfaces; /* max number of concurrent interfaces allowed */ 808c2ecf20Sopenharmony_ci u8 n_diff_channels; /* total number of different channels allowed */ 818c2ecf20Sopenharmony_ci u8 same_bi; /* for APs, 1 if all APs must have same BI */ 828c2ecf20Sopenharmony_ci /* keep last - concurrency limits, variable size by n_limits */ 838c2ecf20Sopenharmony_ci struct wil_fw_concurrency_limit limits[]; 848c2ecf20Sopenharmony_ci} __packed; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ 878c2ecf20Sopenharmony_ci /* identifies concurrency record */ 888c2ecf20Sopenharmony_ci __le32 magic; 898c2ecf20Sopenharmony_ci /* structure version, currently always 1 */ 908c2ecf20Sopenharmony_ci u8 version; 918c2ecf20Sopenharmony_ci /* maximum number of supported MIDs _in addition_ to MID 0 */ 928c2ecf20Sopenharmony_ci u8 n_mids; 938c2ecf20Sopenharmony_ci /* number of concurrency combinations that follow */ 948c2ecf20Sopenharmony_ci __le16 n_combos; 958c2ecf20Sopenharmony_ci /* keep last - combinations, variable size by n_combos */ 968c2ecf20Sopenharmony_ci struct wil_fw_concurrency_combo combos[]; 978c2ecf20Sopenharmony_ci} __packed; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* brd file info encoded inside a comment record */ 1008c2ecf20Sopenharmony_ci#define WIL_BRD_FILE_MAGIC (0xabcddcbb) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistruct brd_info { 1038c2ecf20Sopenharmony_ci __le32 base_addr; 1048c2ecf20Sopenharmony_ci __le32 max_size_bytes; 1058c2ecf20Sopenharmony_ci} __packed; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistruct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ 1088c2ecf20Sopenharmony_ci /* identifies brd file record */ 1098c2ecf20Sopenharmony_ci struct wil_fw_record_comment_hdr hdr; 1108c2ecf20Sopenharmony_ci __le32 version; 1118c2ecf20Sopenharmony_ci struct brd_info brd_info[]; 1128c2ecf20Sopenharmony_ci} __packed; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* perform action 1158c2ecf20Sopenharmony_ci * data_size = @head.size - offsetof(struct wil_fw_record_action, data) 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_cistruct wil_fw_record_action { /* type == wil_fw_type_action */ 1188c2ecf20Sopenharmony_ci __le32 action; /* action to perform: reset, wait for fw ready etc. */ 1198c2ecf20Sopenharmony_ci __le32 data[]; /* action specific, [data_size], see above */ 1208c2ecf20Sopenharmony_ci} __packed; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/* data block for struct wil_fw_record_direct_write */ 1238c2ecf20Sopenharmony_cistruct wil_fw_data_dwrite { 1248c2ecf20Sopenharmony_ci __le32 addr; 1258c2ecf20Sopenharmony_ci __le32 value; 1268c2ecf20Sopenharmony_ci __le32 mask; 1278c2ecf20Sopenharmony_ci} __packed; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/* write @value to the @addr, 1308c2ecf20Sopenharmony_ci * preserve original bits accordingly to the @mask 1318c2ecf20Sopenharmony_ci * data_size is @head.size where @head is record header 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cistruct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */ 1348c2ecf20Sopenharmony_ci struct wil_fw_data_dwrite data[0]; 1358c2ecf20Sopenharmony_ci} __packed; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* verify condition: [@addr] & @mask == @value 1388c2ecf20Sopenharmony_ci * if condition not met, firmware download fails 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_cistruct wil_fw_record_verify { /* type == wil_fw_verify */ 1418c2ecf20Sopenharmony_ci __le32 addr; /* read from this address */ 1428c2ecf20Sopenharmony_ci __le32 value; /* reference value */ 1438c2ecf20Sopenharmony_ci __le32 mask; /* mask for verification */ 1448c2ecf20Sopenharmony_ci} __packed; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* file header 1478c2ecf20Sopenharmony_ci * First record of every file 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci/* the FW version prefix in the comment */ 1508c2ecf20Sopenharmony_ci#define WIL_FW_VERSION_PREFIX "FW version: " 1518c2ecf20Sopenharmony_ci#define WIL_FW_VERSION_PREFIX_LEN (sizeof(WIL_FW_VERSION_PREFIX) - 1) 1528c2ecf20Sopenharmony_cistruct wil_fw_record_file_header { 1538c2ecf20Sopenharmony_ci __le32 signature ; /* Wilocity signature */ 1548c2ecf20Sopenharmony_ci __le32 reserved; 1558c2ecf20Sopenharmony_ci __le32 crc; /* crc32 of the following data */ 1568c2ecf20Sopenharmony_ci __le32 version; /* format version */ 1578c2ecf20Sopenharmony_ci __le32 data_len; /* total data in file, including this record */ 1588c2ecf20Sopenharmony_ci u8 comment[32]; /* short description */ 1598c2ecf20Sopenharmony_ci} __packed; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci/* 1-dword gateway */ 1628c2ecf20Sopenharmony_ci/* data block for the struct wil_fw_record_gateway_data */ 1638c2ecf20Sopenharmony_cistruct wil_fw_data_gw { 1648c2ecf20Sopenharmony_ci __le32 addr; 1658c2ecf20Sopenharmony_ci __le32 value; 1668c2ecf20Sopenharmony_ci} __packed; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* gateway write block. 1698c2ecf20Sopenharmony_ci * write starting address and values from the data buffer 1708c2ecf20Sopenharmony_ci * through the gateway 1718c2ecf20Sopenharmony_ci * data_size inferred from the @head.size. For this case, 1728c2ecf20Sopenharmony_ci * data_size = @head.size - offsetof(struct wil_fw_record_gateway_data, data) 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_cistruct wil_fw_record_gateway_data { /* type == wil_fw_type_gateway_data */ 1758c2ecf20Sopenharmony_ci __le32 gateway_addr_addr; 1768c2ecf20Sopenharmony_ci __le32 gateway_value_addr; 1778c2ecf20Sopenharmony_ci __le32 gateway_cmd_addr; 1788c2ecf20Sopenharmony_ci __le32 gateway_ctrl_address; 1798c2ecf20Sopenharmony_ci#define WIL_FW_GW_CTL_BUSY BIT(29) /* gateway busy performing operation */ 1808c2ecf20Sopenharmony_ci#define WIL_FW_GW_CTL_RUN BIT(30) /* start gateway operation */ 1818c2ecf20Sopenharmony_ci __le32 command; 1828c2ecf20Sopenharmony_ci struct wil_fw_data_gw data[]; /* total size [data_size], see above */ 1838c2ecf20Sopenharmony_ci} __packed; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci/* 4-dword gateway */ 1868c2ecf20Sopenharmony_ci/* data block for the struct wil_fw_record_gateway_data4 */ 1878c2ecf20Sopenharmony_cistruct wil_fw_data_gw4 { 1888c2ecf20Sopenharmony_ci __le32 addr; 1898c2ecf20Sopenharmony_ci __le32 value[4]; 1908c2ecf20Sopenharmony_ci} __packed; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/* gateway write block. 1938c2ecf20Sopenharmony_ci * write starting address and values from the data buffer 1948c2ecf20Sopenharmony_ci * through the gateway 1958c2ecf20Sopenharmony_ci * data_size inferred from the @head.size. For this case, 1968c2ecf20Sopenharmony_ci * data_size = @head.size - offsetof(struct wil_fw_record_gateway_data4, data) 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_cistruct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */ 1998c2ecf20Sopenharmony_ci __le32 gateway_addr_addr; 2008c2ecf20Sopenharmony_ci __le32 gateway_value_addr[4]; 2018c2ecf20Sopenharmony_ci __le32 gateway_cmd_addr; 2028c2ecf20Sopenharmony_ci __le32 gateway_ctrl_address; /* same logic as for 1-dword gw */ 2038c2ecf20Sopenharmony_ci __le32 command; 2048c2ecf20Sopenharmony_ci struct wil_fw_data_gw4 data[]; /* total size [data_size], see above */ 2058c2ecf20Sopenharmony_ci} __packed; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci#endif /* __WIL_FW_H__ */ 208