blob: eb0f43ab6c05e6f9ef89bc767b68b0bfb0f4a0cc [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, 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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**=========================================================================
43
44 @file wlan_qct_pal_device.c
45
46 @brief
47
48 This file implements the device specific HW access interface
49 required by the WLAN Platform Abstraction Layer (WPAL)
50
51 Copyright (c) 2011 QUALCOMM Incorporated.
52 All Rights Reserved.
53 Qualcomm Confidential and Proprietary
54========================================================================*/
55
56/*===========================================================================
57
58 EDIT HISTORY FOR FILE
59
60
61 This section contains comments describing changes made to the module.
62 Notice that changes are listed in reverse chronological order.
63
64
65 $Header:$ $DateTime: $ $Author: $
66
67
68 when who what, where, why
69 ---------- --- -----------------------------------------------------------
70 2011-03-01 jtj Initial version for Linux/Android with Wcnss
71
72===========================================================================*/
73
74/*----------------------------------------------------------------------------
75 * Include Files
76 * -------------------------------------------------------------------------*/
77#include <linux/irqreturn.h>
78#include <linux/interrupt.h>
79#include <linux/io.h>
80#include <mach/msm_smsm.h>
81#include "wlan_qct_pal_api.h"
82#include "wlan_qct_pal_device.h"
83#include "wlan_hdd_main.h"
84#include "linux/wcnss_wlan.h"
85
86/*----------------------------------------------------------------------------
87 * Preprocessor Definitions and Constants
88 * -------------------------------------------------------------------------*/
89
Jeff Johnsone7245742012-09-05 17:12:55 -070090// address in the Host physical memory map
91#ifdef WCN_PRONTO
92#define WCNSS_BASE_ADDRESS 0xFB000000
93#else
Jeff Johnson295189b2012-06-20 16:38:30 -070094#define WCNSS_BASE_ADDRESS 0x03000000
Jeff Johnsone7245742012-09-05 17:12:55 -070095#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070096/*----------------------------------------------------------------------------
97 * Type Declarations
98 * -------------------------------------------------------------------------*/
99
100/*----------------------------------------------------------------------------
101 * Global Data Definitions
102 * -------------------------------------------------------------------------*/
103
104/*----------------------------------------------------------------------------
105 * Static Variable Definitions
106 * -------------------------------------------------------------------------*/
107
Chang Leo1b94cec2012-12-17 13:13:05 -0800108typedef struct {
Jeff Johnson295189b2012-06-20 16:38:30 -0700109 struct resource *wcnss_memory;
110 void __iomem *mmio;
111 int tx_irq;
112 wpalIsrType tx_isr;
113 void *tx_context;
114 int rx_irq;
115 wpalIsrType rx_isr;
116 void *rx_context;
117 int rx_registered;
118 int tx_registered;
Chang Leo1b94cec2012-12-17 13:13:05 -0800119} wcnss_env;
120
121static wcnss_env gEnv;
122static wcnss_env *gpEnv = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700123
124/*----------------------------------------------------------------------------
125 * Static Function Declarations and Definitions
126 * -------------------------------------------------------------------------*/
127
128/**
129 @brief wpalTxIsr is the interrupt service routine which handles
130 the DXE TX Complete interrupt
131
132 wpalTxIsr is registered with the Operating System to handle the
133 DXE TX Complete interrupt during system initialization. When a DXE
134 TX Complete interrupt occurs, it is dispatched to the handler which
135 had previously been registered via wpalRegisterInterrupt.
136
137 @param irq: Enumeration of the interrupt that occurred
138 @param dev_id: User-supplied data passed back via the ISR
139
140 @see wpalRegisterInterrupt
141
142 @return IRQ_HANDLED since it is a dedicated interrupt
143*/
144static irqreturn_t wpalTxIsr
145(
146 int irq,
147 void *dev_id
148)
149{
150 if ((NULL != gpEnv) && (NULL != gpEnv->tx_isr)) {
151 gpEnv->tx_isr(gpEnv->tx_context);
152 }
153 return IRQ_HANDLED;
154}
155
156
157/**
158 @brief wpalRxIsr is the interrupt service routine which handles
159 the DXE RX Available interrupt
160
161 wpalRxIsr is registered with the Operating System to handle the
162 DXE RX Available interrupt during system initalization. When a DXE
163 RX Available interrupt occurs, it is dispatched to the handler which
164 had previously been registered via wpalRegisterInterrupt.
165
166 @param irq: Enumeration of the interrupt that occurred
167 @param dev_id: User-supplied data passed back via the ISR
168
169 @see wpalRegisterInterrupt
170
171 @return IRQ_HANDLED since it is a dedicated interrupt
172*/
173static irqreturn_t wpalRxIsr
174(
175 int irq,
176 void *dev_id
177)
178{
179 if ((NULL != gpEnv) && (NULL != gpEnv->rx_isr)) {
180 gpEnv->rx_isr(gpEnv->rx_context);
181 }
182 return IRQ_HANDLED;
183}
184
185/*----------------------------------------------------------------------------
186 * Externalized Function Definitions
187 * -------------------------------------------------------------------------*/
188
189
190/**
191 @brief wpalRegisterInterrupt provides a mechansim for client
192 to register support for a given interrupt
193
194 The DXE interface supports two interrupts, TX Complete and RX
195 Available. This interface provides the mechanism whereby a client
196 can register to support one of these. It is expected that the core
197 DXE implementation will invoke this API twice, once for each interrupt.
198
199 @param intType: Enumeration of the interrupt type (TX or RX)
200 @param callbackFunction: ISR function pointer
201 @param usrCtxt: User context passed back whenever the
202 callbackFunction is invoked
203
204 @return SUCCESS if the registration was successful
205*/
206
207wpt_status wpalRegisterInterrupt
208(
209 wpt_uint32 intType,
210 wpalIsrType callbackFunction,
211 void *usrCtxt
212)
213{
214 if (NULL == gpEnv) {
215 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
216 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700217 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700218 return eWLAN_PAL_STATUS_E_INVAL;
219 }
220
221 if (NULL == callbackFunction) {
222 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
223 "%s: invoked with NULL callback",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700224 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 return eWLAN_PAL_STATUS_E_INVAL;
226 }
227
228 switch (intType) {
229
230 case DXE_INTERRUPT_TX_COMPLE:
231 if (NULL != gpEnv->tx_isr) {
232 /* TX complete handler already registered */
233 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
234 "%s: TX interrupt handler already registered",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700235 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 /* fall though and accept the new values */
237 }
238 gpEnv->tx_isr = callbackFunction;
239 gpEnv->tx_context = usrCtxt;
240 break;
241
242 case DXE_INTERRUPT_RX_READY:
243 if (NULL != gpEnv->rx_isr) {
244 /* RX complete handler already registered */
245 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
246 "%s: RX interrupt handler already registered",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700247 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 /* fall though and accept the new values */
249 }
250 gpEnv->rx_isr = callbackFunction;
251 gpEnv->rx_context = usrCtxt;
252 break;
253
254 default:
255 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
256 "%s: Unknown interrupt type [%u]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700257 __func__, intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 return eWLAN_PAL_STATUS_E_INVAL;
259 }
260
261 return eWLAN_PAL_STATUS_SUCCESS;
262}
263
264/**
265 @brief wpalUnRegisterInterrupt provides a mechansim for client
266 to un-register for a given interrupt
267
268 When DXE stop, remove registered information from PAL
269
270 @param intType: Enumeration of the interrupt type (TX or RX)
271
272 @return NONE
273*/
274
275void wpalUnRegisterInterrupt
276(
277 wpt_uint32 intType
278)
279{
280 if (NULL == gpEnv) {
281 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
282 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 return;
285 }
286
287 switch (intType) {
288
289 case DXE_INTERRUPT_TX_COMPLE:
290 disable_irq_nosync(gpEnv->tx_irq);
291 if (gpEnv->tx_registered)
292 {
293 free_irq(gpEnv->tx_irq, gpEnv);
294 gpEnv->tx_registered = 0;
295 }
296 gpEnv->tx_isr = NULL;
297 gpEnv->tx_context = NULL;
298 break;
299
300 case DXE_INTERRUPT_RX_READY:
301 disable_irq_nosync(gpEnv->rx_irq);
302 if (gpEnv->rx_registered)
303 {
304 free_irq(gpEnv->rx_irq, gpEnv);
305 gpEnv->rx_registered = 0;
306 }
307 gpEnv->rx_isr = NULL;
308 gpEnv->rx_context = NULL;
309 break;
310
311 default:
312 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
313 "%s: Unknown interrupt type [%u]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700314 __func__, intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700315 return;
316 }
317
318 return;
319}
320
321/**
322 @brief wpalEnableInterrupt provides a mechansim for a client
323 to request that a given interrupt be enabled
324
325 The DXE interface supports two interrupts, TX Complete and RX
326 Available. This interface provides the mechanism whereby a client
327 can request that the platform-specific adaptation layer allows a
328 given interrupt to occur. The expectation is that if a given
329 interrupt is not enabled, if the interrupt occurs then the APPS CPU
330 will not be interrupted.
331
332 @param intType: Enumeration of the interrupt type (TX or RX)
333
334 @return SUCCESS if the interrupt was enabled
335*/
336wpt_status wpalEnableInterrupt
337(
338 wpt_uint32 intType
339)
340{
341 int ret;
342
343 switch (intType)
344 {
345 case DXE_INTERRUPT_RX_READY:
346 if (!gpEnv->rx_registered)
347 {
348 gpEnv->rx_registered = 1;
349 ret = request_irq(gpEnv->rx_irq, wpalRxIsr, IRQF_TRIGGER_HIGH,
350 "wcnss_wlan", gpEnv);
351 if (ret) {
352 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
353 "%s: RX IRQ request failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700354 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700355 break;
356 }
357
358
359 ret = enable_irq_wake(gpEnv->rx_irq);
360 if (ret) {
361 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
362 "%s: enable_irq_wake failed for RX IRQ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700363 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 /* not fatal -- keep on going */
365 }
366 }
367 else
368 {
369 enable_irq(gpEnv->rx_irq);
370 }
371 break;
372 case DXE_INTERRUPT_TX_COMPLE:
373 if (!gpEnv->tx_registered)
374 {
375 gpEnv->tx_registered = 1;
376 ret = request_irq(gpEnv->tx_irq, wpalTxIsr, IRQF_TRIGGER_HIGH,
377 "wcnss_wlan", gpEnv);
378 if (ret) {
379 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
380 "%s: TX IRQ request failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700381 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700382 break;
383 }
384
385
386 ret = enable_irq_wake(gpEnv->tx_irq);
387 if (ret) {
388 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
389 "%s: enable_irq_wake failed for TX IRQ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700390 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700391 /* not fatal -- keep on going */
392 }
393 }
394 else
395 {
396 enable_irq(gpEnv->tx_irq);
397 }
398 break;
399 default:
400 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
401 "%s: unknown interrupt: %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700402 __func__, (int)intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 break;
404 }
405 /* on the integrated platform there is no platform-specific
406 interrupt control */
407 return eWLAN_PAL_STATUS_SUCCESS;
408}
409
410/**
411 @brief wpalDisableInterrupt provides a mechansim for a client
412 to request that a given interrupt be disabled
413
414 The DXE interface supports two interrupts, TX Complete and RX
415 Available. This interface provides the mechanism whereby a client
416 can request that the platform-specific adaptation layer not allow a
417 given interrupt to occur. The expectation is that if a given
418 interrupt is not enabled, if the interrupt occurs then the APPS CPU
419 will not be interrupted.
420
421 @param intType: Enumeration of the interrupt type (TX or RX)
422
423 @return SUCCESS if the interrupt was disabled
424*/
425wpt_status wpalDisableInterrupt
426(
427 wpt_uint32 intType
428)
429{
430 switch (intType)
431 {
432 case DXE_INTERRUPT_RX_READY:
433 disable_irq_nosync(gpEnv->rx_irq);
434 break;
435 case DXE_INTERRUPT_TX_COMPLE:
436 disable_irq_nosync(gpEnv->tx_irq);
437 break;
438 default:
439 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
440 "%s: unknown interrupt: %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700441 __func__, (int)intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700442 break;
443 }
444
445 /* on the integrated platform there is no platform-specific
446 interrupt control */
447 return eWLAN_PAL_STATUS_SUCCESS;
448}
449
450/**
451 @brief wpalWriteRegister provides a mechansim for a client
452 to write data into a hardware data register
453
454 @param address: Physical memory address of the register
455 @param data: Data value to be written
456
457 @return SUCCESS if the data was successfully written
458*/
459wpt_status wpalWriteRegister
460(
461 wpt_uint32 address,
462 wpt_uint32 data
463)
464{
465 if (NULL == gpEnv) {
466 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
467 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700468 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700469 return eWLAN_PAL_STATUS_E_INVAL;
470 }
471
472 if ((address < gpEnv->wcnss_memory->start) ||
473 (address > gpEnv->wcnss_memory->end)) {
474 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
475 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700476 __func__, address,
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
478 return eWLAN_PAL_STATUS_E_INVAL;
479 }
480
481 if (0 != (address & 0x3)) {
482 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
483 "%s: Register address 0x%0x is not word aligned",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700484 __func__, address);
Jeff Johnson295189b2012-06-20 16:38:30 -0700485 return eWLAN_PAL_STATUS_E_INVAL;
486 }
487
488 wmb();
489 writel_relaxed(data, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
490
491 return eWLAN_PAL_STATUS_SUCCESS;
492}
493
494/**
495 @brief wpalReadRegister provides a mechansim for a client
496 to read data from a hardware data register
497
498 @param address: Physical memory address of the register
499 @param data: Return location for value that is read
500
501 @return SUCCESS if the data was successfully read
502*/
503wpt_status wpalReadRegister
504(
505 wpt_uint32 address,
506 wpt_uint32 *data
507)
508{
509 if (NULL == gpEnv) {
510 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
511 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700512 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700513 return eWLAN_PAL_STATUS_E_INVAL;
514 }
515
516 if ((address < gpEnv->wcnss_memory->start) ||
517 (address > gpEnv->wcnss_memory->end)) {
518 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
519 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700520 __func__, address,
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
522 return eWLAN_PAL_STATUS_E_INVAL;
523 }
524
525 if (0 != (address & 0x3)) {
526 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
527 "%s: Register address 0x%0x is not word aligned",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700528 __func__, address);
Jeff Johnson295189b2012-06-20 16:38:30 -0700529 return eWLAN_PAL_STATUS_E_INVAL;
530 }
531
532 *data = readl_relaxed(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
533 rmb();
534
535 return eWLAN_PAL_STATUS_SUCCESS;
536}
537
538/**
539 @brief wpalWriteDeviceMemory provides a mechansim for a client
540 to write data into the hardware address space
541
542 @param address: Start address of physical memory to be written
543 @param s_buffer: Virtual source address from which the data will
544 be read
545 @param len: Number of bytes of data to be written
546
547 @return SUCCESS if the data was successfully written
548*/
549wpt_status wpalWriteDeviceMemory
550(
551 wpt_uint32 address,
552 wpt_uint8* s_buffer,
553 wpt_uint32 len
554)
555{
556 if (NULL == gpEnv) {
557 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
558 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700559 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 return eWLAN_PAL_STATUS_E_INVAL;
561 }
562
563 if ((address < gpEnv->wcnss_memory->start) ||
564 ((address + len) > gpEnv->wcnss_memory->end)) {
565 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
566 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700567 __func__, address, len,
Jeff Johnson295189b2012-06-20 16:38:30 -0700568 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
569 return eWLAN_PAL_STATUS_E_INVAL;
570 }
571
572 memcpy(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), s_buffer, len);
573 wmb();
574
575 return eWLAN_PAL_STATUS_SUCCESS;
576}
577
578/**
579 @brief wpalReadDeviceMemory provides a mechansim for a client
580 to read data from the hardware address space
581
582 @param address: Start address of physical memory to be read
583 @param d_buffer: Virtual destination address to which the
584 data will be written
585 @param len: Number of bytes of data to be read
586
587 @return SUCCESS if the data was successfully read
588*/
589wpt_status wpalReadDeviceMemory
590(
591 wpt_uint32 address,
592 wpt_uint8* d_buffer,
593 wpt_uint32 len
594)
595{
596 if (NULL == gpEnv) {
597 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
598 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700599 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700600 return eWLAN_PAL_STATUS_E_INVAL;
601 }
602
603 if ((address < gpEnv->wcnss_memory->start) ||
604 ((address + len) > gpEnv->wcnss_memory->end)) {
605 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
606 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700607 __func__, address, len,
Jeff Johnson295189b2012-06-20 16:38:30 -0700608 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
609 return eWLAN_PAL_STATUS_E_INVAL;
610 }
611
612 memcpy(d_buffer, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), len);
613 rmb();
614
615 return eWLAN_PAL_STATUS_SUCCESS;
616}
617
618/**
619 @brief wpalDeviceInit provides a mechanism to initialize the DXE
620 platform adaptation
621
622 @param deviceCB: Implementation-specific device control block
623
624 @see wpalDeviceClose
625
626 @return SUCCESS if the DXE abstraction was opened
627*/
628wpt_status wpalDeviceInit
629(
630 void * deviceCB
631)
632{
633 hdd_context_t *pHddCtx = (hdd_context_t *)deviceCB;
634 struct device *wcnss_device = pHddCtx->parent_dev;
635 struct resource *wcnss_memory;
636 int tx_irq;
637 int rx_irq;
638
639 if (NULL != gpEnv) {
640 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
641 "%s: invoked after subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700642 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700643 return eWLAN_PAL_STATUS_E_INVAL;
644 }
645
646 if (NULL == wcnss_device) {
647 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
648 "%s: invalid device",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700649 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700650 return eWLAN_PAL_STATUS_E_INVAL;
651 }
652
653 wcnss_memory = wcnss_wlan_get_memory_map(wcnss_device);
654 if (NULL == wcnss_memory) {
655 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
656 "%s: WCNSS memory map unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700657 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700658 return eWLAN_PAL_STATUS_E_FAILURE;
659 }
660
661 tx_irq = wcnss_wlan_get_dxe_tx_irq(wcnss_device);
662 if (0 > tx_irq) {
663 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
664 "%s: WCNSS TX IRQ unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700665 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700666 return eWLAN_PAL_STATUS_E_FAILURE;
667 }
668
669 rx_irq = wcnss_wlan_get_dxe_rx_irq(wcnss_device);
670 if (0 > rx_irq) {
671 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
672 "%s: WCNSS RX IRQ unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700673 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700674 return eWLAN_PAL_STATUS_E_FAILURE;
675 }
676
Chang Leo1b94cec2012-12-17 13:13:05 -0800677 gpEnv = &gEnv;
Jeff Johnson295189b2012-06-20 16:38:30 -0700678 if (NULL == gpEnv) {
679 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
680 "%s: memory allocation failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700681 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700682 return eWLAN_PAL_STATUS_E_NOMEM;
683 }
684
685 memset(gpEnv, 0, sizeof(*gpEnv));
686
687 gpEnv->wcnss_memory = wcnss_memory;
688 gpEnv->tx_irq = tx_irq;
689 gpEnv->rx_irq = rx_irq;
690
691 /* note the we don't invoke request_mem_region().
692 the memory described by wcnss_memory encompases the entire
693 register space (including BT and FM) and we do not want
694 exclusive access to that memory */
695
696 gpEnv->mmio = ioremap(wcnss_memory->start, resource_size(wcnss_memory));
697 if (NULL == gpEnv->mmio) {
698 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
699 "%s: memory remap failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700700 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700701 goto err_ioremap;
702 }
703
704 gpEnv->tx_registered = 0;
705 gpEnv->rx_registered = 0;
706
707 /* successfully allocated environment, memory and IRQs */
708 return eWLAN_PAL_STATUS_SUCCESS;
709
710 err_ioremap:
Jeff Johnson295189b2012-06-20 16:38:30 -0700711 gpEnv = NULL;
712
713 return eWLAN_PAL_STATUS_E_FAILURE;
714
715}
716
717
718/**
719 @brief wpalDeviceClose provides a mechanism to deinitialize the DXE
720 platform adaptation
721
722 @param deviceCB: Implementation-specific device control block
723
724 @see wpalDeviceOpen
725
726 @return SUCCESS if the DXE abstraction was closed
727*/
728wpt_status wpalDeviceClose
729(
730 void * deviceCB
731 )
732{
733 if (NULL == gpEnv) {
734 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
735 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700736 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700737 return eWLAN_PAL_STATUS_E_INVAL;
738 }
739
740 if (gpEnv->rx_registered)
741 {
742 free_irq(gpEnv->rx_irq, gpEnv);
743 }
744 if (gpEnv->tx_registered)
745 {
746 free_irq(gpEnv->tx_irq, gpEnv);
747 }
748 iounmap(gpEnv->mmio);
Jeff Johnson295189b2012-06-20 16:38:30 -0700749 gpEnv = NULL;
750
751 return eWLAN_PAL_STATUS_SUCCESS;
752}
753
754/**
755 @brief wpalNotifySmsm provides a mechansim for a client to
756 notify SMSM to start DXE engine and/or condition of Tx
757 ring buffer
758
759 @param clrSt: bit(s) to be cleared on the MASK
760 @param setSt: bit(s) to be set on the MASK
761
762 @return SUCCESS if the operation is successful
763*/
764wpt_status wpalNotifySmsm
765(
766 wpt_uint32 clrSt,
767 wpt_uint32 setSt
768)
769{
770 int rc;
771 rc = smsm_change_state(SMSM_APPS_STATE, clrSt, setSt);
772 if(0 != rc)
773 {
774 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
775 "%s: smsm_change_state failed",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700776 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 return eWLAN_PAL_STATUS_E_FAILURE;
778 }
779 return eWLAN_PAL_STATUS_SUCCESS;
780}
781