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