xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
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