1 /*
2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <qdf_types.h>
21 #include <qdf_status.h>
22 #include <qdf_timer.h>
23 #include <qdf_time.h>
24 #include <qdf_lock.h>
25 #include <qdf_mem.h>
26 #include <qdf_util.h>
27 #include <qdf_defer.h>
28 #include <qdf_atomic.h>
29 #include <qdf_nbuf.h>
30 #include <athdefs.h>
31 #include "qdf_net_types.h"
32 #include "a_types.h"
33 #include "athdefs.h"
34 #include "a_osapi.h"
35 #include <hif.h>
36 #include <htc_services.h>
37 #include <a_debug.h>
38 #include "hif_sdio_dev.h"
39 #include "if_sdio.h"
40 #include "regtable_sdio.h"
41 #include <transfer/transfer.h>
42
43 #define ATH_MODULE_NAME hif_sdio
44
45 /**
46 * hif_start() - start hif bus interface.
47 * @hif_ctx: HIF context
48 *
49 * Enables hif device interrupts
50 *
51 * Return: QDF_STATUS
52 */
hif_start(struct hif_opaque_softc * hif_ctx)53 QDF_STATUS hif_start(struct hif_opaque_softc *hif_ctx)
54 {
55 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
56 struct hif_sdio_dev *hif_device = scn->hif_handle;
57 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device);
58 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
59 int ret = 0;
60
61 HIF_ENTER();
62 ret = hif_sdio_bus_configure(hif_sc);
63 if (ret) {
64 hif_err("hif_sdio_bus_configure failed");
65 return QDF_STATUS_E_FAILURE;
66 }
67
68 hif_dev_enable_interrupts(htc_sdio_device);
69 HIF_EXIT();
70 return QDF_STATUS_SUCCESS;
71 }
72
73 /**
74 * hif_flush_surprise_remove() - remove hif bus interface.
75 * @hif_ctx: HIF context
76 *
77 *
78 * Return: none
79 */
hif_flush_surprise_remove(struct hif_opaque_softc * hif_ctx)80 void hif_flush_surprise_remove(struct hif_opaque_softc *hif_ctx)
81 {
82
83 }
84
85 /**
86 * hif_sdio_stop() - stop hif bus interface.
87 * @hif_ctx: HIF context
88 *
89 * Disable hif device interrupts and destroy hif context
90 *
91 * Return: none
92 */
hif_sdio_stop(struct hif_softc * hif_ctx)93 void hif_sdio_stop(struct hif_softc *hif_ctx)
94 {
95 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
96 struct hif_sdio_dev *hif_device = scn->hif_handle;
97 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device);
98
99 HIF_ENTER();
100 if (htc_sdio_device) {
101 hif_dev_disable_interrupts(htc_sdio_device);
102 hif_dev_destroy(htc_sdio_device);
103 }
104 HIF_EXIT();
105 }
106
107 /**
108 * hif_send_head() - send data on hif bus interface.
109 * @hif_ctx: HIF context
110 * @pipe:
111 * @transfer_id:
112 * @nbytes:
113 * @buf:
114 * @data_attr:
115 *
116 * send tx data on a given pipe id
117 *
118 * Return: QDF_STATUS
119 */
hif_send_head(struct hif_opaque_softc * hif_ctx,uint8_t pipe,uint32_t transfer_id,uint32_t nbytes,qdf_nbuf_t buf,uint32_t data_attr)120 QDF_STATUS hif_send_head(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
121 uint32_t transfer_id, uint32_t nbytes, qdf_nbuf_t buf,
122 uint32_t data_attr)
123 {
124 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
125 struct hif_sdio_dev *hif_device = scn->hif_handle;
126 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device);
127
128 return hif_dev_send_buffer(htc_sdio_device,
129 transfer_id, pipe,
130 nbytes, buf);
131 }
132
133 /**
134 * hif_map_service_to_pipe() - maps ul/dl pipe to service id.
135 * @hif_hdl: HIF hdl
136 * @service_id: service index
137 * @ul_pipe: uplink pipe id
138 * @dl_pipe: down-linklink pipe id
139 * @ul_is_polled: if ul is polling based
140 * @dl_is_polled: if dl is polling based
141 *
142 * Return: int
143 */
hif_map_service_to_pipe(struct hif_opaque_softc * hif_hdl,uint16_t service_id,uint8_t * ul_pipe,uint8_t * dl_pipe,int * ul_is_polled,int * dl_is_polled)144 int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl,
145 uint16_t service_id, uint8_t *ul_pipe,
146 uint8_t *dl_pipe, int *ul_is_polled,
147 int *dl_is_polled)
148 {
149 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_hdl);
150 struct hif_sdio_dev *hif_device = scn->hif_handle;
151 QDF_STATUS status;
152
153 status = hif_dev_map_service_to_pipe(hif_device,
154 service_id, ul_pipe, dl_pipe);
155 return qdf_status_to_os_return(status);
156 }
157
158 /**
159 * hif_get_default_pipe() - get default pipe
160 * @scn: HIF context
161 * @ul_pipe: uplink pipe id
162 * @dl_pipe: down-linklink pipe id
163 */
hif_get_default_pipe(struct hif_opaque_softc * scn,uint8_t * ul_pipe,uint8_t * dl_pipe)164 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe,
165 uint8_t *dl_pipe)
166 {
167 hif_map_service_to_pipe(scn, HTC_CTRL_RSVD_SVC,
168 ul_pipe, dl_pipe, NULL, NULL);
169 }
170
171 /**
172 * hif_post_init() - create hif device after probe.
173 * @hif_ctx: HIF context
174 * @target: HIF target
175 * @callbacks: htc callbacks
176 *
177 *
178 * Return: int
179 */
hif_post_init(struct hif_opaque_softc * hif_ctx,void * target,struct hif_msg_callbacks * callbacks)180 void hif_post_init(struct hif_opaque_softc *hif_ctx, void *target,
181 struct hif_msg_callbacks *callbacks)
182 {
183 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
184 struct hif_sdio_dev *hif_device = scn->hif_handle;
185 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device);
186
187 HIF_ENTER();
188
189 if (!htc_sdio_device)
190 htc_sdio_device = hif_dev_create(hif_device, callbacks, target);
191
192 if (htc_sdio_device)
193 hif_dev_setup(htc_sdio_device);
194
195 HIF_EXIT();
196 }
197
198 /**
199 * hif_get_free_queue_number() - create hif device after probe.
200 * @hif_ctx: HIF context
201 * @pipe: pipe id
202 *
203 * SDIO uses credit based flow control at the HTC layer
204 * so transmit resource checks are bypassed
205 * Return: int
206 */
hif_get_free_queue_number(struct hif_opaque_softc * hif_ctx,uint8_t pipe)207 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *hif_ctx,
208 uint8_t pipe)
209 {
210 uint16_t rv;
211
212 rv = 1;
213 return rv;
214 }
215
216 /**
217 * hif_send_complete_check() - check tx complete on a given pipe.
218 * @hif_ctx: HIF context
219 * @pipe: HIF target
220 * @force: check if need to pool for completion
221 * Decide whether to actually poll for completions, or just
222 * wait for a later chance.
223 *
224 * Return: int
225 */
hif_send_complete_check(struct hif_opaque_softc * hif_ctx,uint8_t pipe,int force)226 void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
227 int force)
228 {
229
230 }
231
232