blob: 5b97b4f6953bc3c751129c3f40fe7801630b63de [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
108static struct wcnss_env {
109 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;
119} *gpEnv = NULL;
120
121/*----------------------------------------------------------------------------
122 * Static Function Declarations and Definitions
123 * -------------------------------------------------------------------------*/
124
125/**
126 @brief wpalTxIsr is the interrupt service routine which handles
127 the DXE TX Complete interrupt
128
129 wpalTxIsr is registered with the Operating System to handle the
130 DXE TX Complete interrupt during system initialization. When a DXE
131 TX Complete interrupt occurs, it is dispatched to the handler which
132 had previously been registered via wpalRegisterInterrupt.
133
134 @param irq: Enumeration of the interrupt that occurred
135 @param dev_id: User-supplied data passed back via the ISR
136
137 @see wpalRegisterInterrupt
138
139 @return IRQ_HANDLED since it is a dedicated interrupt
140*/
141static irqreturn_t wpalTxIsr
142(
143 int irq,
144 void *dev_id
145)
146{
147 if ((NULL != gpEnv) && (NULL != gpEnv->tx_isr)) {
148 gpEnv->tx_isr(gpEnv->tx_context);
149 }
150 return IRQ_HANDLED;
151}
152
153
154/**
155 @brief wpalRxIsr is the interrupt service routine which handles
156 the DXE RX Available interrupt
157
158 wpalRxIsr is registered with the Operating System to handle the
159 DXE RX Available interrupt during system initalization. When a DXE
160 RX Available interrupt occurs, it is dispatched to the handler which
161 had previously been registered via wpalRegisterInterrupt.
162
163 @param irq: Enumeration of the interrupt that occurred
164 @param dev_id: User-supplied data passed back via the ISR
165
166 @see wpalRegisterInterrupt
167
168 @return IRQ_HANDLED since it is a dedicated interrupt
169*/
170static irqreturn_t wpalRxIsr
171(
172 int irq,
173 void *dev_id
174)
175{
176 if ((NULL != gpEnv) && (NULL != gpEnv->rx_isr)) {
177 gpEnv->rx_isr(gpEnv->rx_context);
178 }
179 return IRQ_HANDLED;
180}
181
182/*----------------------------------------------------------------------------
183 * Externalized Function Definitions
184 * -------------------------------------------------------------------------*/
185
186
187/**
188 @brief wpalRegisterInterrupt provides a mechansim for client
189 to register support for a given interrupt
190
191 The DXE interface supports two interrupts, TX Complete and RX
192 Available. This interface provides the mechanism whereby a client
193 can register to support one of these. It is expected that the core
194 DXE implementation will invoke this API twice, once for each interrupt.
195
196 @param intType: Enumeration of the interrupt type (TX or RX)
197 @param callbackFunction: ISR function pointer
198 @param usrCtxt: User context passed back whenever the
199 callbackFunction is invoked
200
201 @return SUCCESS if the registration was successful
202*/
203
204wpt_status wpalRegisterInterrupt
205(
206 wpt_uint32 intType,
207 wpalIsrType callbackFunction,
208 void *usrCtxt
209)
210{
211 if (NULL == gpEnv) {
212 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
213 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700214 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 return eWLAN_PAL_STATUS_E_INVAL;
216 }
217
218 if (NULL == callbackFunction) {
219 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
220 "%s: invoked with NULL callback",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700221 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 return eWLAN_PAL_STATUS_E_INVAL;
223 }
224
225 switch (intType) {
226
227 case DXE_INTERRUPT_TX_COMPLE:
228 if (NULL != gpEnv->tx_isr) {
229 /* TX complete handler already registered */
230 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
231 "%s: TX interrupt handler already registered",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700232 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 /* fall though and accept the new values */
234 }
235 gpEnv->tx_isr = callbackFunction;
236 gpEnv->tx_context = usrCtxt;
237 break;
238
239 case DXE_INTERRUPT_RX_READY:
240 if (NULL != gpEnv->rx_isr) {
241 /* RX complete handler already registered */
242 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN,
243 "%s: RX interrupt handler already registered",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700244 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 /* fall though and accept the new values */
246 }
247 gpEnv->rx_isr = callbackFunction;
248 gpEnv->rx_context = usrCtxt;
249 break;
250
251 default:
252 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
253 "%s: Unknown interrupt type [%u]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700254 __func__, intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 return eWLAN_PAL_STATUS_E_INVAL;
256 }
257
258 return eWLAN_PAL_STATUS_SUCCESS;
259}
260
261/**
262 @brief wpalUnRegisterInterrupt provides a mechansim for client
263 to un-register for a given interrupt
264
265 When DXE stop, remove registered information from PAL
266
267 @param intType: Enumeration of the interrupt type (TX or RX)
268
269 @return NONE
270*/
271
272void wpalUnRegisterInterrupt
273(
274 wpt_uint32 intType
275)
276{
277 if (NULL == gpEnv) {
278 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
279 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700280 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 return;
282 }
283
284 switch (intType) {
285
286 case DXE_INTERRUPT_TX_COMPLE:
287 disable_irq_nosync(gpEnv->tx_irq);
288 if (gpEnv->tx_registered)
289 {
290 free_irq(gpEnv->tx_irq, gpEnv);
291 gpEnv->tx_registered = 0;
292 }
293 gpEnv->tx_isr = NULL;
294 gpEnv->tx_context = NULL;
295 break;
296
297 case DXE_INTERRUPT_RX_READY:
298 disable_irq_nosync(gpEnv->rx_irq);
299 if (gpEnv->rx_registered)
300 {
301 free_irq(gpEnv->rx_irq, gpEnv);
302 gpEnv->rx_registered = 0;
303 }
304 gpEnv->rx_isr = NULL;
305 gpEnv->rx_context = NULL;
306 break;
307
308 default:
309 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
310 "%s: Unknown interrupt type [%u]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700311 __func__, intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 return;
313 }
314
315 return;
316}
317
318/**
319 @brief wpalEnableInterrupt provides a mechansim for a client
320 to request that a given interrupt be enabled
321
322 The DXE interface supports two interrupts, TX Complete and RX
323 Available. This interface provides the mechanism whereby a client
324 can request that the platform-specific adaptation layer allows a
325 given interrupt to occur. The expectation is that if a given
326 interrupt is not enabled, if the interrupt occurs then the APPS CPU
327 will not be interrupted.
328
329 @param intType: Enumeration of the interrupt type (TX or RX)
330
331 @return SUCCESS if the interrupt was enabled
332*/
333wpt_status wpalEnableInterrupt
334(
335 wpt_uint32 intType
336)
337{
338 int ret;
339
340 switch (intType)
341 {
342 case DXE_INTERRUPT_RX_READY:
343 if (!gpEnv->rx_registered)
344 {
345 gpEnv->rx_registered = 1;
346 ret = request_irq(gpEnv->rx_irq, wpalRxIsr, IRQF_TRIGGER_HIGH,
347 "wcnss_wlan", gpEnv);
348 if (ret) {
349 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
350 "%s: RX IRQ request failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700351 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700352 break;
353 }
354
355
356 ret = enable_irq_wake(gpEnv->rx_irq);
357 if (ret) {
358 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
359 "%s: enable_irq_wake failed for RX IRQ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700360 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361 /* not fatal -- keep on going */
362 }
363 }
364 else
365 {
366 enable_irq(gpEnv->rx_irq);
367 }
368 break;
369 case DXE_INTERRUPT_TX_COMPLE:
370 if (!gpEnv->tx_registered)
371 {
372 gpEnv->tx_registered = 1;
373 ret = request_irq(gpEnv->tx_irq, wpalTxIsr, IRQF_TRIGGER_HIGH,
374 "wcnss_wlan", gpEnv);
375 if (ret) {
376 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
377 "%s: TX IRQ request failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700378 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700379 break;
380 }
381
382
383 ret = enable_irq_wake(gpEnv->tx_irq);
384 if (ret) {
385 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
386 "%s: enable_irq_wake failed for TX IRQ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700387 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700388 /* not fatal -- keep on going */
389 }
390 }
391 else
392 {
393 enable_irq(gpEnv->tx_irq);
394 }
395 break;
396 default:
397 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
398 "%s: unknown interrupt: %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700399 __func__, (int)intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700400 break;
401 }
402 /* on the integrated platform there is no platform-specific
403 interrupt control */
404 return eWLAN_PAL_STATUS_SUCCESS;
405}
406
407/**
408 @brief wpalDisableInterrupt provides a mechansim for a client
409 to request that a given interrupt be disabled
410
411 The DXE interface supports two interrupts, TX Complete and RX
412 Available. This interface provides the mechanism whereby a client
413 can request that the platform-specific adaptation layer not allow a
414 given interrupt to occur. The expectation is that if a given
415 interrupt is not enabled, if the interrupt occurs then the APPS CPU
416 will not be interrupted.
417
418 @param intType: Enumeration of the interrupt type (TX or RX)
419
420 @return SUCCESS if the interrupt was disabled
421*/
422wpt_status wpalDisableInterrupt
423(
424 wpt_uint32 intType
425)
426{
427 switch (intType)
428 {
429 case DXE_INTERRUPT_RX_READY:
430 disable_irq_nosync(gpEnv->rx_irq);
431 break;
432 case DXE_INTERRUPT_TX_COMPLE:
433 disable_irq_nosync(gpEnv->tx_irq);
434 break;
435 default:
436 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
437 "%s: unknown interrupt: %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700438 __func__, (int)intType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700439 break;
440 }
441
442 /* on the integrated platform there is no platform-specific
443 interrupt control */
444 return eWLAN_PAL_STATUS_SUCCESS;
445}
446
447/**
448 @brief wpalWriteRegister provides a mechansim for a client
449 to write data into a hardware data register
450
451 @param address: Physical memory address of the register
452 @param data: Data value to be written
453
454 @return SUCCESS if the data was successfully written
455*/
456wpt_status wpalWriteRegister
457(
458 wpt_uint32 address,
459 wpt_uint32 data
460)
461{
462 if (NULL == gpEnv) {
463 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
464 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700465 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 return eWLAN_PAL_STATUS_E_INVAL;
467 }
468
469 if ((address < gpEnv->wcnss_memory->start) ||
470 (address > gpEnv->wcnss_memory->end)) {
471 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
472 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700473 __func__, address,
Jeff Johnson295189b2012-06-20 16:38:30 -0700474 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
475 return eWLAN_PAL_STATUS_E_INVAL;
476 }
477
478 if (0 != (address & 0x3)) {
479 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
480 "%s: Register address 0x%0x is not word aligned",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700481 __func__, address);
Jeff Johnson295189b2012-06-20 16:38:30 -0700482 return eWLAN_PAL_STATUS_E_INVAL;
483 }
484
485 wmb();
486 writel_relaxed(data, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
487
488 return eWLAN_PAL_STATUS_SUCCESS;
489}
490
491/**
492 @brief wpalReadRegister provides a mechansim for a client
493 to read data from a hardware data register
494
495 @param address: Physical memory address of the register
496 @param data: Return location for value that is read
497
498 @return SUCCESS if the data was successfully read
499*/
500wpt_status wpalReadRegister
501(
502 wpt_uint32 address,
503 wpt_uint32 *data
504)
505{
506 if (NULL == gpEnv) {
507 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
508 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700509 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 return eWLAN_PAL_STATUS_E_INVAL;
511 }
512
513 if ((address < gpEnv->wcnss_memory->start) ||
514 (address > gpEnv->wcnss_memory->end)) {
515 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
516 "%s: Register address 0x%0x out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700517 __func__, address,
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
519 return eWLAN_PAL_STATUS_E_INVAL;
520 }
521
522 if (0 != (address & 0x3)) {
523 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
524 "%s: Register address 0x%0x is not word aligned",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700525 __func__, address);
Jeff Johnson295189b2012-06-20 16:38:30 -0700526 return eWLAN_PAL_STATUS_E_INVAL;
527 }
528
529 *data = readl_relaxed(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS));
530 rmb();
531
532 return eWLAN_PAL_STATUS_SUCCESS;
533}
534
535/**
536 @brief wpalWriteDeviceMemory provides a mechansim for a client
537 to write data into the hardware address space
538
539 @param address: Start address of physical memory to be written
540 @param s_buffer: Virtual source address from which the data will
541 be read
542 @param len: Number of bytes of data to be written
543
544 @return SUCCESS if the data was successfully written
545*/
546wpt_status wpalWriteDeviceMemory
547(
548 wpt_uint32 address,
549 wpt_uint8* s_buffer,
550 wpt_uint32 len
551)
552{
553 if (NULL == gpEnv) {
554 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
555 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700556 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700557 return eWLAN_PAL_STATUS_E_INVAL;
558 }
559
560 if ((address < gpEnv->wcnss_memory->start) ||
561 ((address + len) > gpEnv->wcnss_memory->end)) {
562 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
563 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700564 __func__, address, len,
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
566 return eWLAN_PAL_STATUS_E_INVAL;
567 }
568
569 memcpy(gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), s_buffer, len);
570 wmb();
571
572 return eWLAN_PAL_STATUS_SUCCESS;
573}
574
575/**
576 @brief wpalReadDeviceMemory provides a mechansim for a client
577 to read data from the hardware address space
578
579 @param address: Start address of physical memory to be read
580 @param d_buffer: Virtual destination address to which the
581 data will be written
582 @param len: Number of bytes of data to be read
583
584 @return SUCCESS if the data was successfully read
585*/
586wpt_status wpalReadDeviceMemory
587(
588 wpt_uint32 address,
589 wpt_uint8* d_buffer,
590 wpt_uint32 len
591)
592{
593 if (NULL == gpEnv) {
594 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
595 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700596 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700597 return eWLAN_PAL_STATUS_E_INVAL;
598 }
599
600 if ((address < gpEnv->wcnss_memory->start) ||
601 ((address + len) > gpEnv->wcnss_memory->end)) {
602 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
603 "%s: Memory address 0x%0x len %d out of range 0x%0x - 0x%0x",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700604 __func__, address, len,
Jeff Johnson295189b2012-06-20 16:38:30 -0700605 gpEnv->wcnss_memory->start, gpEnv->wcnss_memory->end);
606 return eWLAN_PAL_STATUS_E_INVAL;
607 }
608
609 memcpy(d_buffer, gpEnv->mmio + (address - WCNSS_BASE_ADDRESS), len);
610 rmb();
611
612 return eWLAN_PAL_STATUS_SUCCESS;
613}
614
615/**
616 @brief wpalDeviceInit provides a mechanism to initialize the DXE
617 platform adaptation
618
619 @param deviceCB: Implementation-specific device control block
620
621 @see wpalDeviceClose
622
623 @return SUCCESS if the DXE abstraction was opened
624*/
625wpt_status wpalDeviceInit
626(
627 void * deviceCB
628)
629{
630 hdd_context_t *pHddCtx = (hdd_context_t *)deviceCB;
631 struct device *wcnss_device = pHddCtx->parent_dev;
632 struct resource *wcnss_memory;
633 int tx_irq;
634 int rx_irq;
635
636 if (NULL != gpEnv) {
637 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
638 "%s: invoked after subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700639 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700640 return eWLAN_PAL_STATUS_E_INVAL;
641 }
642
643 if (NULL == wcnss_device) {
644 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
645 "%s: invalid device",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700646 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700647 return eWLAN_PAL_STATUS_E_INVAL;
648 }
649
650 wcnss_memory = wcnss_wlan_get_memory_map(wcnss_device);
651 if (NULL == wcnss_memory) {
652 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
653 "%s: WCNSS memory map unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700654 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700655 return eWLAN_PAL_STATUS_E_FAILURE;
656 }
657
658 tx_irq = wcnss_wlan_get_dxe_tx_irq(wcnss_device);
659 if (0 > tx_irq) {
660 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
661 "%s: WCNSS TX IRQ unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700662 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700663 return eWLAN_PAL_STATUS_E_FAILURE;
664 }
665
666 rx_irq = wcnss_wlan_get_dxe_rx_irq(wcnss_device);
667 if (0 > rx_irq) {
668 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
669 "%s: WCNSS RX IRQ unavailable",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700670 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 return eWLAN_PAL_STATUS_E_FAILURE;
672 }
673
674 gpEnv = wpalMemoryAllocate(sizeof(*gpEnv));
675 if (NULL == gpEnv) {
676 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
677 "%s: memory allocation failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700678 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 return eWLAN_PAL_STATUS_E_NOMEM;
680 }
681
682 memset(gpEnv, 0, sizeof(*gpEnv));
683
684 gpEnv->wcnss_memory = wcnss_memory;
685 gpEnv->tx_irq = tx_irq;
686 gpEnv->rx_irq = rx_irq;
687
688 /* note the we don't invoke request_mem_region().
689 the memory described by wcnss_memory encompases the entire
690 register space (including BT and FM) and we do not want
691 exclusive access to that memory */
692
693 gpEnv->mmio = ioremap(wcnss_memory->start, resource_size(wcnss_memory));
694 if (NULL == gpEnv->mmio) {
695 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
696 "%s: memory remap failure",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700697 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700698 goto err_ioremap;
699 }
700
701 gpEnv->tx_registered = 0;
702 gpEnv->rx_registered = 0;
703
704 /* successfully allocated environment, memory and IRQs */
705 return eWLAN_PAL_STATUS_SUCCESS;
706
707 err_ioremap:
708 wpalMemoryFree(gpEnv);
709 gpEnv = NULL;
710
711 return eWLAN_PAL_STATUS_E_FAILURE;
712
713}
714
715
716/**
717 @brief wpalDeviceClose provides a mechanism to deinitialize the DXE
718 platform adaptation
719
720 @param deviceCB: Implementation-specific device control block
721
722 @see wpalDeviceOpen
723
724 @return SUCCESS if the DXE abstraction was closed
725*/
726wpt_status wpalDeviceClose
727(
728 void * deviceCB
729 )
730{
731 if (NULL == gpEnv) {
732 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
733 "%s: invoked before subsystem initialized",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700734 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 return eWLAN_PAL_STATUS_E_INVAL;
736 }
737
738 if (gpEnv->rx_registered)
739 {
740 free_irq(gpEnv->rx_irq, gpEnv);
741 }
742 if (gpEnv->tx_registered)
743 {
744 free_irq(gpEnv->tx_irq, gpEnv);
745 }
746 iounmap(gpEnv->mmio);
747 wpalMemoryFree(gpEnv);
748 gpEnv = NULL;
749
750 return eWLAN_PAL_STATUS_SUCCESS;
751}
752
753/**
754 @brief wpalNotifySmsm provides a mechansim for a client to
755 notify SMSM to start DXE engine and/or condition of Tx
756 ring buffer
757
758 @param clrSt: bit(s) to be cleared on the MASK
759 @param setSt: bit(s) to be set on the MASK
760
761 @return SUCCESS if the operation is successful
762*/
763wpt_status wpalNotifySmsm
764(
765 wpt_uint32 clrSt,
766 wpt_uint32 setSt
767)
768{
769 int rc;
770 rc = smsm_change_state(SMSM_APPS_STATE, clrSt, setSt);
771 if(0 != rc)
772 {
773 WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
774 "%s: smsm_change_state failed",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700775 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 return eWLAN_PAL_STATUS_E_FAILURE;
777 }
778 return eWLAN_PAL_STATUS_SUCCESS;
779}
780