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 #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_ERROR("%s[%d]: get chip id fail\n", __func__, __LINE__); 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 int ret = 0; 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_ERROR("wlan: %s hif_sdio_device_inserted failed", __func__); 167 return QDF_STATUS_E_NOMEM; 168 } 169 170 return ret; 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() - disbale 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_ERROR("%s Get fw indication failed\n", __func__); 275 return 1; 276 } 277 HIF_INFO("%s: fw indication is 0x%x def 0x%x.\n", __func__, 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