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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 226 void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe, 227 int force) 228 { 229 230 } 231 232