blob: 168b968c1eb60828b87d1996b301ff0ad5c72fbf [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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
24 @file wlan_qct_pal_device.c
25
26 @brief
27
28 This file implements the device specific HW access interface
29 required by the WLAN Platform Abstraction Layer (WPAL)
30
31 Copyright (c) 2011 QUALCOMM Incorporated.
32 All Rights Reserved.
33 Qualcomm Confidential and Proprietary
34========================================================================*/
35
36/*===========================================================================
37
38 EDIT HISTORY FOR FILE
39
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44
45 $Header:$ $DateTime: $ $Author: $
46
47
48 when who what, where, why
49 ---------- --- -----------------------------------------------------------
50 2011-03-01 jtj Initial version for Linux/Android with Wcnss
51
52===========================================================================*/
53
54/*----------------------------------------------------------------------------
55 * Include Files
56 * -------------------------------------------------------------------------*/
57#include <linux/irqreturn.h>
58#include <linux/interrupt.h>
59#include <linux/io.h>
60#include <mach/msm_smsm.h>
61#include "wlan_qct_pal_api.h"
62#include "wlan_qct_pal_device.h"
63#include "wlan_hdd_main.h"
64#include "linux/wcnss_wlan.h"
65
66/*----------------------------------------------------------------------------
67 * Preprocessor Definitions and Constants
68 * -------------------------------------------------------------------------*/
69
Jeff Johnsone7245742012-09-05 17:12:55 -070070// address in the Host physical memory map
71#ifdef WCN_PRONTO
72#define WCNSS_BASE_ADDRESS 0xFB000000
73#else
Jeff Johnson295189b2012-06-20 16:38:30 -070074#define WCNSS_BASE_ADDRESS 0x03000000
Jeff Johnsone7245742012-09-05 17:12:55 -070075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070076/*----------------------------------------------------------------------------
77 * Type Declarations
78 * -------------------------------------------------------------------------*/
79
80/*----------------------------------------------------------------------------
81 * Global Data Definitions
82 * -------------------------------------------------------------------------*/
83
84/*----------------------------------------------------------------------------
85 * Static Variable Definitions
86 * -------------------------------------------------------------------------*/
87
88static struct wcnss_env {
89 struct resource *wcnss_memory;
90 void __iomem *mmio;
91 int tx_irq;
92 wpalIsrType tx_isr;
93 void *tx_context;
94 int rx_irq;
95 wpalIsrType rx_isr;
96 void *rx_context;
97 int rx_registered;
98 int tx_registered;
99} *gpEnv = NULL;
100
101/*----------------------------------------------------------------------------
102 * Static Function Declarations and Definitions
103 * -------------------------------------------------------------------------*/
104
105/**
106 @brief wpalTxIsr is the interrupt service routine which handles
107 the DXE TX Complete interrupt
108
109 wpalTxIsr is registered with the Operating System to handle the
110 DXE TX Complete interrupt during system initialization. When a DXE
111 TX Complete interrupt occurs, it is dispatched to the handler which
112 had previously been registered via wpalRegisterInterrupt.
113
114 @param irq: Enumeration of the interrupt that occurred
115 @param dev_id: User-supplied data passed back via the ISR
116
117 @see wpalRegisterInterrupt
118
119 @return IRQ_HANDLED since it is a dedicated interrupt
120*/
121static irqreturn_t wpalTxIsr
122(
123 int irq,
124 void *dev_id
125)
126{
127 if ((NULL != gpEnv) && (NULL != gpEnv->tx_isr)) {
128 gpEnv->tx_isr(gpEnv->tx_context);
129 }
130 return IRQ_HANDLED;
131}
132
133
134/**
135 @brief wpalRxIsr is the interrupt service routine which handles
136 the DXE RX Available interrupt
137
138 wpalRxIsr is registered with the Operating System to handle the
139 DXE RX Available interrupt during system initalization. When a DXE
140 RX Available interrupt occurs, it is dispatched to the handler which
141 had previously been registered via wpalRegisterInterrupt.
142
143 @param irq: Enumeration of the interrupt that occurred
144 @param dev_id: User-supplied data passed back via the ISR
145
146 @see wpalRegisterInterrupt
147
148 @return IRQ_HANDLED since it is a dedicated interrupt
149*/
150static irqreturn_t wpalRxIsr
151(
152 int irq,
153 void *dev_id
154)
155{
156 if ((NULL != gpEnv) && (NULL != gpEnv->rx_isr)) {
157 gpEnv->rx_isr(gpEnv->rx_context);
158 }
159 return IRQ_HANDLED;
160}
161
162/*----------------------------------------------------------------------------
163 * Externalized Function Definitions
164 * -------------------------------------------------------------------------*/
165
166
167/**
168 @brief wpalRegisterInterrupt provides a mechansim for client
169 to register support for a given interrupt
170
171 The DXE interface supports two interrupts, TX Complete and RX
172 Available. This interface provides the mechanism whereby a client
173 can register to support one of these. It is expected that the core
174 DXE implementation will invoke this API twice, once for each interrupt.
175
176 @param intType: Enumeration of the interrupt type (TX or RX)
177 @param callbackFunction: ISR function pointer
178 @param usrCtxt: User context passed back whenever the
179 callbackFunction is invoked
180
181 @return SUCCESS if the registration was successful
182*/
183
184wpt_status wpalRegisterInterrupt
185(
186 wpt_uint32 intType,
187 wpalIsrType callbackFunction,
188 void *usrCtxt
189)
190{
191 if (NULL == gpEnv) {
192 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
193 "%s: invoked before subsystem initialized",
194 __FUNCTION__);
195 return eWLAN_PAL_STATUS_E_INVAL;
196 }
197
198 if (NULL == callbackFunction) {
199 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
200 "%s: invoked with NULL callback",
201 __FUNCTION__);
202 return eWLAN_PAL_STATUS_E_INVAL;
203 }
204
205 switch (intType) {
206
207 case DXE_INTERRUPT_TX_COMPLE:
208 if (NULL != gpEnv->tx_isr) {
209 /* TX complete handler already registered */
210 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
211 "%s: TX interrupt handler already registered",
212 __FUNCTION__);
213 /* fall though and accept the new values */
214 }
215 gpEnv->tx_isr = callbackFunction;
216 gpEnv->tx_context = usrCtxt;
217 break;
218
219 case DXE_INTERRUPT_RX_READY:
220 if (NULL != gpEnv->rx_isr) {
221 /* RX complete handler already registered */
222 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
223 "%s: RX interrupt handler already registered",
224 __FUNCTION__);
225 /* fall though and accept the new values */
226 }
227 gpEnv->rx_isr = callbackFunction;
228 gpEnv->rx_context = usrCtxt;
229 break;
230
231 default:
232 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
233 "%s: Unknown interrupt type [%u]",
234 __FUNCTION__, intType);
235 return eWLAN_PAL_STATUS_E_INVAL;
236 }
237
238 return eWLAN_PAL_STATUS_SUCCESS;
239}
240
241/**
242 @brief wpalUnRegisterInterrupt provides a mechansim for client
243 to un-register for a given interrupt
244
245 When DXE stop, remove registered information from PAL
246
247 @param intType: Enumeration of the interrupt type (TX or RX)
248
249 @return NONE
250*/
251
252void wpalUnRegisterInterrupt
253(
254 wpt_uint32 intType
255)
256{
257 if (NULL == gpEnv) {
258 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
259 "%s: invoked before subsystem initialized",
260 __FUNCTION__);
261 return;
262 }
263
264 switch (intType) {
265
266 case DXE_INTERRUPT_TX_COMPLE:
267 disable_irq_nosync(gpEnv->tx_irq);
268 if (gpEnv->tx_registered)
269 {
270 free_irq(gpEnv->tx_irq, gpEnv);
271 gpEnv->tx_registered = 0;
272 }
273 gpEnv->tx_isr = NULL;
274 gpEnv->tx_context = NULL;
275 break;
276
277 case DXE_INTERRUPT_RX_READY:
278 disable_irq_nosync(gpEnv->rx_irq);
279 if (gpEnv->rx_registered)
280 {
281 free_irq(gpEnv->rx_irq, gpEnv);
282 gpEnv->rx_registered = 0;
283 }
284 gpEnv->rx_isr = NULL;
285 gpEnv->rx_context = NULL;
286 break;
287
288 default:
289 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
290 "%s: Unknown interrupt type [%u]",
291 __FUNCTION__, intType);
292 return;
293 }
294
295 return;
296}
297
298/**
299 @brief wpalEnableInterrupt provides a mechansim for a client
300 to request that a given interrupt be enabled
301
302 The DXE interface supports two interrupts, TX Complete and RX
303 Available. This interface provides the mechanism whereby a client
304 can request that the platform-specific adaptation layer allows a
305 given interrupt to occur. The expectation is that if a given
306 interrupt is not enabled, if the interrupt occurs then the APPS CPU
307 will not be interrupted.
308
309 @param intType: Enumeration of the interrupt type (TX or RX)
310
311 @return SUCCESS if the interrupt was enabled
312*/
313wpt_status wpalEnableInterrupt
314(
315 wpt_uint32 intType
316)
317{
318 int ret;
319
320 switch (intType)
321 {
322 case DXE_INTERRUPT_RX_READY:
323 if (!gpEnv->rx_registered)
324 {
325 gpEnv->rx_registered = 1;
326 ret = request_irq(gpEnv->rx_irq, wpalRxIsr, IRQF_TRIGGER_HIGH,
327 "wcnss_wlan", gpEnv);
328 if (ret) {
329 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
330 "%s: RX IRQ request failure",
331 __FUNCTION__);
332 break;
333 }
334
335
336 ret = enable_irq_wake(gpEnv->rx_irq);
337 if (ret) {
338 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
339 "%s: enable_irq_wake failed for RX IRQ",
340 __FUNCTION__);
341 /* not fatal -- keep on going */
342 }
343 }
344 else
345 {
346 enable_irq(gpEnv->rx_irq);
347 }
348 break;
349 case DXE_INTERRUPT_TX_COMPLE:
350 if (!gpEnv->tx_registered)
351 {
352 gpEnv->tx_registered = 1;
353 ret = request_irq(gpEnv->tx_irq, wpalTxIsr, IRQF_TRIGGER_HIGH,
354 "wcnss_wlan", gpEnv);
355 if (ret) {
356 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
357 "%s: TX IRQ request failure",
358 __FUNCTION__);
359 break;
360 }
361
362
363 ret = enable_irq_wake(gpEnv->tx_irq);
364 if (ret) {
365 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
366 "%s: enable_irq_wake failed for TX IRQ",
367 __FUNCTION__);
368 /* not fatal -- keep on going */
369 }
370 }
371 else
372 {
373 enable_irq(gpEnv->tx_irq);
374 }
375 break;
376 default:
377 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
378 "%s: unknown interrupt: %d",
379 __FUNCTION__, (int)intType);
380 break;
381 }
382 /* on the integrated platform there is no platform-specific
383 interrupt control */
384 return eWLAN_PAL_STATUS_SUCCESS;
385}
386
387/**
388 @brief wpalDisableInterrupt provides a mechansim for a client
389 to request that a given interrupt be disabled
390
391 The DXE interface supports two interrupts, TX Complete and RX
392 Available. This interface provides the mechanism whereby a client
393 can request that the platform-specific adaptation layer not allow a
394 given interrupt to occur. The expectation is that if a given
395 interrupt is not enabled, if the interrupt occurs then the APPS CPU
396 will not be interrupted.
397
398 @param intType: Enumeration of the interrupt type (TX or RX)
399
400 @return SUCCESS if the interrupt was disabled
401*/
402wpt_status wpalDisableInterrupt
403(
404 wpt_uint32 intType
405)
406{
407 switch (intType)
408 {
409 case DXE_INTERRUPT_RX_READY:
410 disable_irq_nosync(gpEnv->rx_irq);
411 break;
412 case DXE_INTERRUPT_TX_COMPLE:
413 disable_irq_nosync(gpEnv->tx_irq);
414 break;
415 default:
416 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
417 "%s: unknown interrupt: %d",
418 __FUNCTION__, (int)intType);
419 break;
420 }
421
422 /* on the integrated platform there is no platform-specific
423 interrupt control */
424 return eWLAN_PAL_STATUS_SUCCESS;
425}
426
427/**
428 @brief wpalWriteRegister provides a mechansim for a client
429 to write data into a hardware data register
430
431 @param address: Physical memory address of the register
432 @param data: Data value to be written
433
434 @return SUCCESS if the data was successfully written
435*/
436wpt_status wpalWriteRegister
437(
438 wpt_uint32 address,
439 wpt_uint32 data
440)
441{
442 if (NULL == gpEnv) {
443 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
444 "%s: invoked before subsystem initialized",
445 __FUNCTION__);
446 return eWLAN_PAL_STATUS_E_INVAL;
447 }
448
449 if ((address < gpEnv->wcnss_memory->start) ||
450 (address > gpEnv->wcnss_memory->end)) {
451 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
452 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
453 __FUNCTION__, address,
454 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
455 return eWLAN_PAL_STATUS_E_INVAL;
456 }
457
458 if (0 != (address & 0x3)) {
459 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
460 "%s: Register address 0x%0x is not word aligned",
461 __FUNCTION__, address);
462 return eWLAN_PAL_STATUS_E_INVAL;
463 }
464
465 wmb();
466 writel_relaxed(data, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
467
468 return eWLAN_PAL_STATUS_SUCCESS;
469}
470
471/**
472 @brief wpalReadRegister provides a mechansim for a client
473 to read data from a hardware data register
474
475 @param address: Physical memory address of the register
476 @param data: Return location for value that is read
477
478 @return SUCCESS if the data was successfully read
479*/
480wpt_status wpalReadRegister
481(
482 wpt_uint32 address,
483 wpt_uint32 *data
484)
485{
486 if (NULL == gpEnv) {
487 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
488 "%s: invoked before subsystem initialized",
489 __FUNCTION__);
490 return eWLAN_PAL_STATUS_E_INVAL;
491 }
492
493 if ((address < gpEnv->wcnss_memory->start) ||
494 (address > gpEnv->wcnss_memory->end)) {
495 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
496 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
497 __FUNCTION__, address,
498 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
499 return eWLAN_PAL_STATUS_E_INVAL;
500 }
501
502 if (0 != (address & 0x3)) {
503 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
504 "%s: Register address 0x%0x is not word aligned",
505 __FUNCTION__, address);
506 return eWLAN_PAL_STATUS_E_INVAL;
507 }
508
509 *data = readl_relaxed(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
510 rmb();
511
512 return eWLAN_PAL_STATUS_SUCCESS;
513}
514
515/**
516 @brief wpalWriteDeviceMemory provides a mechansim for a client
517 to write data into the hardware address space
518
519 @param address: Start address of physical memory to be written
520 @param s_buffer: Virtual source address from which the data will
521 be read
522 @param len: Number of bytes of data to be written
523
524 @return SUCCESS if the data was successfully written
525*/
526wpt_status wpalWriteDeviceMemory
527(
528 wpt_uint32 address,
529 wpt_uint8* s_buffer,
530 wpt_uint32 len
531)
532{
533 if (NULL == gpEnv) {
534 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
535 "%s: invoked before subsystem initialized",
536 __FUNCTION__);
537 return eWLAN_PAL_STATUS_E_INVAL;
538 }
539
540 if ((address < gpEnv->wcnss_memory->start) ||
541 ((address + len) > gpEnv->wcnss_memory->end)) {
542 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
543 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
544 __FUNCTION__, address, len,
545 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
546 return eWLAN_PAL_STATUS_E_INVAL;
547 }
548
549 memcpy(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), s_buffer, len);
550 wmb();
551
552 return eWLAN_PAL_STATUS_SUCCESS;
553}
554
555/**
556 @brief wpalReadDeviceMemory provides a mechansim for a client
557 to read data from the hardware address space
558
559 @param address: Start address of physical memory to be read
560 @param d_buffer: Virtual destination address to which the
561 data will be written
562 @param len: Number of bytes of data to be read
563
564 @return SUCCESS if the data was successfully read
565*/
566wpt_status wpalReadDeviceMemory
567(
568 wpt_uint32 address,
569 wpt_uint8* d_buffer,
570 wpt_uint32 len
571)
572{
573 if (NULL == gpEnv) {
574 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
575 "%s: invoked before subsystem initialized",
576 __FUNCTION__);
577 return eWLAN_PAL_STATUS_E_INVAL;
578 }
579
580 if ((address < gpEnv->wcnss_memory->start) ||
581 ((address + len) > gpEnv->wcnss_memory->end)) {
582 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
583 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
584 __FUNCTION__, address, len,
585 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
586 return eWLAN_PAL_STATUS_E_INVAL;
587 }
588
589 memcpy(d_buffer, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), len);
590 rmb();
591
592 return eWLAN_PAL_STATUS_SUCCESS;
593}
594
595/**
596 @brief wpalDeviceInit provides a mechanism to initialize the DXE
597 platform adaptation
598
599 @param deviceCB: Implementation-specific device control block
600
601 @see wpalDeviceClose
602
603 @return SUCCESS if the DXE abstraction was opened
604*/
605wpt_status wpalDeviceInit
606(
607 void * deviceCB
608)
609{
610 hdd_context_t *pHddCtx = (hdd_context_t *)deviceCB;
611 struct device *wcnss_device = pHddCtx->parent_dev;
612 struct resource *wcnss_memory;
613 int tx_irq;
614 int rx_irq;
615
616 if (NULL != gpEnv) {
617 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
618 "%s: invoked after subsystem initialized",
619 __FUNCTION__);
620 return eWLAN_PAL_STATUS_E_INVAL;
621 }
622
623 if (NULL == wcnss_device) {
624 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
625 "%s: invalid device",
626 __FUNCTION__);
627 return eWLAN_PAL_STATUS_E_INVAL;
628 }
629
630 wcnss_memory = wcnss_wlan_get_memory_map(wcnss_device);
631 if (NULL == wcnss_memory) {
632 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
633 "%s: WCNSS memory map unavailable",
634 __FUNCTION__);
635 return eWLAN_PAL_STATUS_E_FAILURE;
636 }
637
638 tx_irq = wcnss_wlan_get_dxe_tx_irq(wcnss_device);
639 if (0 > tx_irq) {
640 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
641 "%s: WCNSS TX IRQ unavailable",
642 __FUNCTION__);
643 return eWLAN_PAL_STATUS_E_FAILURE;
644 }
645
646 rx_irq = wcnss_wlan_get_dxe_rx_irq(wcnss_device);
647 if (0 > rx_irq) {
648 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
649 "%s: WCNSS RX IRQ unavailable",
650 __FUNCTION__);
651 return eWLAN_PAL_STATUS_E_FAILURE;
652 }
653
654 gpEnv = wpalMemoryAllocate(sizeof(*gpEnv));
655 if (NULL == gpEnv) {
656 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
657 "%s: memory allocation failure",
658 __FUNCTION__);
659 return eWLAN_PAL_STATUS_E_NOMEM;
660 }
661
662 memset(gpEnv, 0, sizeof(*gpEnv));
663
664 gpEnv->wcnss_memory = wcnss_memory;
665 gpEnv->tx_irq = tx_irq;
666 gpEnv->rx_irq = rx_irq;
667
668 /* note the we don't invoke request_mem_region().
669 the memory described by wcnss_memory encompases the entire
670 register space (including BT and FM) and we do not want
671 exclusive access to that memory */
672
673 gpEnv->mmio = ioremap(wcnss_memory->start, resource_size(wcnss_memory));
674 if (NULL == gpEnv->mmio) {
675 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
676 "%s: memory remap failure",
677 __FUNCTION__);
678 goto err_ioremap;
679 }
680
681 gpEnv->tx_registered = 0;
682 gpEnv->rx_registered = 0;
683
684 /* successfully allocated environment, memory and IRQs */
685 return eWLAN_PAL_STATUS_SUCCESS;
686
687 err_ioremap:
688 wpalMemoryFree(gpEnv);
689 gpEnv = NULL;
690
691 return eWLAN_PAL_STATUS_E_FAILURE;
692
693}
694
695
696/**
697 @brief wpalDeviceClose provides a mechanism to deinitialize the DXE
698 platform adaptation
699
700 @param deviceCB: Implementation-specific device control block
701
702 @see wpalDeviceOpen
703
704 @return SUCCESS if the DXE abstraction was closed
705*/
706wpt_status wpalDeviceClose
707(
708 void * deviceCB
709 )
710{
711 if (NULL == gpEnv) {
712 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
713 "%s: invoked before subsystem initialized",
714 __FUNCTION__);
715 return eWLAN_PAL_STATUS_E_INVAL;
716 }
717
718 if (gpEnv->rx_registered)
719 {
720 free_irq(gpEnv->rx_irq, gpEnv);
721 }
722 if (gpEnv->tx_registered)
723 {
724 free_irq(gpEnv->tx_irq, gpEnv);
725 }
726 iounmap(gpEnv->mmio);
727 wpalMemoryFree(gpEnv);
728 gpEnv = NULL;
729
730 return eWLAN_PAL_STATUS_SUCCESS;
731}
732
733/**
734 @brief wpalNotifySmsm provides a mechansim for a client to
735 notify SMSM to start DXE engine and/or condition of Tx
736 ring buffer
737
738 @param clrSt: bit(s) to be cleared on the MASK
739 @param setSt: bit(s) to be set on the MASK
740
741 @return SUCCESS if the operation is successful
742*/
743wpt_status wpalNotifySmsm
744(
745 wpt_uint32 clrSt,
746 wpt_uint32 setSt
747)
748{
749 int rc;
750 rc = smsm_change_state(SMSM_APPS_STATE, clrSt, setSt);
751 if(0 != rc)
752 {
753 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
754 "%s: smsm_change_state failed",
755 __FUNCTION__);
756 return eWLAN_PAL_STATUS_E_FAILURE;
757 }
758 return eWLAN_PAL_STATUS_SUCCESS;
759}
760