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