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