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