Vladimir Kondratiev | 151a970 | 2014-09-10 16:34:30 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. |
| 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above |
| 6 | * copyright notice and this permission notice appear in all copies. |
| 7 | * |
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 15 | */ |
| 16 | |
| 17 | #define WIL_FW_SIGNATURE (0x36323130) /* '0126' */ |
| 18 | #define WIL_FW_FMT_VERSION (1) /* format version driver supports */ |
| 19 | |
| 20 | enum wil_fw_record_type { |
| 21 | wil_fw_type_comment = 1, |
| 22 | wil_fw_type_data = 2, |
| 23 | wil_fw_type_fill = 3, |
| 24 | wil_fw_type_action = 4, |
| 25 | wil_fw_type_verify = 5, |
| 26 | wil_fw_type_file_header = 6, |
| 27 | wil_fw_type_direct_write = 7, |
| 28 | wil_fw_type_gateway_data = 8, |
| 29 | wil_fw_type_gateway_data4 = 9, |
| 30 | }; |
| 31 | |
| 32 | struct wil_fw_record_head { |
| 33 | __le16 type; /* enum wil_fw_record_type */ |
| 34 | __le16 flags; /* to be defined */ |
| 35 | __le32 size; /* whole record, bytes after head */ |
| 36 | } __packed; |
| 37 | |
| 38 | /* data block. write starting from @addr |
| 39 | * data_size inferred from the @head.size. For this case, |
| 40 | * data_size = @head.size - offsetof(struct wil_fw_record_data, data) |
| 41 | */ |
| 42 | struct wil_fw_record_data { /* type == wil_fw_type_data */ |
| 43 | __le32 addr; |
| 44 | __le32 data[0]; /* [data_size], see above */ |
| 45 | } __packed; |
| 46 | |
| 47 | /* fill with constant @value, @size bytes starting from @addr */ |
| 48 | struct wil_fw_record_fill { /* type == wil_fw_type_fill */ |
| 49 | __le32 addr; |
| 50 | __le32 value; |
| 51 | __le32 size; |
| 52 | } __packed; |
| 53 | |
| 54 | /* free-form comment |
| 55 | * for informational purpose, data_size is @head.size from record header |
| 56 | */ |
| 57 | struct wil_fw_record_comment { /* type == wil_fw_type_comment */ |
| 58 | u8 data[0]; /* free-form data [data_size], see above */ |
| 59 | } __packed; |
| 60 | |
| 61 | /* perform action |
| 62 | * data_size = @head.size - offsetof(struct wil_fw_record_action, data) |
| 63 | */ |
| 64 | struct wil_fw_record_action { /* type == wil_fw_type_action */ |
| 65 | __le32 action; /* action to perform: reset, wait for fw ready etc. */ |
| 66 | __le32 data[0]; /* action specific, [data_size], see above */ |
| 67 | } __packed; |
| 68 | |
| 69 | /* data block for struct wil_fw_record_direct_write */ |
| 70 | struct wil_fw_data_dwrite { |
| 71 | __le32 addr; |
| 72 | __le32 value; |
| 73 | __le32 mask; |
| 74 | } __packed; |
| 75 | |
| 76 | /* write @value to the @addr, |
| 77 | * preserve original bits accordingly to the @mask |
| 78 | * data_size is @head.size where @head is record header |
| 79 | */ |
| 80 | struct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */ |
| 81 | struct wil_fw_data_dwrite data[0]; |
| 82 | } __packed; |
| 83 | |
| 84 | /* verify condition: [@addr] & @mask == @value |
| 85 | * if condition not met, firmware download fails |
| 86 | */ |
| 87 | struct wil_fw_record_verify { /* type == wil_fw_verify */ |
| 88 | __le32 addr; /* read from this address */ |
| 89 | __le32 value; /* reference value */ |
| 90 | __le32 mask; /* mask for verification */ |
| 91 | } __packed; |
| 92 | |
| 93 | /* file header |
| 94 | * First record of every file |
| 95 | */ |
| 96 | struct wil_fw_record_file_header { |
| 97 | __le32 signature ; /* Wilocity signature */ |
| 98 | __le32 reserved; |
| 99 | __le32 crc; /* crc32 of the following data */ |
| 100 | __le32 version; /* format version */ |
| 101 | __le32 data_len; /* total data in file, including this record */ |
| 102 | u8 comment[32]; /* short description */ |
| 103 | } __packed; |
| 104 | |
| 105 | /* 1-dword gateway */ |
| 106 | /* data block for the struct wil_fw_record_gateway_data */ |
| 107 | struct wil_fw_data_gw { |
| 108 | __le32 addr; |
| 109 | __le32 value; |
| 110 | } __packed; |
| 111 | |
| 112 | /* gateway write block. |
| 113 | * write starting address and values from the data buffer |
| 114 | * through the gateway |
| 115 | * data_size inferred from the @head.size. For this case, |
| 116 | * data_size = @head.size - offsetof(struct wil_fw_record_gateway_data, data) |
| 117 | */ |
| 118 | struct wil_fw_record_gateway_data { /* type == wil_fw_type_gateway_data */ |
| 119 | __le32 gateway_addr_addr; |
| 120 | __le32 gateway_value_addr; |
| 121 | __le32 gateway_cmd_addr; |
| 122 | __le32 gateway_ctrl_address; |
| 123 | #define WIL_FW_GW_CTL_BUSY BIT(29) /* gateway busy performing operation */ |
| 124 | #define WIL_FW_GW_CTL_RUN BIT(30) /* start gateway operation */ |
| 125 | __le32 command; |
| 126 | struct wil_fw_data_gw data[0]; /* total size [data_size], see above */ |
| 127 | } __packed; |
| 128 | |
| 129 | /* 4-dword gateway */ |
| 130 | /* data block for the struct wil_fw_record_gateway_data4 */ |
| 131 | struct wil_fw_data_gw4 { |
| 132 | __le32 addr; |
| 133 | __le32 value[4]; |
| 134 | } __packed; |
| 135 | |
| 136 | /* gateway write block. |
| 137 | * write starting address and values from the data buffer |
| 138 | * through the gateway |
| 139 | * data_size inferred from the @head.size. For this case, |
| 140 | * data_size = @head.size - offsetof(struct wil_fw_record_gateway_data4, data) |
| 141 | */ |
| 142 | struct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */ |
| 143 | __le32 gateway_addr_addr; |
| 144 | __le32 gateway_value_addr[4]; |
| 145 | __le32 gateway_cmd_addr; |
| 146 | __le32 gateway_ctrl_address; /* same logic as for 1-dword gw */ |
| 147 | __le32 command; |
| 148 | struct wil_fw_data_gw4 data[0]; /* total size [data_size], see above */ |
| 149 | } __packed; |