18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Shared CARL9170 Header 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Firmware descriptor format 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef __CARL9170_SHARED_FWDESC_H 118c2ecf20Sopenharmony_ci#define __CARL9170_SHARED_FWDESC_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* NOTE: Don't mess with the order of the flags! */ 148c2ecf20Sopenharmony_cienum carl9170fw_feature_list { 158c2ecf20Sopenharmony_ci /* Always set */ 168c2ecf20Sopenharmony_ci CARL9170FW_DUMMY_FEATURE, 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci /* 198c2ecf20Sopenharmony_ci * Indicates that this image has special boot block which prevents 208c2ecf20Sopenharmony_ci * legacy drivers to drive the firmware. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci CARL9170FW_MINIBOOT, 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci /* usb registers are initialized by the firmware */ 258c2ecf20Sopenharmony_ci CARL9170FW_USB_INIT_FIRMWARE, 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci /* command traps & notifications are send through EP2 */ 288c2ecf20Sopenharmony_ci CARL9170FW_USB_RESP_EP2, 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci /* usb download (app -> fw) stream */ 318c2ecf20Sopenharmony_ci CARL9170FW_USB_DOWN_STREAM, 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* usb upload (fw -> app) stream */ 348c2ecf20Sopenharmony_ci CARL9170FW_USB_UP_STREAM, 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* unusable - reserved to flag non-functional debug firmwares */ 378c2ecf20Sopenharmony_ci CARL9170FW_UNUSABLE, 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */ 408c2ecf20Sopenharmony_ci CARL9170FW_COMMAND_PHY, 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci /* AR9170_CMD_EKEY, AR9170_CMD_DKEY */ 438c2ecf20Sopenharmony_ci CARL9170FW_COMMAND_CAM, 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* Firmware has a software Content After Beacon Queueing mechanism */ 468c2ecf20Sopenharmony_ci CARL9170FW_WLANTX_CAB, 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* The firmware is capable of responding to incoming BAR frames */ 498c2ecf20Sopenharmony_ci CARL9170FW_HANDLE_BACK_REQ, 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* GPIO Interrupt | CARL9170_RSP_GPIO */ 528c2ecf20Sopenharmony_ci CARL9170FW_GPIO_INTERRUPT, 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Firmware PSM support | CARL9170_CMD_PSM */ 558c2ecf20Sopenharmony_ci CARL9170FW_PSM, 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ 588c2ecf20Sopenharmony_ci CARL9170FW_RX_FILTER, 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Wake up on WLAN */ 618c2ecf20Sopenharmony_ci CARL9170FW_WOL, 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* Firmware supports PSM in the 5GHZ Band */ 648c2ecf20Sopenharmony_ci CARL9170FW_FIXED_5GHZ_PSM, 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* HW (ANI, CCA, MIB) tally counters */ 678c2ecf20Sopenharmony_ci CARL9170FW_HW_COUNTERS, 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* Firmware will pass BA when BARs are queued */ 708c2ecf20Sopenharmony_ci CARL9170FW_RX_BA_FILTER, 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* Firmware has support to write a byte at a time */ 738c2ecf20Sopenharmony_ci CARL9170FW_HAS_WREGB_CMD, 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* Pattern generator */ 768c2ecf20Sopenharmony_ci CARL9170FW_PATTERN_GENERATOR, 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* KEEP LAST */ 798c2ecf20Sopenharmony_ci __CARL9170FW_FEATURE_NUM 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define OTUS_MAGIC "OTAR" 838c2ecf20Sopenharmony_ci#define MOTD_MAGIC "MOTD" 848c2ecf20Sopenharmony_ci#define FIX_MAGIC "FIX\0" 858c2ecf20Sopenharmony_ci#define DBG_MAGIC "DBG\0" 868c2ecf20Sopenharmony_ci#define CHK_MAGIC "CHK\0" 878c2ecf20Sopenharmony_ci#define TXSQ_MAGIC "TXSQ" 888c2ecf20Sopenharmony_ci#define WOL_MAGIC "WOL\0" 898c2ecf20Sopenharmony_ci#define LAST_MAGIC "LAST" 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) 928c2ecf20Sopenharmony_ci#define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31) 938c2ecf20Sopenharmony_ci#define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define CARL9170FW_GET_DAY(d) (((d) % 31) + 1) 968c2ecf20Sopenharmony_ci#define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) 978c2ecf20Sopenharmony_ci#define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#define CARL9170FW_MAGIC_SIZE 4 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct carl9170fw_desc_head { 1028c2ecf20Sopenharmony_ci u8 magic[CARL9170FW_MAGIC_SIZE]; 1038c2ecf20Sopenharmony_ci __le16 length; 1048c2ecf20Sopenharmony_ci u8 min_ver; 1058c2ecf20Sopenharmony_ci u8 cur_ver; 1068c2ecf20Sopenharmony_ci} __packed; 1078c2ecf20Sopenharmony_ci#define CARL9170FW_DESC_HEAD_SIZE \ 1088c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_desc_head)) 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#define CARL9170FW_OTUS_DESC_MIN_VER 6 1118c2ecf20Sopenharmony_ci#define CARL9170FW_OTUS_DESC_CUR_VER 7 1128c2ecf20Sopenharmony_cistruct carl9170fw_otus_desc { 1138c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1148c2ecf20Sopenharmony_ci __le32 feature_set; 1158c2ecf20Sopenharmony_ci __le32 fw_address; 1168c2ecf20Sopenharmony_ci __le32 bcn_addr; 1178c2ecf20Sopenharmony_ci __le16 bcn_len; 1188c2ecf20Sopenharmony_ci __le16 miniboot_size; 1198c2ecf20Sopenharmony_ci __le16 tx_frag_len; 1208c2ecf20Sopenharmony_ci __le16 rx_max_frame_len; 1218c2ecf20Sopenharmony_ci u8 tx_descs; 1228c2ecf20Sopenharmony_ci u8 cmd_bufs; 1238c2ecf20Sopenharmony_ci u8 api_ver; 1248c2ecf20Sopenharmony_ci u8 vif_num; 1258c2ecf20Sopenharmony_ci} __packed; 1268c2ecf20Sopenharmony_ci#define CARL9170FW_OTUS_DESC_SIZE \ 1278c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_otus_desc)) 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#define CARL9170FW_MOTD_STRING_LEN 24 1308c2ecf20Sopenharmony_ci#define CARL9170FW_MOTD_RELEASE_LEN 20 1318c2ecf20Sopenharmony_ci#define CARL9170FW_MOTD_DESC_MIN_VER 1 1328c2ecf20Sopenharmony_ci#define CARL9170FW_MOTD_DESC_CUR_VER 2 1338c2ecf20Sopenharmony_cistruct carl9170fw_motd_desc { 1348c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1358c2ecf20Sopenharmony_ci __le32 fw_year_month_day; 1368c2ecf20Sopenharmony_ci char desc[CARL9170FW_MOTD_STRING_LEN]; 1378c2ecf20Sopenharmony_ci char release[CARL9170FW_MOTD_RELEASE_LEN]; 1388c2ecf20Sopenharmony_ci} __packed; 1398c2ecf20Sopenharmony_ci#define CARL9170FW_MOTD_DESC_SIZE \ 1408c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_motd_desc)) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define CARL9170FW_FIX_DESC_MIN_VER 1 1438c2ecf20Sopenharmony_ci#define CARL9170FW_FIX_DESC_CUR_VER 2 1448c2ecf20Sopenharmony_cistruct carl9170fw_fix_entry { 1458c2ecf20Sopenharmony_ci __le32 address; 1468c2ecf20Sopenharmony_ci __le32 mask; 1478c2ecf20Sopenharmony_ci __le32 value; 1488c2ecf20Sopenharmony_ci} __packed; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistruct carl9170fw_fix_desc { 1518c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1528c2ecf20Sopenharmony_ci struct carl9170fw_fix_entry data[0]; 1538c2ecf20Sopenharmony_ci} __packed; 1548c2ecf20Sopenharmony_ci#define CARL9170FW_FIX_DESC_SIZE \ 1558c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_fix_desc)) 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci#define CARL9170FW_DBG_DESC_MIN_VER 1 1588c2ecf20Sopenharmony_ci#define CARL9170FW_DBG_DESC_CUR_VER 3 1598c2ecf20Sopenharmony_cistruct carl9170fw_dbg_desc { 1608c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci __le32 bogoclock_addr; 1638c2ecf20Sopenharmony_ci __le32 counter_addr; 1648c2ecf20Sopenharmony_ci __le32 rx_total_addr; 1658c2ecf20Sopenharmony_ci __le32 rx_overrun_addr; 1668c2ecf20Sopenharmony_ci __le32 rx_filter; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* Put your debugging definitions here */ 1698c2ecf20Sopenharmony_ci} __packed; 1708c2ecf20Sopenharmony_ci#define CARL9170FW_DBG_DESC_SIZE \ 1718c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_dbg_desc)) 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#define CARL9170FW_CHK_DESC_MIN_VER 1 1748c2ecf20Sopenharmony_ci#define CARL9170FW_CHK_DESC_CUR_VER 2 1758c2ecf20Sopenharmony_cistruct carl9170fw_chk_desc { 1768c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1778c2ecf20Sopenharmony_ci __le32 fw_crc32; 1788c2ecf20Sopenharmony_ci __le32 hdr_crc32; 1798c2ecf20Sopenharmony_ci} __packed; 1808c2ecf20Sopenharmony_ci#define CARL9170FW_CHK_DESC_SIZE \ 1818c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_chk_desc)) 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci#define CARL9170FW_TXSQ_DESC_MIN_VER 1 1848c2ecf20Sopenharmony_ci#define CARL9170FW_TXSQ_DESC_CUR_VER 1 1858c2ecf20Sopenharmony_cistruct carl9170fw_txsq_desc { 1868c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci __le32 seq_table_addr; 1898c2ecf20Sopenharmony_ci} __packed; 1908c2ecf20Sopenharmony_ci#define CARL9170FW_TXSQ_DESC_SIZE \ 1918c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_txsq_desc)) 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#define CARL9170FW_WOL_DESC_MIN_VER 1 1948c2ecf20Sopenharmony_ci#define CARL9170FW_WOL_DESC_CUR_VER 1 1958c2ecf20Sopenharmony_cistruct carl9170fw_wol_desc { 1968c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci __le32 supported_triggers; /* CARL9170_WOL_ */ 1998c2ecf20Sopenharmony_ci} __packed; 2008c2ecf20Sopenharmony_ci#define CARL9170FW_WOL_DESC_SIZE \ 2018c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_wol_desc)) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci#define CARL9170FW_LAST_DESC_MIN_VER 1 2048c2ecf20Sopenharmony_ci#define CARL9170FW_LAST_DESC_CUR_VER 2 2058c2ecf20Sopenharmony_cistruct carl9170fw_last_desc { 2068c2ecf20Sopenharmony_ci struct carl9170fw_desc_head head; 2078c2ecf20Sopenharmony_ci} __packed; 2088c2ecf20Sopenharmony_ci#define CARL9170FW_LAST_DESC_SIZE \ 2098c2ecf20Sopenharmony_ci (sizeof(struct carl9170fw_fix_desc)) 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#define CARL9170FW_DESC_MAX_LENGTH 8192 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci#define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \ 2148c2ecf20Sopenharmony_ci .head = { \ 2158c2ecf20Sopenharmony_ci .magic = _magic, \ 2168c2ecf20Sopenharmony_ci .length = cpu_to_le16(_length), \ 2178c2ecf20Sopenharmony_ci .min_ver = _min_ver, \ 2188c2ecf20Sopenharmony_ci .cur_ver = _cur_ver, \ 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, 2228c2ecf20Sopenharmony_ci u8 magic[CARL9170FW_MAGIC_SIZE], 2238c2ecf20Sopenharmony_ci __le16 length, u8 min_ver, u8 cur_ver) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci head->magic[0] = magic[0]; 2268c2ecf20Sopenharmony_ci head->magic[1] = magic[1]; 2278c2ecf20Sopenharmony_ci head->magic[2] = magic[2]; 2288c2ecf20Sopenharmony_ci head->magic[3] = magic[3]; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci head->length = length; 2318c2ecf20Sopenharmony_ci head->min_ver = min_ver; 2328c2ecf20Sopenharmony_ci head->cur_ver = cur_ver; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#define carl9170fw_for_each_hdr(desc, fw_desc) \ 2368c2ecf20Sopenharmony_ci for (desc = fw_desc; \ 2378c2ecf20Sopenharmony_ci memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) && \ 2388c2ecf20Sopenharmony_ci le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ 2398c2ecf20Sopenharmony_ci le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ 2408c2ecf20Sopenharmony_ci desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci#define CHECK_HDR_VERSION(head, _min_ver) \ 2438c2ecf20Sopenharmony_ci (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \ 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic inline bool carl9170fw_supports(__le32 list, u8 feature) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci return le32_to_cpu(list) & BIT(feature); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, 2518c2ecf20Sopenharmony_ci const u8 descid[CARL9170FW_MAGIC_SIZE], 2528c2ecf20Sopenharmony_ci u16 min_len, u8 compatible_revision) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && 2558c2ecf20Sopenharmony_ci descid[2] == head->magic[2] && descid[3] == head->magic[3] && 2568c2ecf20Sopenharmony_ci !CHECK_HDR_VERSION(head, compatible_revision) && 2578c2ecf20Sopenharmony_ci (le16_to_cpu(head->length) >= min_len)) 2588c2ecf20Sopenharmony_ci return true; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return false; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci#define CARL9170FW_MIN_SIZE 32 2648c2ecf20Sopenharmony_ci#define CARL9170FW_MAX_SIZE 16384 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic inline bool carl9170fw_size_check(unsigned int len) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE); 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci#endif /* __CARL9170_SHARED_FWDESC_H */ 272