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 #ifndef EXPORT_SYMTAB 21 #define EXPORT_SYMTAB 22 #endif 23 24 #include <osdep.h> 25 #include <linux/slab.h> 26 #include <linux/interrupt.h> 27 #include <linux/if_arp.h> 28 #include <linux/mmc/card.h> 29 #include <linux/mmc/mmc.h> 30 #include <linux/mmc/host.h> 31 #include <linux/mmc/sdio_func.h> 32 #include <linux/mmc/sdio_ids.h> 33 #include <linux/mmc/sdio.h> 34 #include <linux/mmc/sd.h> 35 #include <linux/wait.h> 36 #include <qdf_mem.h> 37 #include "if_sdio.h" 38 #include <qdf_trace.h> 39 #include <cds_api.h> 40 #include "regtable_sdio.h" 41 #include <hif_debug.h> 42 #include "target_type.h" 43 #include "epping_main.h" 44 #include "targaddrs.h" 45 #include "sdio_api.h" 46 #include <hif_sdio_dev.h> 47 #ifndef REMOVE_PKT_LOG 48 #include "ol_txrx_types.h" 49 #include "pktlog_ac_api.h" 50 #include "pktlog_ac.h" 51 #endif 52 #ifndef ATH_BUS_PM 53 #ifdef CONFIG_PM 54 #define ATH_BUS_PM 55 #endif /* CONFIG_PM */ 56 #endif /* ATH_BUS_PM */ 57 58 #ifndef REMOVE_PKT_LOG 59 struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs; 60 #endif 61 #define HIF_SDIO_LOAD_TIMEOUT 1000 62 63 /** 64 * hif_sdio_bus_suspend() - suspend the bus 65 * @hif_ctx: hif context 66 * 67 * This function suspends the bus, but sdio doesn't need to suspend. 68 * Therefore do nothing. 69 * 70 * Return: 0 for success and non-zero for failure 71 */ 72 int hif_sdio_bus_suspend(struct hif_softc *hif_ctx) 73 { 74 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 75 struct hif_sdio_dev *hif_device = scn->hif_handle; 76 struct device *dev = &hif_device->func->dev; 77 78 return hif_device_suspend(hif_ctx, dev); 79 } 80 81 82 /** 83 * hif_sdio_bus_resume() - hif resume API 84 * @hif_ctx: hif context 85 * 86 * This function resumes the bus. but sdio doesn't need to resume. 87 * Therefore do nothing. 88 * 89 * Return: 0 for success and non-zero for failure 90 */ 91 int hif_sdio_bus_resume(struct hif_softc *hif_ctx) 92 { 93 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 94 struct hif_sdio_dev *hif_device = scn->hif_handle; 95 struct device *dev = &hif_device->func->dev; 96 97 hif_device_resume(hif_ctx, dev); 98 return 0; 99 } 100 101 /** 102 * hif_enable_power_gating() - enable HW power gating 103 * @hif_ctx: hif context 104 * 105 * Return: n/a 106 */ 107 void hif_enable_power_gating(void *hif_ctx) 108 { 109 } 110 111 /** 112 * hif_sdio_close() - hif_bus_close 113 * @hif_sc: hif context 114 * 115 * Return: None 116 */ 117 void hif_sdio_close(struct hif_softc *hif_sc) 118 { 119 } 120 121 /** 122 * hif_sdio_open() - hif_bus_open 123 * @hif_sc: hif context 124 * @bus_type: bus type 125 * 126 * Return: QDF status 127 */ 128 QDF_STATUS hif_sdio_open(struct hif_softc *hif_sc, 129 enum qdf_bus_type bus_type) 130 { 131 hif_sc->bus_type = bus_type; 132 133 return QDF_STATUS_SUCCESS; 134 } 135 136 void hif_get_target_revision(struct hif_softc *ol_sc) 137 { 138 struct hif_softc *ol_sc_local = (struct hif_softc *)ol_sc; 139 struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc_local); 140 uint32_t chip_id = 0; 141 QDF_STATUS rv; 142 143 rv = hif_diag_read_access(hif_hdl, 144 (CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS), &chip_id); 145 if (rv != QDF_STATUS_SUCCESS) { 146 hif_err("get chip id fail"); 147 } else { 148 ol_sc_local->target_info.target_revision = 149 CHIP_ID_REVISION_GET(chip_id); 150 } 151 } 152 153 /** 154 * hif_sdio_enable_bus() - hif_enable_bus 155 * @ol_sc: hif context 156 * @dev: dev 157 * @bdev: bus dev 158 * @bid: bus id 159 * @type: bus type 160 * 161 * Return: QDF_STATUS 162 */ 163 QDF_STATUS hif_sdio_enable_bus(struct hif_softc *ol_sc, struct device *dev, 164 void *bdev, const struct hif_bus_id *bid, 165 enum hif_enable_type type) 166 { 167 const struct sdio_device_id *id = (const struct sdio_device_id *)bid; 168 169 if (hif_sdio_device_inserted(ol_sc, dev, id)) { 170 hif_err("hif_sdio_device_inserted failed"); 171 return QDF_STATUS_E_NOMEM; 172 } 173 174 return QDF_STATUS_SUCCESS; 175 } 176 177 178 /** 179 * hif_sdio_disable_bus() - sdio disable bus 180 * @hif_sc: hif softc pointer 181 * 182 * Return: none 183 */ 184 void hif_sdio_disable_bus(struct hif_softc *hif_sc) 185 { 186 struct sdio_func *func = dev_to_sdio_func(hif_sc->qdf_dev->dev); 187 188 hif_sdio_device_removed(hif_sc, func); 189 } 190 191 /** 192 * hif_sdio_get_config_item - sdio configure bus 193 * @hif_sc: hif context 194 * @opcode: configuration type 195 * @config: configuration value to set 196 * @config_len: configuration length 197 * 198 * Return: QDF_STATUS_SUCCESS for success 199 */ 200 QDF_STATUS hif_sdio_get_config_item(struct hif_softc *hif_sc, 201 int opcode, void *config, uint32_t config_len) 202 { 203 struct hif_sdio_softc *sc = HIF_GET_SDIO_SOFTC(hif_sc); 204 struct hif_sdio_dev *hif_device = sc->hif_handle; 205 206 return hif_configure_device(hif_sc, hif_device, opcode, 207 config, config_len); 208 } 209 210 /** 211 * hif_sdio_set_mailbox_swap - set mailbox swap 212 * @hif_sc: hif context 213 * 214 * Return: None 215 */ 216 void hif_sdio_set_mailbox_swap(struct hif_softc *hif_sc) 217 { 218 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_sc); 219 struct hif_sdio_dev *hif_device = scn->hif_handle; 220 221 hif_dev_set_mailbox_swap(hif_device); 222 } 223 224 /** 225 * hif_sdio_claim_device - set mailbox swap 226 * @hif_sc: hif context 227 * 228 * Return: None 229 */ 230 void hif_sdio_claim_device(struct hif_softc *hif_sc) 231 { 232 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_sc); 233 struct hif_sdio_dev *hif_device = scn->hif_handle; 234 235 hif_device->claimed_ctx = hif_sc; 236 } 237 238 /** 239 * hif_sdio_mask_interrupt_call() - disable hif device irq 240 * @scn: pointr to softc structure 241 * 242 * Return: None 243 */ 244 void hif_sdio_mask_interrupt_call(struct hif_softc *scn) 245 { 246 struct hif_sdio_softc *hif_ctx = HIF_GET_SDIO_SOFTC(scn); 247 struct hif_sdio_dev *hif_device = hif_ctx->hif_handle; 248 249 hif_mask_interrupt(hif_device); 250 } 251 252 /** 253 * hif_trigger_dump() - trigger various dump cmd 254 * @scn: struct hif_opaque_softc 255 * @cmd_id: dump command id 256 * @start: start/stop dump 257 * 258 * Return: None 259 */ 260 void hif_trigger_dump(struct hif_opaque_softc *scn, uint8_t cmd_id, bool start) 261 { 262 } 263 264 /** 265 * hif_check_fw_reg() - check fw selfrecovery indication 266 * @hif_ctx: hif_opaque_softc 267 * 268 * Return: int 269 */ 270 int hif_check_fw_reg(struct hif_opaque_softc *hif_ctx) 271 { 272 int ret = 1; 273 uint32_t fw_indication = 0; 274 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 275 276 if (hif_diag_read_access(hif_ctx, FW_INDICATOR_ADDRESS, 277 &fw_indication) != QDF_STATUS_SUCCESS) { 278 hif_err("Get fw indication failed"); 279 return 1; 280 } 281 hif_info("fw indication is 0x%x def 0x%x", 282 fw_indication, FW_IND_HELPER); 283 if (fw_indication & FW_IND_HELPER) 284 ret = 0; 285 286 return ret; 287 } 288 289 /** 290 * hif_wlan_disable() - call the platform driver to disable wlan 291 * @scn: scn 292 * 293 * Return: void 294 */ 295 void hif_wlan_disable(struct hif_softc *scn) 296 { 297 } 298 299 /** 300 * hif_sdio_needs_bmi() - return true if the soc needs bmi through the driver 301 * @scn: hif context 302 * 303 * Return: true if soc needs driver bmi otherwise false 304 */ 305 bool hif_sdio_needs_bmi(struct hif_softc *scn) 306 { 307 return true; 308 } 309