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 */
hif_sdio_bus_suspend(struct hif_softc * hif_ctx)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 */
hif_sdio_bus_resume(struct hif_softc * hif_ctx)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 */
hif_enable_power_gating(void * hif_ctx)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 */
hif_sdio_close(struct hif_softc * hif_sc)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 */
hif_sdio_open(struct hif_softc * hif_sc,enum qdf_bus_type bus_type)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
hif_get_target_revision(struct hif_softc * ol_sc)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 */
hif_sdio_enable_bus(struct hif_softc * ol_sc,struct device * dev,void * bdev,const struct hif_bus_id * bid,enum hif_enable_type type)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 */
hif_sdio_disable_bus(struct hif_softc * hif_sc)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 */
hif_sdio_get_config_item(struct hif_softc * hif_sc,int opcode,void * config,uint32_t config_len)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 */
hif_sdio_set_mailbox_swap(struct hif_softc * hif_sc)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 */
hif_sdio_claim_device(struct hif_softc * hif_sc)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 */
hif_sdio_mask_interrupt_call(struct hif_softc * scn)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 */
hif_trigger_dump(struct hif_opaque_softc * scn,uint8_t cmd_id,bool start)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 */
hif_check_fw_reg(struct hif_opaque_softc * hif_ctx)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 */
hif_wlan_disable(struct hif_softc * scn)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 */
hif_sdio_needs_bmi(struct hif_softc * scn)305 bool hif_sdio_needs_bmi(struct hif_softc *scn)
306 {
307 return true;
308 }
309