blob: 4c2def66bb15fe9f4b0304abf8c5791829f7c3d8 [file] [log] [blame]
Houston Hoffman32bc8eb2016-03-14 21:11:34 -07001/*
2 * Copyright (c) 2016 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28
29/* this file dispatches functions to bus specific definitions */
30#include "hif_debug.h"
31#include "hif.h"
32#include "hif_main.h"
33#include "multibus.h"
Houston Hoffman162164c2016-03-14 21:12:10 -070034#include "ce_main.h"
Komal Seelam6ee55902016-04-11 17:11:07 +053035#include "htc_services.h"
36#include "a_types.h"
Houston Hoffman32bc8eb2016-03-14 21:11:34 -070037/**
38 * hif_intialize_default_ops() - intializes default operations values
39 *
40 * bus specific features should assign their dummy implementations here.
41 */
42static void hif_intialize_default_ops(struct hif_softc *hif_sc)
43{
44 struct hif_bus_ops *bus_ops = &hif_sc->bus_ops;
45
46 /* must be filled in by hif_bus_open */
47 bus_ops->hif_bus_close = NULL;
48
49 /* dummy implementations */
50}
51
52#define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *))
53
54/**
55 * hif_verify_basic_ops() - ensure required bus apis are defined
56 *
57 * all bus operations must be defined to avoid crashes
58 * itterate over the structure and ensure all function pointers
59 * are non null.
60 *
61 * Return: QDF_STATUS_SUCCESS if all the operations are defined
62 */
63static QDF_STATUS hif_verify_basic_ops(struct hif_softc *hif_sc)
64{
65 struct hif_bus_ops *bus_ops = &hif_sc->bus_ops;
66 void **ops_array = (void *)bus_ops;
67 QDF_STATUS status = QDF_STATUS_SUCCESS;
68 int i;
69
70 for (i = 0; i < NUM_OPS; i++) {
71 if (!ops_array[i]) {
72 HIF_ERROR("%s: function %d is null", __func__, i);
73 status = QDF_STATUS_E_NOSUPPORT;
74 }
75 }
76 return status;
77}
78
79/**
Houston Hoffman162164c2016-03-14 21:12:10 -070080 * hif_bus_get_context_size - API to return size of the bus specific structure
81 *
82 * Return: sizeof of hif_pci_softc
83 */
84int hif_bus_get_context_size(enum qdf_bus_type bus_type)
85{
86 switch (bus_type) {
87 case QDF_BUS_TYPE_PCI:
88 return hif_pci_get_context_size();
89 case QDF_BUS_TYPE_SNOC:
90 return hif_snoc_get_context_size();
91 default:
92 return 0;
93 }
94}
95
96/**
Houston Hoffman32bc8eb2016-03-14 21:11:34 -070097 * hif_bus_open() - initialize the bus_ops and call the bus specific open
98 * hif_sc: hif_context
99 * bus_type: type of bus being enumerated
100 *
101 * Return: QDF_STATUS_SUCCESS or error
102 */
103QDF_STATUS hif_bus_open(struct hif_softc *hif_sc,
104 enum qdf_bus_type bus_type)
105{
106 QDF_STATUS status = QDF_STATUS_E_INVAL;
107
108 hif_intialize_default_ops(hif_sc);
109
110 switch (bus_type) {
111 case QDF_BUS_TYPE_PCI:
Houston Hoffman54ef87d2016-03-14 21:11:58 -0700112 status = hif_initialize_pci_ops(hif_sc);
Houston Hoffman32bc8eb2016-03-14 21:11:34 -0700113 break;
114 case QDF_BUS_TYPE_SNOC:
115 status = hif_initialize_snoc_ops(&hif_sc->bus_ops);
116 break;
117 default:
118 status = QDF_STATUS_E_NOSUPPORT;
119 break;
120 }
121
122 if (status != QDF_STATUS_SUCCESS) {
123 HIF_ERROR("%s: %d not supported", __func__, bus_type);
124 return status;
125 }
126
127 status = hif_verify_basic_ops(hif_sc);
128 if (status != QDF_STATUS_SUCCESS)
129 return status;
130
131 return hif_sc->bus_ops.hif_bus_open(hif_sc, bus_type);
132}
133
134/**
135 * hif_bus_close() - close the bus
136 * @hif_sc: hif_context
137 */
138void hif_bus_close(struct hif_softc *hif_sc)
139{
140 hif_sc->bus_ops.hif_bus_close(hif_sc);
141}
Houston Hoffman4ca03b62016-03-14 21:11:51 -0700142
143/**
144 * hif_bus_prevent_linkdown() - prevent linkdown
145 * @hif_ctx: hif context
146 * @flag: true = keep bus alive false = let bus go to sleep
147 *
148 * Keeps the bus awake durring suspend.
149 */
150void hif_bus_prevent_linkdown(struct hif_softc *hif_sc, bool flag)
151{
152 hif_sc->bus_ops.hif_bus_prevent_linkdown(hif_sc, flag);
153}
154
155
156void hif_reset_soc(struct hif_opaque_softc *hif_ctx)
157{
158 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
159 hif_sc->bus_ops.hif_reset_soc(hif_sc);
160}
161
162int hif_bus_suspend(struct hif_opaque_softc *hif_ctx)
163{
164 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
165 return hif_sc->bus_ops.hif_bus_suspend(hif_sc);
166}
167
168int hif_bus_resume(struct hif_opaque_softc *hif_ctx)
169{
170 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
171 return hif_sc->bus_ops.hif_bus_resume(hif_sc);
172}
173
174int hif_target_sleep_state_adjust(struct hif_softc *hif_sc,
175 bool sleep_ok, bool wait_for_it)
176{
177 return hif_sc->bus_ops.hif_target_sleep_state_adjust(hif_sc,
178 sleep_ok, wait_for_it);
179}
Houston Hoffman8f239f62016-03-14 21:12:05 -0700180
181void hif_disable_isr(struct hif_opaque_softc *hif_hdl)
182{
183 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
184 hif_sc->bus_ops.hif_disable_isr(hif_sc);
185}
186
187void hif_nointrs(struct hif_softc *hif_sc)
188{
189 hif_sc->bus_ops.hif_nointrs(hif_sc);
190}
191
192QDF_STATUS hif_enable_bus(struct hif_softc *hif_sc, struct device *dev,
193 void *bdev, const hif_bus_id *bid,
194 enum hif_enable_type type)
195{
196 return hif_sc->bus_ops.hif_enable_bus(hif_sc, dev, bdev, bid, type);
197}
198
199void hif_disable_bus(struct hif_softc *hif_sc)
200{
201 hif_sc->bus_ops.hif_disable_bus(hif_sc);
202}
203
204int hif_bus_configure(struct hif_softc *hif_sc)
205{
206 return hif_sc->bus_ops.hif_bus_configure(hif_sc);
207}
208
209void hif_irq_enable(struct hif_softc *hif_sc, int irq_id)
210{
211 hif_sc->bus_ops.hif_irq_enable(hif_sc, irq_id);
212}
213
214void hif_irq_disable(struct hif_softc *hif_sc, int irq_id)
215{
216 hif_sc->bus_ops.hif_irq_disable(hif_sc, irq_id);
217}
Houston Hoffman3c017e72016-03-14 21:12:11 -0700218
219int hif_dump_registers(struct hif_opaque_softc *hif_hdl)
220{
221 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
222 return hif_sc->bus_ops.hif_dump_registers(hif_sc);
223}
Houston Hoffmanb4149dd2016-03-23 15:55:41 -0700224
225/**
226 * hif_enable_power_management() - enable power management after driver load
227 * @hif_hdl: opaque pointer to the hif context
228 * is_packet_log_enabled: true if packet log is enabled
229 *
230 * Driver load and firmware download are done in a high performance mode.
231 * Enable power management after the driver is loaded.
232 * packet log can require fewer power management features to be enabled.
233 */
234void hif_enable_power_management(struct hif_opaque_softc *hif_hdl,
235 bool is_packet_log_enabled)
236{
237 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
238 hif_sc->bus_ops.hif_enable_power_management(hif_sc,
239 is_packet_log_enabled);
240}
241
242/**
243 * hif_disable_power_management() - reset the bus power management
244 * @hif_hdl: opaque pointer to the hif context
245 *
246 * return the power management of the bus to its default state.
247 * This isn't necessarily a complete reversal of its counterpart.
248 * This should be called when unloading the driver.
249 */
250void hif_disable_power_management(struct hif_opaque_softc *hif_hdl)
251{
252 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
253 hif_sc->bus_ops.hif_disable_power_management(hif_sc);
254}
255