1 | /* SPDX-License-Identifier: ISC */ |
2 | /* |
3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
4 | * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc. |
5 | */ |
6 | |
7 | #ifndef _HIF_H_ |
8 | #define _HIF_H_ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include "core.h" |
12 | #include "bmi.h" |
13 | #include "debug.h" |
14 | |
15 | /* Types of fw logging mode */ |
16 | enum ath_dbg_mode { |
17 | ATH10K_ENABLE_FW_LOG_DIAG, |
18 | ATH10K_ENABLE_FW_LOG_CE, |
19 | }; |
20 | |
21 | struct ath10k_hif_sg_item { |
22 | u16 transfer_id; |
23 | void *transfer_context; /* NULL = tx completion callback not called */ |
24 | void *vaddr; /* for debugging mostly */ |
25 | dma_addr_t paddr; |
26 | u16 len; |
27 | }; |
28 | |
29 | struct ath10k_hif_ops { |
30 | /* send a scatter-gather list to the target */ |
31 | int (*tx_sg)(struct ath10k *ar, u8 pipe_id, |
32 | struct ath10k_hif_sg_item *items, int n_items); |
33 | |
34 | /* read firmware memory through the diagnose interface */ |
35 | int (*diag_read)(struct ath10k *ar, u32 address, void *buf, |
36 | size_t buf_len); |
37 | |
38 | int (*diag_write)(struct ath10k *ar, u32 address, const void *data, |
39 | int nbytes); |
40 | /* |
41 | * API to handle HIF-specific BMI message exchanges, this API is |
42 | * synchronous and only allowed to be called from a context that |
43 | * can block (sleep) |
44 | */ |
45 | int (*exchange_bmi_msg)(struct ath10k *ar, |
46 | void *request, u32 request_len, |
47 | void *response, u32 *response_len); |
48 | |
49 | /* Post BMI phase, after FW is loaded. Starts regular operation */ |
50 | int (*start)(struct ath10k *ar); |
51 | |
52 | /* Clean up what start() did. This does not revert to BMI phase. If |
53 | * desired so, call power_down() and power_up() |
54 | */ |
55 | void (*stop)(struct ath10k *ar); |
56 | |
57 | int (*start_post)(struct ath10k *ar); |
58 | |
59 | int (*get_htt_tx_complete)(struct ath10k *ar); |
60 | |
61 | int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, |
62 | u8 *ul_pipe, u8 *dl_pipe); |
63 | |
64 | void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe); |
65 | |
66 | /* |
67 | * Check if prior sends have completed. |
68 | * |
69 | * Check whether the pipe in question has any completed |
70 | * sends that have not yet been processed. |
71 | * This function is only relevant for HIF pipes that are configured |
72 | * to be polled rather than interrupt-driven. |
73 | */ |
74 | void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force); |
75 | |
76 | u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); |
77 | |
78 | u32 (*read32)(struct ath10k *ar, u32 address); |
79 | |
80 | void (*write32)(struct ath10k *ar, u32 address, u32 value); |
81 | |
82 | /* Power up the device and enter BMI transfer mode for FW download */ |
83 | int (*power_up)(struct ath10k *ar, enum ath10k_firmware_mode fw_mode); |
84 | |
85 | /* Power down the device and free up resources. stop() must be called |
86 | * before this if start() was called earlier |
87 | */ |
88 | void (*power_down)(struct ath10k *ar); |
89 | |
90 | int (*suspend)(struct ath10k *ar); |
91 | int (*resume)(struct ath10k *ar); |
92 | |
93 | /* fetch calibration data from target eeprom */ |
94 | int (*fetch_cal_eeprom)(struct ath10k *ar, void **data, |
95 | size_t *data_len); |
96 | |
97 | int (*get_target_info)(struct ath10k *ar, |
98 | struct bmi_target_info *target_info); |
99 | int (*set_target_log_mode)(struct ath10k *ar, u8 fw_log_mode); |
100 | }; |
101 | |
102 | static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, |
103 | struct ath10k_hif_sg_item *items, |
104 | int n_items) |
105 | { |
106 | return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items); |
107 | } |
108 | |
109 | static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf, |
110 | size_t buf_len) |
111 | { |
112 | return ar->hif.ops->diag_read(ar, address, buf, buf_len); |
113 | } |
114 | |
115 | static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address, |
116 | const void *data, int nbytes) |
117 | { |
118 | if (!ar->hif.ops->diag_write) |
119 | return -EOPNOTSUPP; |
120 | |
121 | return ar->hif.ops->diag_write(ar, address, data, nbytes); |
122 | } |
123 | |
124 | static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, |
125 | void *request, u32 request_len, |
126 | void *response, u32 *response_len) |
127 | { |
128 | return ar->hif.ops->exchange_bmi_msg(ar, request, request_len, |
129 | response, response_len); |
130 | } |
131 | |
132 | static inline int ath10k_hif_start(struct ath10k *ar) |
133 | { |
134 | return ar->hif.ops->start(ar); |
135 | } |
136 | |
137 | static inline void ath10k_hif_stop(struct ath10k *ar) |
138 | { |
139 | return ar->hif.ops->stop(ar); |
140 | } |
141 | |
142 | static inline int ath10k_hif_start_post(struct ath10k *ar) |
143 | { |
144 | if (ar->hif.ops->start_post) |
145 | return ar->hif.ops->start_post(ar); |
146 | return 0; |
147 | } |
148 | |
149 | static inline int ath10k_hif_get_htt_tx_complete(struct ath10k *ar) |
150 | { |
151 | if (ar->hif.ops->get_htt_tx_complete) |
152 | return ar->hif.ops->get_htt_tx_complete(ar); |
153 | return 0; |
154 | } |
155 | |
156 | static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, |
157 | u16 service_id, |
158 | u8 *ul_pipe, u8 *dl_pipe) |
159 | { |
160 | return ar->hif.ops->map_service_to_pipe(ar, service_id, |
161 | ul_pipe, dl_pipe); |
162 | } |
163 | |
164 | static inline void ath10k_hif_get_default_pipe(struct ath10k *ar, |
165 | u8 *ul_pipe, u8 *dl_pipe) |
166 | { |
167 | ar->hif.ops->get_default_pipe(ar, ul_pipe, dl_pipe); |
168 | } |
169 | |
170 | static inline void ath10k_hif_send_complete_check(struct ath10k *ar, |
171 | u8 pipe_id, int force) |
172 | { |
173 | if (ar->hif.ops->send_complete_check) |
174 | ar->hif.ops->send_complete_check(ar, pipe_id, force); |
175 | } |
176 | |
177 | static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar, |
178 | u8 pipe_id) |
179 | { |
180 | return ar->hif.ops->get_free_queue_number(ar, pipe_id); |
181 | } |
182 | |
183 | static inline int ath10k_hif_power_up(struct ath10k *ar, |
184 | enum ath10k_firmware_mode fw_mode) |
185 | { |
186 | return ar->hif.ops->power_up(ar, fw_mode); |
187 | } |
188 | |
189 | static inline void ath10k_hif_power_down(struct ath10k *ar) |
190 | { |
191 | ar->hif.ops->power_down(ar); |
192 | } |
193 | |
194 | static inline int ath10k_hif_suspend(struct ath10k *ar) |
195 | { |
196 | if (!ar->hif.ops->suspend) |
197 | return -EOPNOTSUPP; |
198 | |
199 | return ar->hif.ops->suspend(ar); |
200 | } |
201 | |
202 | static inline int ath10k_hif_resume(struct ath10k *ar) |
203 | { |
204 | if (!ar->hif.ops->resume) |
205 | return -EOPNOTSUPP; |
206 | |
207 | return ar->hif.ops->resume(ar); |
208 | } |
209 | |
210 | static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address) |
211 | { |
212 | if (!ar->hif.ops->read32) { |
213 | ath10k_warn(ar, fmt: "hif read32 not supported\n" ); |
214 | return 0xdeaddead; |
215 | } |
216 | |
217 | return ar->hif.ops->read32(ar, address); |
218 | } |
219 | |
220 | static inline void ath10k_hif_write32(struct ath10k *ar, |
221 | u32 address, u32 data) |
222 | { |
223 | if (!ar->hif.ops->write32) { |
224 | ath10k_warn(ar, fmt: "hif write32 not supported\n" ); |
225 | return; |
226 | } |
227 | |
228 | ar->hif.ops->write32(ar, address, data); |
229 | } |
230 | |
231 | static inline int ath10k_hif_fetch_cal_eeprom(struct ath10k *ar, |
232 | void **data, |
233 | size_t *data_len) |
234 | { |
235 | if (!ar->hif.ops->fetch_cal_eeprom) |
236 | return -EOPNOTSUPP; |
237 | |
238 | return ar->hif.ops->fetch_cal_eeprom(ar, data, data_len); |
239 | } |
240 | |
241 | static inline int ath10k_hif_get_target_info(struct ath10k *ar, |
242 | struct bmi_target_info *tgt_info) |
243 | { |
244 | if (!ar->hif.ops->get_target_info) |
245 | return -EOPNOTSUPP; |
246 | |
247 | return ar->hif.ops->get_target_info(ar, tgt_info); |
248 | } |
249 | |
250 | static inline int ath10k_hif_set_target_log_mode(struct ath10k *ar, |
251 | u8 fw_log_mode) |
252 | { |
253 | if (!ar->hif.ops->set_target_log_mode) |
254 | return -EOPNOTSUPP; |
255 | |
256 | return ar->hif.ops->set_target_log_mode(ar, fw_log_mode); |
257 | } |
258 | #endif /* _HIF_H_ */ |
259 | |