1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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 * 111 * send tx data on a given pipe id 112 * 113 * Return: QDF_STATUS 114 */ 115 QDF_STATUS hif_send_head(struct hif_opaque_softc *hif_ctx, uint8_t pipe, 116 uint32_t transfer_id, uint32_t nbytes, qdf_nbuf_t buf, 117 uint32_t data_attr) 118 { 119 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 120 struct hif_sdio_dev *hif_device = scn->hif_handle; 121 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 122 123 return hif_dev_send_buffer(htc_sdio_device, 124 transfer_id, pipe, 125 nbytes, buf); 126 } 127 128 /** 129 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 130 * @hif_ctx: HIF hdl 131 * @ServiceId: service index 132 * @ul_pipe: uplink pipe id 133 * @dl_pipe: down-linklink pipe id 134 * @ul_is_polled: if ul is polling based 135 * @ul_is_polled: if dl is polling based 136 * 137 * Return: int 138 */ 139 int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl, 140 uint16_t service_id, uint8_t *ul_pipe, 141 uint8_t *dl_pipe, int *ul_is_polled, 142 int *dl_is_polled) 143 { 144 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_hdl); 145 struct hif_sdio_dev *hif_device = scn->hif_handle; 146 QDF_STATUS status; 147 148 status = hif_dev_map_service_to_pipe(hif_device, 149 service_id, ul_pipe, dl_pipe); 150 return qdf_status_to_os_return(status); 151 } 152 153 /** 154 * hif_get_default_pipe() - get default pipe 155 * @scn: HIF context 156 * @ul_pipe: uplink pipe id 157 * @dl_pipe: down-linklink pipe id 158 */ 159 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe, 160 uint8_t *dl_pipe) 161 { 162 hif_map_service_to_pipe(scn, HTC_CTRL_RSVD_SVC, 163 ul_pipe, dl_pipe, NULL, NULL); 164 } 165 166 /** 167 * hif_post_init() - create hif device after probe. 168 * @hif_ctx: HIF context 169 * @target: HIF target 170 * @callbacks: htc callbacks 171 * 172 * 173 * Return: int 174 */ 175 void hif_post_init(struct hif_opaque_softc *hif_ctx, void *target, 176 struct hif_msg_callbacks *callbacks) 177 { 178 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 179 struct hif_sdio_dev *hif_device = scn->hif_handle; 180 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 181 182 HIF_ENTER(); 183 184 if (!htc_sdio_device) 185 htc_sdio_device = hif_dev_create(hif_device, callbacks, target); 186 187 if (htc_sdio_device) 188 hif_dev_setup(htc_sdio_device); 189 190 HIF_EXIT(); 191 } 192 193 /** 194 * hif_get_free_queue_number() - create hif device after probe. 195 * @hif_ctx: HIF context 196 * @pipe: pipe id 197 * 198 * SDIO uses credit based flow control at the HTC layer 199 * so transmit resource checks are bypassed 200 * Return: int 201 */ 202 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *hif_ctx, 203 uint8_t pipe) 204 { 205 uint16_t rv; 206 207 rv = 1; 208 return rv; 209 } 210 211 /** 212 * hif_send_complete_check() - check tx complete on a given pipe. 213 * @hif_ctx: HIF context 214 * @pipe: HIF target 215 * @force: check if need to pool for completion 216 * Decide whether to actually poll for completions, or just 217 * wait for a later chance. 218 * 219 * Return: int 220 */ 221 void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe, 222 int force) 223 { 224 225 } 226 227