Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
| 3 | * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. |
| 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above |
| 7 | * copyright notice and this permission notice appear in all copies. |
| 8 | * |
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 16 | */ |
| 17 | |
| 18 | #ifndef _HTC_H_ |
| 19 | #define _HTC_H_ |
| 20 | |
| 21 | #include <linux/kernel.h> |
| 22 | #include <linux/list.h> |
| 23 | #include <linux/bug.h> |
| 24 | #include <linux/skbuff.h> |
| 25 | #include <linux/semaphore.h> |
| 26 | #include <linux/timer.h> |
| 27 | |
| 28 | struct ath10k; |
| 29 | |
| 30 | /****************/ |
| 31 | /* HTC protocol */ |
| 32 | /****************/ |
| 33 | |
| 34 | /* |
| 35 | * HTC - host-target control protocol |
| 36 | * |
| 37 | * tx packets are generally <htc_hdr><payload> |
| 38 | * rx packets are more complex: <htc_hdr><payload><trailer> |
| 39 | * |
| 40 | * The payload + trailer length is stored in len. |
| 41 | * To get payload-only length one needs to payload - trailer_len. |
| 42 | * |
| 43 | * Trailer contains (possibly) multiple <htc_record>. |
| 44 | * Each record is a id-len-value. |
| 45 | * |
| 46 | * HTC header flags, control_byte0, control_byte1 |
| 47 | * have different meaning depending whether its tx |
| 48 | * or rx. |
| 49 | * |
| 50 | * Alignment: htc_hdr, payload and trailer are |
| 51 | * 4-byte aligned. |
| 52 | */ |
| 53 | |
| 54 | enum ath10k_htc_tx_flags { |
| 55 | ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01, |
| 56 | ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02 |
| 57 | }; |
| 58 | |
| 59 | enum ath10k_htc_rx_flags { |
| 60 | ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02, |
| 61 | ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0 |
| 62 | }; |
| 63 | |
| 64 | struct ath10k_htc_hdr { |
| 65 | u8 eid; /* @enum ath10k_htc_ep_id */ |
| 66 | u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */ |
| 67 | __le16 len; |
| 68 | union { |
| 69 | u8 trailer_len; /* for rx */ |
| 70 | u8 control_byte0; |
| 71 | } __packed; |
| 72 | union { |
| 73 | u8 seq_no; /* for tx */ |
| 74 | u8 control_byte1; |
| 75 | } __packed; |
| 76 | u8 pad0; |
| 77 | u8 pad1; |
| 78 | } __packed __aligned(4); |
| 79 | |
| 80 | enum ath10k_ath10k_htc_msg_id { |
| 81 | ATH10K_HTC_MSG_READY_ID = 1, |
| 82 | ATH10K_HTC_MSG_CONNECT_SERVICE_ID = 2, |
| 83 | ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3, |
| 84 | ATH10K_HTC_MSG_SETUP_COMPLETE_ID = 4, |
| 85 | ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID = 5, |
| 86 | ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6 |
| 87 | }; |
| 88 | |
| 89 | enum ath10k_htc_version { |
| 90 | ATH10K_HTC_VERSION_2P0 = 0x00, /* 2.0 */ |
| 91 | ATH10K_HTC_VERSION_2P1 = 0x01, /* 2.1 */ |
| 92 | }; |
| 93 | |
| 94 | enum ath10k_htc_conn_flags { |
| 95 | ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH = 0x0, |
| 96 | ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF = 0x1, |
| 97 | ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2, |
| 98 | ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY = 0x3, |
| 99 | #define ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK 0x3 |
| 100 | ATH10K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE = 1 << 2, |
| 101 | ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3 |
| 102 | #define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_MASK 0xFF00 |
| 103 | #define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB 8 |
| 104 | }; |
| 105 | |
| 106 | enum ath10k_htc_conn_svc_status { |
| 107 | ATH10K_HTC_CONN_SVC_STATUS_SUCCESS = 0, |
| 108 | ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND = 1, |
| 109 | ATH10K_HTC_CONN_SVC_STATUS_FAILED = 2, |
| 110 | ATH10K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3, |
| 111 | ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP = 4 |
| 112 | }; |
| 113 | |
| 114 | struct ath10k_ath10k_htc_msg_hdr { |
| 115 | __le16 message_id; /* @enum htc_message_id */ |
| 116 | } __packed; |
| 117 | |
| 118 | struct ath10k_htc_unknown { |
| 119 | u8 pad0; |
| 120 | u8 pad1; |
| 121 | } __packed; |
| 122 | |
| 123 | struct ath10k_htc_ready { |
| 124 | __le16 credit_count; |
| 125 | __le16 credit_size; |
| 126 | u8 max_endpoints; |
| 127 | u8 pad0; |
| 128 | } __packed; |
| 129 | |
| 130 | struct ath10k_htc_ready_extended { |
| 131 | struct ath10k_htc_ready base; |
| 132 | u8 htc_version; /* @enum ath10k_htc_version */ |
| 133 | u8 max_msgs_per_htc_bundle; |
| 134 | u8 pad0; |
| 135 | u8 pad1; |
| 136 | } __packed; |
| 137 | |
| 138 | struct ath10k_htc_conn_svc { |
| 139 | __le16 service_id; |
| 140 | __le16 flags; /* @enum ath10k_htc_conn_flags */ |
| 141 | u8 pad0; |
| 142 | u8 pad1; |
| 143 | } __packed; |
| 144 | |
| 145 | struct ath10k_htc_conn_svc_response { |
| 146 | __le16 service_id; |
| 147 | u8 status; /* @enum ath10k_htc_conn_svc_status */ |
| 148 | u8 eid; |
| 149 | __le16 max_msg_size; |
| 150 | } __packed; |
| 151 | |
| 152 | struct ath10k_htc_setup_complete_extended { |
| 153 | u8 pad0; |
| 154 | u8 pad1; |
| 155 | __le32 flags; /* @enum htc_setup_complete_flags */ |
| 156 | u8 max_msgs_per_bundled_recv; |
| 157 | u8 pad2; |
| 158 | u8 pad3; |
| 159 | u8 pad4; |
| 160 | } __packed; |
| 161 | |
| 162 | struct ath10k_htc_msg { |
| 163 | struct ath10k_ath10k_htc_msg_hdr hdr; |
| 164 | union { |
| 165 | /* host-to-target */ |
| 166 | struct ath10k_htc_conn_svc connect_service; |
| 167 | struct ath10k_htc_ready ready; |
| 168 | struct ath10k_htc_ready_extended ready_ext; |
| 169 | struct ath10k_htc_unknown unknown; |
| 170 | struct ath10k_htc_setup_complete_extended setup_complete_ext; |
| 171 | |
| 172 | /* target-to-host */ |
| 173 | struct ath10k_htc_conn_svc_response connect_service_response; |
| 174 | }; |
| 175 | } __packed __aligned(4); |
| 176 | |
| 177 | enum ath10k_ath10k_htc_record_id { |
| 178 | ATH10K_HTC_RECORD_NULL = 0, |
| 179 | ATH10K_HTC_RECORD_CREDITS = 1 |
| 180 | }; |
| 181 | |
| 182 | struct ath10k_ath10k_htc_record_hdr { |
| 183 | u8 id; /* @enum ath10k_ath10k_htc_record_id */ |
| 184 | u8 len; |
| 185 | u8 pad0; |
| 186 | u8 pad1; |
| 187 | } __packed; |
| 188 | |
| 189 | struct ath10k_htc_credit_report { |
| 190 | u8 eid; /* @enum ath10k_htc_ep_id */ |
| 191 | u8 credits; |
| 192 | u8 pad0; |
| 193 | u8 pad1; |
| 194 | } __packed; |
| 195 | |
| 196 | struct ath10k_htc_record { |
| 197 | struct ath10k_ath10k_htc_record_hdr hdr; |
| 198 | union { |
| 199 | struct ath10k_htc_credit_report credit_report[0]; |
| 200 | u8 pauload[0]; |
| 201 | }; |
| 202 | } __packed __aligned(4); |
| 203 | |
| 204 | /* |
| 205 | * note: the trailer offset is dynamic depending |
| 206 | * on payload length. this is only a struct layout draft |
| 207 | */ |
| 208 | struct ath10k_htc_frame { |
| 209 | struct ath10k_htc_hdr hdr; |
| 210 | union { |
| 211 | struct ath10k_htc_msg msg; |
| 212 | u8 payload[0]; |
| 213 | }; |
| 214 | struct ath10k_htc_record trailer[0]; |
| 215 | } __packed __aligned(4); |
| 216 | |
| 217 | |
| 218 | /*******************/ |
| 219 | /* Host-side stuff */ |
| 220 | /*******************/ |
| 221 | |
| 222 | enum ath10k_htc_svc_gid { |
| 223 | ATH10K_HTC_SVC_GRP_RSVD = 0, |
| 224 | ATH10K_HTC_SVC_GRP_WMI = 1, |
| 225 | ATH10K_HTC_SVC_GRP_NMI = 2, |
| 226 | ATH10K_HTC_SVC_GRP_HTT = 3, |
| 227 | |
| 228 | ATH10K_HTC_SVC_GRP_TEST = 254, |
| 229 | ATH10K_HTC_SVC_GRP_LAST = 255, |
| 230 | }; |
| 231 | |
| 232 | #define SVC(group, idx) \ |
| 233 | (int)(((int)(group) << 8) | (int)(idx)) |
| 234 | |
| 235 | enum ath10k_htc_svc_id { |
| 236 | /* NOTE: service ID of 0x0000 is reserved and should never be used */ |
| 237 | ATH10K_HTC_SVC_ID_RESERVED = 0x0000, |
| 238 | ATH10K_HTC_SVC_ID_UNUSED = ATH10K_HTC_SVC_ID_RESERVED, |
| 239 | |
| 240 | ATH10K_HTC_SVC_ID_RSVD_CTRL = SVC(ATH10K_HTC_SVC_GRP_RSVD, 1), |
| 241 | ATH10K_HTC_SVC_ID_WMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_WMI, 0), |
| 242 | ATH10K_HTC_SVC_ID_WMI_DATA_BE = SVC(ATH10K_HTC_SVC_GRP_WMI, 1), |
| 243 | ATH10K_HTC_SVC_ID_WMI_DATA_BK = SVC(ATH10K_HTC_SVC_GRP_WMI, 2), |
| 244 | ATH10K_HTC_SVC_ID_WMI_DATA_VI = SVC(ATH10K_HTC_SVC_GRP_WMI, 3), |
| 245 | ATH10K_HTC_SVC_ID_WMI_DATA_VO = SVC(ATH10K_HTC_SVC_GRP_WMI, 4), |
| 246 | |
| 247 | ATH10K_HTC_SVC_ID_NMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_NMI, 0), |
| 248 | ATH10K_HTC_SVC_ID_NMI_DATA = SVC(ATH10K_HTC_SVC_GRP_NMI, 1), |
| 249 | |
| 250 | ATH10K_HTC_SVC_ID_HTT_DATA_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 0), |
| 251 | |
| 252 | /* raw stream service (i.e. flash, tcmd, calibration apps) */ |
| 253 | ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0), |
| 254 | }; |
| 255 | |
| 256 | #undef SVC |
| 257 | |
| 258 | enum ath10k_htc_ep_id { |
| 259 | ATH10K_HTC_EP_UNUSED = -1, |
| 260 | ATH10K_HTC_EP_0 = 0, |
| 261 | ATH10K_HTC_EP_1 = 1, |
| 262 | ATH10K_HTC_EP_2, |
| 263 | ATH10K_HTC_EP_3, |
| 264 | ATH10K_HTC_EP_4, |
| 265 | ATH10K_HTC_EP_5, |
| 266 | ATH10K_HTC_EP_6, |
| 267 | ATH10K_HTC_EP_7, |
| 268 | ATH10K_HTC_EP_8, |
| 269 | ATH10K_HTC_EP_COUNT, |
| 270 | }; |
| 271 | |
| 272 | struct ath10k_htc_ops { |
| 273 | void (*target_send_suspend_complete)(struct ath10k *ar); |
| 274 | }; |
| 275 | |
| 276 | struct ath10k_htc_ep_ops { |
| 277 | void (*ep_tx_complete)(struct ath10k *, struct sk_buff *); |
| 278 | void (*ep_rx_complete)(struct ath10k *, struct sk_buff *); |
Michal Kazior | 88e65fc | 2013-09-13 14:16:53 +0200 | [diff] [blame] | 279 | void (*ep_tx_credits)(struct ath10k *); |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 280 | }; |
| 281 | |
| 282 | /* service connection information */ |
| 283 | struct ath10k_htc_svc_conn_req { |
| 284 | u16 service_id; |
| 285 | struct ath10k_htc_ep_ops ep_ops; |
| 286 | int max_send_queue_depth; |
| 287 | }; |
| 288 | |
| 289 | /* service connection response information */ |
| 290 | struct ath10k_htc_svc_conn_resp { |
| 291 | u8 buffer_len; |
| 292 | u8 actual_len; |
| 293 | enum ath10k_htc_ep_id eid; |
| 294 | unsigned int max_msg_len; |
| 295 | u8 connect_resp_code; |
| 296 | }; |
| 297 | |
| 298 | #define ATH10K_NUM_CONTROL_TX_BUFFERS 2 |
| 299 | #define ATH10K_HTC_MAX_LEN 4096 |
| 300 | #define ATH10K_HTC_MAX_CTRL_MSG_LEN 256 |
| 301 | #define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ) |
| 302 | #define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \ |
| 303 | sizeof(struct ath10k_htc_hdr)) |
| 304 | #define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ) |
| 305 | |
| 306 | struct ath10k_htc_ep { |
| 307 | struct ath10k_htc *htc; |
| 308 | enum ath10k_htc_ep_id eid; |
| 309 | enum ath10k_htc_svc_id service_id; |
| 310 | struct ath10k_htc_ep_ops ep_ops; |
| 311 | |
| 312 | int max_tx_queue_depth; |
| 313 | int max_ep_message_len; |
| 314 | u8 ul_pipe_id; |
| 315 | u8 dl_pipe_id; |
| 316 | int ul_is_polled; /* call HIF to get tx completions */ |
| 317 | int dl_is_polled; /* call HIF to fetch rx (not implemented) */ |
| 318 | |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 319 | u8 seq_no; /* for debugging */ |
| 320 | int tx_credits; |
| 321 | int tx_credit_size; |
| 322 | int tx_credits_per_max_message; |
| 323 | bool tx_credit_flow_enabled; |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 324 | }; |
| 325 | |
| 326 | struct ath10k_htc_svc_tx_credits { |
| 327 | u16 service_id; |
| 328 | u8 credit_allocation; |
| 329 | }; |
| 330 | |
| 331 | struct ath10k_htc { |
| 332 | struct ath10k *ar; |
| 333 | struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT]; |
| 334 | |
Michal Kazior | b7967dc | 2014-08-07 11:03:31 +0200 | [diff] [blame^] | 335 | /* protects endpoints */ |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 336 | spinlock_t tx_lock; |
| 337 | |
| 338 | struct ath10k_htc_ops htc_ops; |
| 339 | |
| 340 | u8 control_resp_buffer[ATH10K_HTC_MAX_CTRL_MSG_LEN]; |
| 341 | int control_resp_len; |
| 342 | |
| 343 | struct completion ctl_resp; |
| 344 | |
| 345 | int total_transmit_credits; |
| 346 | struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; |
| 347 | int target_credit_size; |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 348 | }; |
| 349 | |
Michal Kazior | cd003fa | 2013-07-05 16:15:13 +0300 | [diff] [blame] | 350 | int ath10k_htc_init(struct ath10k *ar); |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 351 | int ath10k_htc_wait_target(struct ath10k_htc *htc); |
| 352 | int ath10k_htc_start(struct ath10k_htc *htc); |
| 353 | int ath10k_htc_connect_service(struct ath10k_htc *htc, |
| 354 | struct ath10k_htc_svc_conn_req *conn_req, |
| 355 | struct ath10k_htc_svc_conn_resp *conn_resp); |
| 356 | int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, |
| 357 | struct sk_buff *packet); |
Kalle Valo | 5e3dd15 | 2013-06-12 20:52:10 +0300 | [diff] [blame] | 358 | struct sk_buff *ath10k_htc_alloc_skb(int size); |
| 359 | |
| 360 | #endif |