.. | .. |
---|
1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
---|
2 | 1 | /* |
---|
3 | 2 | * DHD Bus Module for SDIO |
---|
4 | 3 | * |
---|
5 | | - * Copyright (C) 1999-2019, Broadcom Corporation |
---|
6 | | - * |
---|
| 4 | + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation |
---|
| 5 | + * |
---|
| 6 | + * Copyright (C) 1999-2017, Broadcom Corporation |
---|
| 7 | + * |
---|
7 | 8 | * Unless you and Broadcom execute a separate written software license |
---|
8 | 9 | * agreement governing use of this software, this software is licensed to you |
---|
9 | 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
---|
10 | 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
---|
11 | 12 | * following added to such license: |
---|
12 | | - * |
---|
| 13 | + * |
---|
13 | 14 | * As a special exception, the copyright holders of this software give you |
---|
14 | 15 | * permission to link this software with independent modules, and to copy and |
---|
15 | 16 | * distribute the resulting executable under terms of your choice, provided that |
---|
.. | .. |
---|
17 | 18 | * the license of that module. An independent module is a module which is not |
---|
18 | 19 | * derived from this software. The special exception does not apply to any |
---|
19 | 20 | * modifications of the software. |
---|
20 | | - * |
---|
| 21 | + * |
---|
21 | 22 | * Notwithstanding the above, under no circumstances may you combine this |
---|
22 | 23 | * software in any way with any other Broadcom software provided under a license |
---|
23 | 24 | * other than the GPL, without Broadcom's express prior written consent. |
---|
.. | .. |
---|
25 | 26 | * |
---|
26 | 27 | * <<Broadcom-WL-IPTag/Open:>> |
---|
27 | 28 | * |
---|
28 | | - * $Id: dhd_sdio.c 722050 2019-08-21 02:24:57Z $ |
---|
| 29 | + * $Id: dhd_sdio.c 701844 2017-05-26 18:56:40Z $ |
---|
29 | 30 | */ |
---|
30 | 31 | |
---|
31 | 32 | #include <typedefs.h> |
---|
32 | 33 | #include <osl.h> |
---|
33 | 34 | #include <bcmsdh.h> |
---|
34 | | - |
---|
35 | | -#ifdef BCMEMBEDIMAGE |
---|
36 | | -#include BCMEMBEDIMAGE |
---|
37 | | -#endif /* BCMEMBEDIMAGE */ |
---|
38 | 35 | |
---|
39 | 36 | #include <bcmdefs.h> |
---|
40 | 37 | #include <bcmutils.h> |
---|
.. | .. |
---|
51 | 48 | #include <sbhnddma.h> |
---|
52 | 49 | |
---|
53 | 50 | #include <sdio.h> |
---|
| 51 | +#ifdef BCMSPI |
---|
| 52 | +#include <spid.h> |
---|
| 53 | +#endif /* BCMSPI */ |
---|
54 | 54 | #include <sbsdio.h> |
---|
55 | 55 | #include <sbsdpcmdev.h> |
---|
56 | 56 | #include <bcmsdpcm.h> |
---|
57 | 57 | #include <bcmsdbus.h> |
---|
| 58 | +#include <trxhdr.h> |
---|
58 | 59 | |
---|
59 | | -#include <proto/ethernet.h> |
---|
60 | | -#include <proto/802.1d.h> |
---|
61 | | -#include <proto/802.11.h> |
---|
| 60 | +#include <ethernet.h> |
---|
| 61 | +#include <802.1d.h> |
---|
| 62 | +#include <802.11.h> |
---|
62 | 63 | |
---|
63 | 64 | #include <dngl_stats.h> |
---|
64 | 65 | #include <dhd.h> |
---|
.. | .. |
---|
68 | 69 | #include <dhdioctl.h> |
---|
69 | 70 | #include <sdiovar.h> |
---|
70 | 71 | |
---|
71 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
72 | | -#include <dhd_chip_info.h> |
---|
73 | | -#endif |
---|
74 | | - |
---|
75 | 72 | #ifdef PROP_TXSTATUS |
---|
76 | 73 | #include <dhd_wlfc.h> |
---|
77 | | -#endif |
---|
| 74 | +#endif // endif |
---|
78 | 75 | #ifdef DHDTCPACK_SUPPRESS |
---|
79 | 76 | #include <dhd_ip.h> |
---|
80 | 77 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
81 | 78 | |
---|
| 79 | +#ifdef BT_OVER_SDIO |
---|
| 80 | +#include <dhd_bt_interface.h> |
---|
| 81 | +#endif /* BT_OVER_SDIO */ |
---|
| 82 | + |
---|
| 83 | +#if defined(DEBUGGER) || defined(DHD_DSCOPE) |
---|
| 84 | +#include <debugger.h> |
---|
| 85 | +#endif /* DEBUGGER || DHD_DSCOPE */ |
---|
| 86 | + |
---|
82 | 87 | bool dhd_mp_halting(dhd_pub_t *dhdp); |
---|
83 | 88 | extern void bcmsdh_waitfor_iodrain(void *sdh); |
---|
84 | 89 | extern void bcmsdh_reject_ioreqs(void *sdh, bool reject); |
---|
85 | | -extern bool bcmsdh_fatal_error(void *sdh); |
---|
| 90 | +extern bool bcmsdh_fatal_error(void *sdh); |
---|
| 91 | +static int dhdsdio_suspend(void *context); |
---|
| 92 | +static int dhdsdio_resume(void *context); |
---|
86 | 93 | |
---|
87 | 94 | #ifndef DHDSDIO_MEM_DUMP_FNAME |
---|
88 | 95 | #define DHDSDIO_MEM_DUMP_FNAME "mem_dump" |
---|
89 | | -#endif |
---|
| 96 | +#endif // endif |
---|
90 | 97 | |
---|
91 | 98 | #define QLEN (1024) /* bulk rx and tx queue lengths */ |
---|
92 | 99 | #define FCHI (QLEN - 10) |
---|
93 | 100 | #define FCLOW (FCHI / 2) |
---|
94 | 101 | #define PRIOMASK 7 |
---|
95 | 102 | |
---|
| 103 | +#define F0_BLOCK_SIZE 32 |
---|
96 | 104 | #define TXRETRIES 2 /* # of retries for tx frames */ |
---|
97 | 105 | #define READ_FRM_CNT_RETRIES 3 |
---|
98 | 106 | #ifndef DHD_RXBOUND |
---|
99 | 107 | #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ |
---|
100 | | -#endif |
---|
| 108 | +#endif // endif |
---|
101 | 109 | |
---|
102 | 110 | #ifndef DHD_TXBOUND |
---|
103 | 111 | #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ |
---|
104 | | -#endif |
---|
| 112 | +#endif // endif |
---|
105 | 113 | |
---|
106 | | -#define DHD_TXMINMAX DHD_TXBOUND /* Max tx frames if rx still pending */ |
---|
| 114 | +#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ |
---|
107 | 115 | |
---|
108 | 116 | #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ |
---|
109 | 117 | #define MAX_MEMBLOCK (32 * 1024) /* Block size used for downloading of dongle image */ |
---|
110 | 118 | |
---|
111 | 119 | #define MAX_DATA_BUF (64 * 1024) /* Must be large enough to hold biggest possible glom */ |
---|
112 | 120 | |
---|
113 | | -//added 20190626 for fixed that download fw failed in new kernel version |
---|
114 | | -#define MAX_MEM_BUF 4096 |
---|
115 | | - |
---|
116 | 121 | #ifndef DHD_FIRSTREAD |
---|
117 | 122 | #define DHD_FIRSTREAD 32 |
---|
118 | | -#endif |
---|
| 123 | +#endif // endif |
---|
119 | 124 | #if !ISPOWEROF2(DHD_FIRSTREAD) |
---|
120 | 125 | #error DHD_FIRSTREAD is not a power of 2! |
---|
121 | | -#endif |
---|
| 126 | +#endif // endif |
---|
122 | 127 | |
---|
123 | 128 | /* Total length of frame header for dongle protocol */ |
---|
124 | 129 | #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) |
---|
.. | .. |
---|
129 | 134 | #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN) |
---|
130 | 135 | #else |
---|
131 | 136 | #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN) |
---|
132 | | -#endif |
---|
| 137 | +#endif // endif |
---|
133 | 138 | |
---|
134 | 139 | /* Space for header read, limit for data packets */ |
---|
135 | 140 | #ifndef MAX_HDR_READ |
---|
136 | 141 | #define MAX_HDR_READ 32 |
---|
137 | | -#endif |
---|
| 142 | +#endif // endif |
---|
138 | 143 | #if !ISPOWEROF2(MAX_HDR_READ) |
---|
139 | 144 | #error MAX_HDR_READ is not a power of 2! |
---|
140 | | -#endif |
---|
| 145 | +#endif // endif |
---|
141 | 146 | |
---|
142 | 147 | #define MAX_RX_DATASZ 2048 |
---|
143 | 148 | |
---|
| 149 | +#define SDIO_FUNC_BLOCK_SIZE_SHIFT 16 |
---|
| 150 | +#define F2_BLOCK_SIZE_256 256 |
---|
| 151 | + |
---|
144 | 152 | /* Maximum milliseconds to wait for F2 to come up */ |
---|
| 153 | +#ifdef BCMQT |
---|
| 154 | +#define DHD_WAIT_F2RDY 30000 |
---|
| 155 | +#else |
---|
145 | 156 | #define DHD_WAIT_F2RDY 3000 |
---|
| 157 | +#endif /* BCMQT */ |
---|
| 158 | + |
---|
| 159 | +/* Maximum usec to wait for HTAVAIL to come up */ |
---|
| 160 | +#ifdef BCMQT |
---|
| 161 | +#define DHD_WAIT_HTAVAIL 10000000 |
---|
| 162 | +#else |
---|
| 163 | +#define DHD_WAIT_HTAVAIL 10000 |
---|
| 164 | +#endif /* BCMQT */ |
---|
146 | 165 | |
---|
147 | 166 | /* Bump up limit on waiting for HT to account for first startup; |
---|
148 | 167 | * if the image is doing a CRC calculation before programming the PMU |
---|
.. | .. |
---|
152 | 171 | #if (PMU_MAX_TRANSITION_DLY <= 1000000) |
---|
153 | 172 | #undef PMU_MAX_TRANSITION_DLY |
---|
154 | 173 | #define PMU_MAX_TRANSITION_DLY 1000000 |
---|
155 | | -#endif |
---|
| 174 | +#endif // endif |
---|
156 | 175 | |
---|
157 | 176 | /* hooks for limiting threshold custom tx num in rx processing */ |
---|
158 | 177 | #define DEFAULT_TXINRX_THRES 0 |
---|
159 | 178 | #ifndef CUSTOM_TXINRX_THRES |
---|
160 | 179 | #define CUSTOM_TXINRX_THRES DEFAULT_TXINRX_THRES |
---|
161 | | -#endif |
---|
| 180 | +#endif // endif |
---|
162 | 181 | |
---|
163 | 182 | /* Value for ChipClockCSR during initial setup */ |
---|
164 | 183 | #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ) |
---|
.. | .. |
---|
174 | 193 | PKTFREE(bus->dhd->osh, pkt, FALSE); |
---|
175 | 194 | DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); |
---|
176 | 195 | |
---|
| 196 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 197 | +DEFINE_MUTEX(_dhd_sdio_mutex_lock_); |
---|
| 198 | +#endif // endif |
---|
| 199 | + |
---|
| 200 | +#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW |
---|
| 201 | +extern unsigned int system_hw_rev; |
---|
| 202 | +#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */ |
---|
177 | 203 | |
---|
178 | 204 | /* Device console log buffer state */ |
---|
179 | 205 | #define CONSOLE_LINE_MAX 192 |
---|
.. | .. |
---|
209 | 235 | #define OVERFLOW_BLKSZ512_MES 80 |
---|
210 | 236 | |
---|
211 | 237 | #define CC_PMUCC3 (0x3) |
---|
| 238 | + |
---|
| 239 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 240 | +/* Ucode host download related macros */ |
---|
| 241 | +#define UCODE_DOWNLOAD_REQUEST 0xCAFECAFE |
---|
| 242 | +#define UCODE_DOWNLOAD_COMPLETE 0xABCDABCD |
---|
| 243 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
| 244 | + |
---|
| 245 | +#if defined(BT_OVER_SDIO) |
---|
| 246 | +#define BTMEM_OFFSET_MASK 0xFF000000 |
---|
| 247 | +#define BTMEM_OFFSET 0x19000000 |
---|
| 248 | +/* BIT0 => WLAN Power UP and BIT1=> WLAN Wake */ |
---|
| 249 | +#define BT2WLAN_PWRUP_WAKE 0x03 |
---|
| 250 | +#define BT2WLAN_PWRUP_ADDR 0x640894 /* This address is specific to 43012B0 */ |
---|
| 251 | + |
---|
| 252 | +#define BTFW_MAX_STR_LEN 600 |
---|
| 253 | +#define BTFW_DOWNLOAD_BLK_SIZE (BTFW_MAX_STR_LEN/2 + 8) |
---|
| 254 | + |
---|
| 255 | +#define BTFW_ADDR_MODE_UNKNOWN 0 |
---|
| 256 | +#define BTFW_ADDR_MODE_EXTENDED 1 |
---|
| 257 | +#define BTFW_ADDR_MODE_SEGMENT 2 |
---|
| 258 | +#define BTFW_ADDR_MODE_LINEAR32 3 |
---|
| 259 | + |
---|
| 260 | +#define BTFW_HEX_LINE_TYPE_DATA 0 |
---|
| 261 | +#define BTFW_HEX_LINE_TYPE_END_OF_DATA 1 |
---|
| 262 | +#define BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS 2 |
---|
| 263 | +#define BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS 4 |
---|
| 264 | +#define BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS 5 |
---|
| 265 | + |
---|
| 266 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 267 | + |
---|
212 | 268 | /* Private data for SDIO bus interaction */ |
---|
213 | 269 | typedef struct dhd_bus { |
---|
214 | 270 | dhd_pub_t *dhd; |
---|
.. | .. |
---|
277 | 333 | uint polltick; /* Tick counter */ |
---|
278 | 334 | uint pollcnt; /* Count of active polls */ |
---|
279 | 335 | |
---|
280 | | -#ifdef DHD_DEBUG |
---|
281 | 336 | dhd_console_t console; /* Console output polling support */ |
---|
282 | 337 | uint console_addr; /* Console address from shared struct */ |
---|
283 | | -#endif /* DHD_DEBUG */ |
---|
284 | 338 | |
---|
285 | 339 | uint regfails; /* Count of R_REG/W_REG failures */ |
---|
286 | 340 | |
---|
.. | .. |
---|
294 | 348 | int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ |
---|
295 | 349 | bool use_rxchain; /* If dhd should use PKT chains */ |
---|
296 | 350 | bool sleeping; /* Is SDIO bus sleeping? */ |
---|
297 | | -#if (defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16)) |
---|
| 351 | +#if defined(SUPPORT_P2P_GO_PS) |
---|
298 | 352 | wait_queue_head_t bus_sleep; |
---|
299 | 353 | #endif /* LINUX && SUPPORT_P2P_GO_PS */ |
---|
300 | 354 | uint rxflow_mode; /* Rx flow control mode */ |
---|
.. | .. |
---|
359 | 413 | uint f2rxdata; /* Number of frame data reads */ |
---|
360 | 414 | uint f2txdata; /* Number of f2 frame writes */ |
---|
361 | 415 | uint f1regdata; /* Number of f1 register accesses */ |
---|
| 416 | + wake_counts_t wake_counts; /* Wake up counter */ |
---|
| 417 | +#ifdef BCMSPI |
---|
| 418 | + bool dwordmode; |
---|
| 419 | +#endif /* BCMSPI */ |
---|
362 | 420 | #ifdef DHDENABLE_TAILPAD |
---|
363 | 421 | uint tx_tailpad_chain; /* Number of tail padding by chaining pad_pkt */ |
---|
364 | 422 | uint tx_tailpad_pktget; /* Number of tail padding by new PKTGET */ |
---|
.. | .. |
---|
366 | 424 | uint8 *ctrl_frame_buf; |
---|
367 | 425 | uint32 ctrl_frame_len; |
---|
368 | 426 | bool ctrl_frame_stat; |
---|
| 427 | +#ifndef BCMSPI |
---|
369 | 428 | uint32 rxint_mode; /* rx interrupt mode */ |
---|
| 429 | +#endif /* BCMSPI */ |
---|
370 | 430 | bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram |
---|
371 | 431 | * Available with socram rev 16 |
---|
372 | 432 | * Remap region not DMA-able |
---|
.. | .. |
---|
385 | 445 | uint32 txglom_total_len; /* Total length of pkts in glom array */ |
---|
386 | 446 | bool txglom_enable; /* Flag to indicate whether tx glom is enabled/disabled */ |
---|
387 | 447 | uint32 txglomsize; /* Glom size limitation */ |
---|
388 | | - uint8 *membuf; |
---|
389 | 448 | #ifdef DHDENABLE_TAILPAD |
---|
390 | 449 | void *pad_pkt; |
---|
391 | 450 | #endif /* DHDENABLE_TAILPAD */ |
---|
| 451 | + uint32 dongle_trap_addr; /* device trap addr location in device memory */ |
---|
| 452 | +#if defined(BT_OVER_SDIO) |
---|
| 453 | + char *btfw_path; /* module_param: path to BT firmware image */ |
---|
| 454 | + uint32 bt_use_count; /* Counter that tracks whether BT is using the bus */ |
---|
| 455 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 456 | + bool chipidpresent; /* ChipID is present in SDIO core enum address space */ |
---|
| 457 | + bool secureboot; /* security related features are present */ |
---|
392 | 458 | } dhd_bus_t; |
---|
| 459 | + |
---|
| 460 | +/* |
---|
| 461 | + * Whenever DHD_IDLE_IMMEDIATE condition is handled, we have to now check if |
---|
| 462 | + * BT is active too. Instead of adding #ifdef code in all the places, we thought |
---|
| 463 | + * of adding one macro check as part of the if condition that checks for DHD_IDLE_IMMEDIATE |
---|
| 464 | + * In case of non BT over SDIO builds, this macro will always return TRUE. In case |
---|
| 465 | + * of the builds where BT_OVER_SDIO is enabled, it will expand to a condition check |
---|
| 466 | + * that checks if bt_use_count is zero. So this macro will return equate to 1 if |
---|
| 467 | + * bt_use_count is 0, indicating that there are no active users and if bt_use_count |
---|
| 468 | + * is non zero it would return 0 there by preventing the caller from executing the |
---|
| 469 | + * sleep calls. |
---|
| 470 | + */ |
---|
| 471 | +#ifdef BT_OVER_SDIO |
---|
| 472 | +#define NO_OTHER_ACTIVE_BUS_USER(bus) (bus->bt_use_count == 0) |
---|
| 473 | +#else |
---|
| 474 | +#define NO_OTHER_ACTIVE_BUS_USER(bus) (1) |
---|
| 475 | +#endif /* BT_OVER_SDIO */ |
---|
393 | 476 | |
---|
394 | 477 | /* clkstate */ |
---|
395 | 478 | #define CLK_NONE 0 |
---|
.. | .. |
---|
414 | 497 | extern uint dhd_watchdog_ms; |
---|
415 | 498 | extern uint sd_f1_blocksize; |
---|
416 | 499 | |
---|
| 500 | +#ifdef BCMSPI_ANDROID |
---|
| 501 | +extern uint *dhd_spi_lockcount; |
---|
| 502 | +#endif /* BCMSPI_ANDROID */ |
---|
417 | 503 | |
---|
418 | 504 | extern void dhd_os_wd_timer(void *bus, uint wdtick); |
---|
419 | 505 | int dhd_enableOOB(dhd_pub_t *dhd, bool sleep); |
---|
| 506 | + |
---|
| 507 | +#ifdef DHD_PM_CONTROL_FROM_FILE |
---|
| 508 | +extern bool g_pm_control; |
---|
| 509 | +#endif /* DHD_PM_CONTROL_FROM_FILE */ |
---|
| 510 | + |
---|
| 511 | +#ifdef DHD_FW_COREDUMP |
---|
| 512 | +uint tcm_dump_enable; |
---|
| 513 | +module_param(tcm_dump_enable, uint, 0); |
---|
| 514 | +#endif /* DHD_FW_COREDUMP */ |
---|
420 | 515 | |
---|
421 | 516 | /* Tx/Rx bounds */ |
---|
422 | 517 | uint dhd_txbound; |
---|
.. | .. |
---|
440 | 535 | static bool retrydata; |
---|
441 | 536 | #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) |
---|
442 | 537 | |
---|
| 538 | +#ifdef BCMSPI |
---|
| 539 | +/* At a watermark around 8 the spid hits underflow error. */ |
---|
| 540 | +static uint watermark = 32; |
---|
| 541 | +static uint mesbusyctrl = 0; |
---|
| 542 | +#else |
---|
443 | 543 | static uint watermark = 8; |
---|
444 | 544 | static uint mesbusyctrl = 0; |
---|
| 545 | +#endif /* BCMSPI */ |
---|
445 | 546 | static const uint firstread = DHD_FIRSTREAD; |
---|
446 | 547 | |
---|
447 | 548 | /* Retry count for register access failures */ |
---|
.. | .. |
---|
450 | 551 | /* Force even SD lengths (some host controllers mess up on odd bytes) */ |
---|
451 | 552 | static bool forcealign; |
---|
452 | 553 | |
---|
453 | | -#define ALIGNMENT 4 |
---|
| 554 | +#if defined(DEBUGGER) |
---|
| 555 | +static uint32 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr); |
---|
| 556 | +static void dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val); |
---|
454 | 557 | |
---|
455 | | -#define F2_BLOCK_SIZE_256 256 |
---|
456 | | -#define SDIO_FUNC_BLOCK_SIZE_SHIFT 16 |
---|
| 558 | +/** the debugger layer will call back into this (bus) layer to read/write dongle memory */ |
---|
| 559 | +static struct dhd_dbg_bus_ops_s bus_ops = { |
---|
| 560 | + .read_u16 = NULL, |
---|
| 561 | + .read_u32 = dhd_sdio_reg_read, |
---|
| 562 | + .write_u32 = dhd_sdio_reg_write, |
---|
| 563 | +}; |
---|
| 564 | +#endif /* DEBUGGER */ |
---|
| 565 | + |
---|
| 566 | +#define ALIGNMENT 4 |
---|
457 | 567 | |
---|
458 | 568 | #if defined(OOB_INTR_ONLY) && defined(HW_OOB) |
---|
459 | 569 | extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); |
---|
460 | | -#endif |
---|
| 570 | +#endif // endif |
---|
461 | 571 | |
---|
462 | 572 | #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) |
---|
463 | 573 | #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD |
---|
.. | .. |
---|
480 | 590 | /* Try doing readahead */ |
---|
481 | 591 | static bool dhd_readahead; |
---|
482 | 592 | |
---|
| 593 | +#define TXCTL_CREDITS 2 |
---|
| 594 | + |
---|
483 | 595 | /* To check if there's window offered */ |
---|
484 | 596 | #define DATAOK(bus) \ |
---|
485 | | - (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ |
---|
| 597 | + (((uint8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS) && \ |
---|
486 | 598 | (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) |
---|
487 | 599 | |
---|
488 | 600 | /* To check if there's window offered for ctrl frame */ |
---|
.. | .. |
---|
554 | 666 | #define SDIO_DEVICE_RXDATAINT_MODE_0 1 /* from sdiod rev 4 */ |
---|
555 | 667 | #define SDIO_DEVICE_RXDATAINT_MODE_1 2 /* from sdiod rev 4 */ |
---|
556 | 668 | |
---|
| 669 | +#define SDIO_FUNC_BLOCK_SIZE_SHIFT 16 |
---|
| 670 | +#define F2_BLOCK 2 |
---|
| 671 | +#define DEFAULT_SDIO_F2_BLKSIZE 512 |
---|
| 672 | + |
---|
| 673 | +#ifdef BCMSPI |
---|
| 674 | + |
---|
| 675 | +#define FRAME_AVAIL_MASK(bus) I_HMB_FRAME_IND |
---|
| 676 | + |
---|
| 677 | +#define DHD_BUS SPI_BUS |
---|
| 678 | + |
---|
| 679 | +/* check packet-available-interrupt in piggybacked dstatus */ |
---|
| 680 | +#define PKT_AVAILABLE(bus, intstatus) (bcmsdh_get_dstatus(bus->sdh) & STATUS_F2_PKT_AVAILABLE) |
---|
| 681 | + |
---|
| 682 | +#define HOSTINTMASK (I_HMB_FC_CHANGE | I_HMB_HOST_INT) |
---|
| 683 | + |
---|
| 684 | +#define GSPI_PR55150_BAILOUT \ |
---|
| 685 | +do { \ |
---|
| 686 | + uint32 dstatussw = bcmsdh_get_dstatus((void *)bus->sdh); \ |
---|
| 687 | + uint32 dstatushw = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL); \ |
---|
| 688 | + uint32 intstatuserr = 0; \ |
---|
| 689 | + uint retries = 0; \ |
---|
| 690 | + \ |
---|
| 691 | + R_SDREG(intstatuserr, &bus->regs->intstatus, retries); \ |
---|
| 692 | + printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n", \ |
---|
| 693 | + dstatussw, dstatushw, intstatuserr); \ |
---|
| 694 | + \ |
---|
| 695 | + bus->nextlen = 0; \ |
---|
| 696 | + *finished = TRUE; \ |
---|
| 697 | +} while (0) |
---|
| 698 | + |
---|
| 699 | +#else /* BCMSDIO */ |
---|
557 | 700 | |
---|
558 | 701 | #define FRAME_AVAIL_MASK(bus) \ |
---|
559 | 702 | ((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL) |
---|
.. | .. |
---|
566 | 709 | |
---|
567 | 710 | #define GSPI_PR55150_BAILOUT |
---|
568 | 711 | |
---|
| 712 | +#endif /* BCMSPI */ |
---|
| 713 | + |
---|
| 714 | +extern uint sd_f2_blocksize; |
---|
| 715 | + |
---|
569 | 716 | #ifdef SDTEST |
---|
570 | 717 | static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq); |
---|
571 | 718 | static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count); |
---|
572 | | -#endif |
---|
| 719 | +#endif // endif |
---|
573 | 720 | |
---|
574 | 721 | static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size); |
---|
575 | 722 | #ifdef DHD_DEBUG |
---|
.. | .. |
---|
578 | 725 | |
---|
579 | 726 | #if defined(DHD_FW_COREDUMP) |
---|
580 | 727 | static int dhdsdio_mem_dump(dhd_bus_t *bus); |
---|
| 728 | +static int dhdsdio_get_mem_dump(dhd_bus_t *bus); |
---|
581 | 729 | #endif /* DHD_FW_COREDUMP */ |
---|
582 | 730 | static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap); |
---|
| 731 | +static int dhdsdio_readshared_console(dhd_bus_t *bus); |
---|
583 | 732 | static int dhdsdio_download_state(dhd_bus_t *bus, bool enter); |
---|
| 733 | +static int dhdsdio_wait_bootloader_ready(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 734 | +static int dhdsdio_dongle_host_get_handshake_address(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 735 | +static int dhdsdio_dongle_host_pre_handshake(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 736 | +static int dhdsdio_dongle_host_post_handshake(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 737 | +static int dhdsdio_dongle_host_chk_validation(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 738 | +static int dhdsdio_dongle_host_post_varswrite(dhd_bus_t *bus, hs_addrs_t *addr); |
---|
| 739 | +int dhdsdio_dongle_host_pre_wd_reset_sequence(dhd_bus_t *bus); |
---|
| 740 | + |
---|
| 741 | +static int dhdsdio_handshake_msg_reg_write(dhd_bus_t *bus, volatile void *addr, |
---|
| 742 | + uint32 *buffer); |
---|
| 743 | +static int dhdsdio_handshake_msg_reg_read(dhd_bus_t *bus, volatile void *addr, |
---|
| 744 | + uint32 *buffer); |
---|
| 745 | +static int dhdsdio_cfg_write_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset); |
---|
| 746 | +static int dhdsdio_cfg_read_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset); |
---|
| 747 | +static int dhdsdio_dongle_host_handshake_spinwait(dhd_bus_t *bus, volatile void *addr, |
---|
| 748 | + uint32 bitshift, uint32 us); |
---|
584 | 749 | |
---|
585 | 750 | static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh); |
---|
586 | 751 | static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh); |
---|
.. | .. |
---|
609 | 774 | static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh); |
---|
610 | 775 | static int _dhdsdio_download_firmware(dhd_bus_t *bus); |
---|
611 | 776 | |
---|
| 777 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 778 | +static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path); |
---|
| 779 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
612 | 780 | static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path); |
---|
613 | 781 | static int dhdsdio_download_nvram(dhd_bus_t *bus); |
---|
614 | | -#ifdef BCMEMBEDIMAGE |
---|
615 | | -static int dhdsdio_download_code_array(dhd_bus_t *bus); |
---|
616 | | -#endif |
---|
617 | 782 | static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep); |
---|
618 | 783 | static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok); |
---|
619 | 784 | static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus); |
---|
620 | 785 | static bool dhdsdio_dpc(dhd_bus_t *bus); |
---|
| 786 | +static int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len); |
---|
| 787 | +static int dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode); |
---|
| 788 | +static int dhdsdio_sdclk(dhd_bus_t *bus, bool on); |
---|
| 789 | +static void dhdsdio_advertise_bus_cleanup(dhd_pub_t *dhdp); |
---|
621 | 790 | |
---|
622 | | -#ifdef WLMEDIA_HTSF |
---|
623 | | -#include <htsf.h> |
---|
624 | | -extern uint32 dhd_get_htsf(void *dhd, int ifidx); |
---|
625 | | -#endif /* WLMEDIA_HTSF */ |
---|
| 791 | +#if defined(BT_OVER_SDIO) |
---|
| 792 | +static int extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value); |
---|
| 793 | +static int read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode, |
---|
| 794 | + uint16 * hi_addr, uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes); |
---|
| 795 | +static int dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh); |
---|
| 796 | +static int _dhdsdio_download_btfw(struct dhd_bus *bus); |
---|
| 797 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
626 | 798 | |
---|
627 | | -int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len); |
---|
628 | 799 | #ifdef DHD_ULP |
---|
629 | 800 | #include <dhd_ulp.h> |
---|
630 | 801 | static int dhd_bus_ulp_reinit_fw(dhd_bus_t *bus); |
---|
.. | .. |
---|
702 | 873 | return err; |
---|
703 | 874 | } |
---|
704 | 875 | |
---|
| 876 | +#ifdef BCMSPI |
---|
| 877 | +static void |
---|
| 878 | +dhdsdio_wkwlan(dhd_bus_t *bus, bool on) |
---|
| 879 | +{ |
---|
| 880 | + int err; |
---|
| 881 | + uint32 regdata; |
---|
| 882 | + bcmsdh_info_t *sdh = bus->sdh; |
---|
| 883 | + |
---|
| 884 | + if (bus->sih->buscoretype == SDIOD_CORE_ID) { |
---|
| 885 | + /* wake up wlan function :WAKE_UP goes as ht_avail_request and alp_avail_request */ |
---|
| 886 | + regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL); |
---|
| 887 | + DHD_INFO(("F0 REG0 rd = 0x%x\n", regdata)); |
---|
| 888 | + |
---|
| 889 | + if (on == TRUE) |
---|
| 890 | + regdata |= WAKE_UP; |
---|
| 891 | + else |
---|
| 892 | + regdata &= ~WAKE_UP; |
---|
| 893 | + |
---|
| 894 | + bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err); |
---|
| 895 | + } |
---|
| 896 | +} |
---|
| 897 | +#endif /* BCMSPI */ |
---|
705 | 898 | |
---|
706 | 899 | #ifdef USE_OOB_GPIO1 |
---|
707 | 900 | static int |
---|
.. | .. |
---|
711 | 904 | |
---|
712 | 905 | bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP); |
---|
713 | 906 | |
---|
714 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
715 | | - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
| 907 | + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
| 908 | + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
716 | 909 | |
---|
717 | 910 | /* Set device for gpio1 wakeup */ |
---|
718 | 911 | bcmsdh_reg_write(bus->sdh, addr, 4, 2); |
---|
.. | .. |
---|
735 | 928 | bool cap = FALSE; |
---|
736 | 929 | uint32 core_capext, addr, data; |
---|
737 | 930 | |
---|
| 931 | + /* Query for SRcore in Chip else check for SR mode is enabled in FW */ |
---|
| 932 | + if (si_findcoreidx(bus->sih, SR_CORE_ID, 0) != BADIDX) { |
---|
| 933 | + if (bus->sih->chip == CYW55500_CHIP_ID || |
---|
| 934 | + bus->sih->chip == CYW55560_CHIP_ID) { |
---|
| 935 | + return true; |
---|
| 936 | + } |
---|
| 937 | + } |
---|
| 938 | + |
---|
738 | 939 | if (bus->sih->chip == BCM43430_CHIP_ID || |
---|
739 | 940 | bus->sih->chip == BCM43018_CHIP_ID) { |
---|
740 | 941 | /* check if fw initialized sr engine */ |
---|
741 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, sr_control1); |
---|
| 942 | + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, sr_control1); |
---|
742 | 943 | if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0) |
---|
743 | 944 | cap = TRUE; |
---|
744 | 945 | |
---|
745 | 946 | return cap; |
---|
746 | 947 | } |
---|
747 | | - if (bus->sih->chip == BCM4324_CHIP_ID) { |
---|
748 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
749 | | - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
750 | | - bcmsdh_reg_write(bus->sdh, addr, 4, 3); |
---|
751 | | - core_capext = bcmsdh_reg_read(bus->sdh, data, 4); |
---|
752 | | - } else if (bus->sih->chip == BCM4330_CHIP_ID) { |
---|
| 948 | + if ( |
---|
| 949 | + 0) { |
---|
753 | 950 | core_capext = FALSE; |
---|
754 | 951 | } else if ((bus->sih->chip == BCM4335_CHIP_ID) || |
---|
755 | 952 | (bus->sih->chip == BCM4339_CHIP_ID) || |
---|
756 | | - (bus->sih->chip == BCM43349_CHIP_ID) || |
---|
757 | | - (bus->sih->chip == BCM4345_CHIP_ID) || |
---|
758 | | - (bus->sih->chip == BCM43454_CHIP_ID) || |
---|
| 953 | + BCM4345_CHIP(bus->sih->chip) || |
---|
759 | 954 | (bus->sih->chip == BCM4354_CHIP_ID) || |
---|
760 | | - (bus->sih->chip == BCM4356_CHIP_ID) || |
---|
761 | 955 | (bus->sih->chip == BCM4358_CHIP_ID) || |
---|
762 | 956 | (BCM4349_CHIP(bus->sih->chip)) || |
---|
763 | 957 | (bus->sih->chip == BCM4350_CHIP_ID) || |
---|
| 958 | +#ifdef UNRELEASEDCHIP_FOR_ANDROID |
---|
| 959 | + (bus->sih->chip == BCM4362_CHIP_ID) || |
---|
| 960 | +#endif /* UNRELEASEDCHIP_FOR_ANDROID */ |
---|
764 | 961 | (bus->sih->chip == BCM43012_CHIP_ID) || |
---|
| 962 | + (bus->sih->chip == BCM43014_CHIP_ID) || |
---|
| 963 | + (bus->sih->chip == BCM43751_CHIP_ID) || |
---|
765 | 964 | (bus->sih->chip == BCM4373_CHIP_ID)) { |
---|
766 | 965 | core_capext = TRUE; |
---|
767 | 966 | } else { |
---|
768 | 967 | core_capext = bcmsdh_reg_read(bus->sdh, |
---|
769 | 968 | si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)), |
---|
770 | 969 | 4); |
---|
| 970 | + |
---|
771 | 971 | core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK); |
---|
772 | 972 | } |
---|
773 | 973 | if (!(core_capext)) |
---|
774 | 974 | return FALSE; |
---|
775 | 975 | |
---|
776 | | - if (bus->sih->chip == BCM4324_CHIP_ID) { |
---|
777 | | - /* FIX: Should change to query SR control register instead */ |
---|
778 | | - cap = TRUE; |
---|
779 | | - } else if ((bus->sih->chip == BCM4335_CHIP_ID) || |
---|
| 976 | + if ((bus->sih->chip == BCM4335_CHIP_ID) || |
---|
780 | 977 | (bus->sih->chip == BCM4339_CHIP_ID) || |
---|
781 | | - (bus->sih->chip == BCM43349_CHIP_ID) || |
---|
782 | | - (bus->sih->chip == BCM4345_CHIP_ID) || |
---|
783 | | - (bus->sih->chip == BCM43454_CHIP_ID) || |
---|
| 978 | + BCM4345_CHIP(bus->sih->chip) || |
---|
784 | 979 | (bus->sih->chip == BCM4354_CHIP_ID) || |
---|
785 | | - (bus->sih->chip == BCM4356_CHIP_ID) || |
---|
786 | 980 | (bus->sih->chip == BCM4358_CHIP_ID) || |
---|
787 | 981 | (bus->sih->chip == BCM4350_CHIP_ID)) { |
---|
788 | 982 | uint32 enabval = 0; |
---|
789 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
790 | | - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
| 983 | + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
| 984 | + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
791 | 985 | bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3); |
---|
792 | 986 | enabval = bcmsdh_reg_read(bus->sdh, data, 4); |
---|
793 | 987 | |
---|
794 | 988 | if ((bus->sih->chip == BCM4350_CHIP_ID) || |
---|
795 | | - (bus->sih->chip == BCM4345_CHIP_ID) || |
---|
796 | | - (bus->sih->chip == BCM43454_CHIP_ID) || |
---|
| 989 | + BCM4345_CHIP(bus->sih->chip) || |
---|
797 | 990 | (bus->sih->chip == BCM4354_CHIP_ID) || |
---|
798 | | - (bus->sih->chip == BCM4356_CHIP_ID) || |
---|
799 | 991 | (bus->sih->chip == BCM4358_CHIP_ID)) |
---|
800 | 992 | enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE; |
---|
801 | 993 | |
---|
.. | .. |
---|
813 | 1005 | } |
---|
814 | 1006 | |
---|
815 | 1007 | static int |
---|
816 | | -dhdsdio_srwar_init(dhd_bus_t *bus) |
---|
817 | | -{ |
---|
818 | | - bcmsdh_gpio_init(bus->sdh); |
---|
819 | | - |
---|
820 | | -#ifdef USE_OOB_GPIO1 |
---|
821 | | - dhdsdio_oobwakeup_init(bus); |
---|
822 | | -#endif |
---|
823 | | - |
---|
824 | | - |
---|
825 | | - return 0; |
---|
826 | | -} |
---|
827 | | - |
---|
828 | | -static int |
---|
829 | 1008 | dhdsdio_sr_init(dhd_bus_t *bus) |
---|
830 | 1009 | { |
---|
831 | 1010 | uint8 val; |
---|
832 | 1011 | int err = 0; |
---|
833 | 1012 | |
---|
834 | | - if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) |
---|
835 | | - dhdsdio_srwar_init(bus); |
---|
836 | | - |
---|
837 | | - |
---|
838 | | - if (bus->sih->chip == BCM43012_CHIP_ID) { |
---|
| 1013 | + if (bus->sih->chip == BCM43012_CHIP_ID || |
---|
| 1014 | + bus->sih->chip == CYW55500_CHIP_ID || |
---|
| 1015 | + bus->sih->chip == CYW55560_CHIP_ID) { |
---|
839 | 1016 | val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL); |
---|
840 | 1017 | val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT; |
---|
841 | 1018 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, |
---|
.. | .. |
---|
855 | 1032 | (SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT)); |
---|
856 | 1033 | #endif /* USE_CMD14 */ |
---|
857 | 1034 | |
---|
858 | | - dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC); |
---|
| 1035 | + if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID || |
---|
| 1036 | + CHIPID(bus->sih->chip) == BCM43018_CHIP_ID || |
---|
| 1037 | + CHIPID(bus->sih->chip) == BCM4339_CHIP_ID || |
---|
| 1038 | + CHIPID(bus->sih->chip) == BCM43012_CHIP_ID || |
---|
| 1039 | + CHIPID(bus->sih->chip) == CYW55500_CHIP_ID || |
---|
| 1040 | + CHIPID(bus->sih->chip) == CYW55560_CHIP_ID || |
---|
| 1041 | +#ifdef UNRELEASEDCHIP_FOR_ANDROID |
---|
| 1042 | + CHIPID(bus->sih->chip) == BCM4362_CHIP_ID || |
---|
| 1043 | +#endif /* UNRELEASEDCHIP_FOR_ANDROID */ |
---|
| 1044 | + CHIPID(bus->sih->chip) == BCM43014_CHIP_ID || |
---|
| 1045 | + CHIPID(bus->sih->chip) == BCM43751_CHIP_ID || |
---|
| 1046 | + FALSE) |
---|
| 1047 | +#ifdef BCMSPI |
---|
| 1048 | + dhdsdio_wkwlan(bus, FALSE); |
---|
| 1049 | +#else |
---|
| 1050 | + dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC); |
---|
| 1051 | +#endif /* BCMSPI */ |
---|
859 | 1052 | |
---|
860 | | - if (bus->sih->chip == BCM43012_CHIP_ID) { |
---|
| 1053 | + if (bus->sih->chip == BCM43012_CHIP_ID || |
---|
| 1054 | + bus->sih->chip == CYW55500_CHIP_ID || |
---|
| 1055 | + bus->sih->chip == CYW55560_CHIP_ID) { |
---|
861 | 1056 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, |
---|
862 | 1057 | SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err); |
---|
863 | 1058 | } else { |
---|
.. | .. |
---|
906 | 1101 | #define KSO_WAKE_RETRY_COUNT 100 |
---|
907 | 1102 | #define ERROR_BCME_NODEVICE_MAX 1 |
---|
908 | 1103 | |
---|
909 | | -#include <linux/mmc/sdio_func.h> |
---|
910 | | -#include <linux/mmc/host.h> |
---|
911 | | -#include "bcmsdh_sdmmc.h" |
---|
| 1104 | +#define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) |
---|
| 1105 | +#ifndef CUSTOM_MAX_KSO_ATTEMPTS |
---|
| 1106 | +#define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS |
---|
| 1107 | +#endif // endif |
---|
912 | 1108 | |
---|
913 | | -#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) |
---|
914 | 1109 | static int |
---|
915 | 1110 | dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) |
---|
916 | 1111 | { |
---|
917 | 1112 | uint8 wr_val = 0, rd_val, cmp_val, bmask; |
---|
918 | 1113 | int err = 0; |
---|
919 | 1114 | int try_cnt = 0; |
---|
920 | | - struct mmc_host *host; |
---|
921 | | - struct sdioh_info *sd = (struct sdioh_info *)(bus->sdh->sdioh); |
---|
922 | | - struct sdio_func *func = sd->func[SDIO_FUNC_0]; |
---|
923 | | - |
---|
924 | | - host = func->card->host; |
---|
925 | | - mmc_retune_disable(host); |
---|
926 | 1115 | |
---|
927 | 1116 | KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"))); |
---|
928 | 1117 | |
---|
.. | .. |
---|
930 | 1119 | |
---|
931 | 1120 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); |
---|
932 | 1121 | |
---|
933 | | - |
---|
934 | | - /* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared. |
---|
935 | | - * So the further reads of KSO register could fail. Thereby just bailing out immediately |
---|
936 | | - * after clearing KSO bit, to avoid polling of KSO bit. |
---|
| 1122 | + /* In case of 43012/555x0 chip, the chip could go down immediately after KSO bit is |
---|
| 1123 | + * cleared. So the further reads of KSO register could fail. Thereby just bailing out |
---|
| 1124 | + * immediately after clearing KSO bit, to avoid polling of KSO bit. |
---|
937 | 1125 | */ |
---|
938 | | - if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID)) { |
---|
939 | | - mmc_retune_enable(host); |
---|
| 1126 | + if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID || |
---|
| 1127 | + bus->sih->chip == CYW55500_CHIP_ID || |
---|
| 1128 | + bus->sih->chip == CYW55560_CHIP_ID)) { |
---|
940 | 1129 | return err; |
---|
941 | 1130 | } |
---|
942 | 1131 | |
---|
.. | .. |
---|
965 | 1154 | OSL_DELAY(KSO_WAIT_US); |
---|
966 | 1155 | |
---|
967 | 1156 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); |
---|
968 | | - } while (try_cnt++ < MAX_KSO_ATTEMPTS); |
---|
969 | | - |
---|
| 1157 | + } while (try_cnt++ < CUSTOM_MAX_KSO_ATTEMPTS); |
---|
970 | 1158 | |
---|
971 | 1159 | if (try_cnt > 2) |
---|
972 | 1160 | KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n", |
---|
973 | 1161 | __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err)); |
---|
974 | 1162 | |
---|
975 | | - if (try_cnt > MAX_KSO_ATTEMPTS) { |
---|
| 1163 | + if (try_cnt > CUSTOM_MAX_KSO_ATTEMPTS) { |
---|
976 | 1164 | DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n", |
---|
977 | 1165 | __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err)); |
---|
978 | 1166 | } |
---|
979 | | - |
---|
980 | | - mmc_retune_enable(host); |
---|
981 | 1167 | |
---|
982 | 1168 | return err; |
---|
983 | 1169 | } |
---|
.. | .. |
---|
1085 | 1271 | #ifdef USE_CMD14 |
---|
1086 | 1272 | err = bcmsdh_sleep(bus->sdh, TRUE); |
---|
1087 | 1273 | #else |
---|
1088 | | - |
---|
| 1274 | + if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) { |
---|
| 1275 | + if (sd1idle) { |
---|
| 1276 | + /* Change to SD1 mode */ |
---|
| 1277 | + dhdsdio_set_sdmode(bus, 1); |
---|
| 1278 | + } |
---|
| 1279 | + } |
---|
1089 | 1280 | |
---|
1090 | 1281 | err = dhdsdio_clk_kso_enab(bus, FALSE); |
---|
1091 | 1282 | if (OOB_WAKEUP_ENAB(bus)) |
---|
.. | .. |
---|
1096 | 1287 | |
---|
1097 | 1288 | if ((SLPAUTO_ENAB(bus)) && (bus->idleclock != DHD_IDLE_ACTIVE)) { |
---|
1098 | 1289 | DHD_TRACE(("%s: Turnoff SD clk\n", __FUNCTION__)); |
---|
1099 | | - dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
| 1290 | + /* Now remove the SD clock */ |
---|
| 1291 | + err = dhdsdio_sdclk(bus, FALSE); |
---|
1100 | 1292 | } |
---|
1101 | 1293 | } else { |
---|
1102 | 1294 | /* Exit Sleep */ |
---|
.. | .. |
---|
1104 | 1296 | if (bus->clkstate == CLK_NONE) { |
---|
1105 | 1297 | DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__)); |
---|
1106 | 1298 | dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); |
---|
1107 | | - } |
---|
1108 | | - |
---|
1109 | | - if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) { |
---|
1110 | | - SPINWAIT_SLEEP(sdioh_spinwait_sleep, |
---|
1111 | | - (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE), |
---|
1112 | | - GPIO_DEV_SRSTATE_TIMEOUT); |
---|
1113 | | - |
---|
1114 | | - if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) { |
---|
1115 | | - DHD_ERROR(("ERROR: GPIO_DEV_SRSTATE still low!\n")); |
---|
1116 | | - } |
---|
1117 | 1299 | } |
---|
1118 | 1300 | #ifdef USE_CMD14 |
---|
1119 | 1301 | err = bcmsdh_sleep(bus->sdh, FALSE); |
---|
.. | .. |
---|
1155 | 1337 | |
---|
1156 | 1338 | if (err != 0) { |
---|
1157 | 1339 | DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry)); |
---|
| 1340 | +#ifndef BT_OVER_SDIO |
---|
1158 | 1341 | err = 0; /* continue anyway */ |
---|
| 1342 | +#endif /* BT_OVER_SDIO */ |
---|
1159 | 1343 | } |
---|
1160 | 1344 | |
---|
1161 | | - |
---|
| 1345 | + if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) { |
---|
| 1346 | + dhdsdio_set_sdmode(bus, bus->sd_mode); |
---|
| 1347 | + } |
---|
1162 | 1348 | #endif /* !USE_CMD14 */ |
---|
1163 | 1349 | |
---|
1164 | 1350 | if (err == 0) { |
---|
.. | .. |
---|
1181 | 1367 | SPINWAIT_SLEEP(sdioh_spinwait_sleep, |
---|
1182 | 1368 | (((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, |
---|
1183 | 1369 | SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) != |
---|
1184 | | - (SBSDIO_HT_AVAIL)), (10000)); |
---|
| 1370 | + (SBSDIO_HT_AVAIL)), (DHD_WAIT_HTAVAIL)); |
---|
1185 | 1371 | |
---|
1186 | 1372 | DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr)); |
---|
1187 | 1373 | if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) { |
---|
.. | .. |
---|
1220 | 1406 | clkctl = 0; |
---|
1221 | 1407 | sdh = bus->sdh; |
---|
1222 | 1408 | |
---|
1223 | | - |
---|
1224 | 1409 | if (!KSO_ENAB(bus)) |
---|
1225 | 1410 | return BCME_OK; |
---|
1226 | 1411 | |
---|
.. | .. |
---|
1233 | 1418 | /* Request HT Avail */ |
---|
1234 | 1419 | clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; |
---|
1235 | 1420 | |
---|
1236 | | - |
---|
| 1421 | +#ifdef BCMSPI |
---|
| 1422 | + dhdsdio_wkwlan(bus, TRUE); |
---|
| 1423 | +#endif /* BCMSPI */ |
---|
1237 | 1424 | |
---|
1238 | 1425 | bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); |
---|
1239 | 1426 | if (err) { |
---|
.. | .. |
---|
1242 | 1429 | DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); |
---|
1243 | 1430 | } |
---|
1244 | 1431 | |
---|
1245 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |
---|
| 1432 | +#ifdef OEM_ANDROID |
---|
1246 | 1433 | else if (ht_avail_error == HT_AVAIL_ERROR_MAX) { |
---|
| 1434 | + bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR; |
---|
1247 | 1435 | dhd_os_send_hang_message(bus->dhd); |
---|
1248 | 1436 | } |
---|
1249 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */ |
---|
| 1437 | +#endif /* OEM_ANDROID */ |
---|
1250 | 1438 | return BCME_ERROR; |
---|
1251 | 1439 | } else { |
---|
1252 | 1440 | ht_avail_error = 0; |
---|
1253 | 1441 | } |
---|
1254 | | - |
---|
1255 | 1442 | |
---|
1256 | 1443 | /* Check current status */ |
---|
1257 | 1444 | clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
.. | .. |
---|
1286 | 1473 | bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); |
---|
1287 | 1474 | } |
---|
1288 | 1475 | } |
---|
1289 | | - |
---|
| 1476 | +#ifndef BCMSDIOLITE |
---|
1290 | 1477 | /* Otherwise, wait here (polling) for HT Avail */ |
---|
1291 | 1478 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { |
---|
1292 | 1479 | SPINWAIT_SLEEP(sdioh_spinwait_sleep, |
---|
.. | .. |
---|
1303 | 1490 | __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl)); |
---|
1304 | 1491 | return BCME_ERROR; |
---|
1305 | 1492 | } |
---|
1306 | | - |
---|
| 1493 | +#endif /* BCMSDIOLITE */ |
---|
1307 | 1494 | /* Mark clock available */ |
---|
1308 | 1495 | bus->clkstate = CLK_AVAIL; |
---|
1309 | 1496 | DHD_INFO(("CLKCTL: turned ON\n")); |
---|
.. | .. |
---|
1346 | 1533 | return BCME_ERROR; |
---|
1347 | 1534 | } |
---|
1348 | 1535 | } |
---|
| 1536 | +#ifdef BCMSPI |
---|
| 1537 | + dhdsdio_wkwlan(bus, FALSE); |
---|
| 1538 | +#endif /* BCMSPI */ |
---|
| 1539 | + } |
---|
| 1540 | + return BCME_OK; |
---|
| 1541 | +} |
---|
| 1542 | + |
---|
| 1543 | +/* Change SD1/SD4 bus mode */ |
---|
| 1544 | +static int |
---|
| 1545 | +dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode) |
---|
| 1546 | +{ |
---|
| 1547 | + int err; |
---|
| 1548 | + |
---|
| 1549 | + err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, |
---|
| 1550 | + &sd_mode, sizeof(sd_mode), TRUE); |
---|
| 1551 | + if (err) { |
---|
| 1552 | + DHD_ERROR(("%s: error changing sd_mode: %d\n", |
---|
| 1553 | + __FUNCTION__, err)); |
---|
| 1554 | + return BCME_ERROR; |
---|
1349 | 1555 | } |
---|
1350 | 1556 | return BCME_OK; |
---|
1351 | 1557 | } |
---|
.. | .. |
---|
1354 | 1560 | static int |
---|
1355 | 1561 | dhdsdio_sdclk(dhd_bus_t *bus, bool on) |
---|
1356 | 1562 | { |
---|
| 1563 | +#ifndef BCMSPI |
---|
1357 | 1564 | int err; |
---|
1358 | 1565 | int32 iovalue; |
---|
1359 | 1566 | |
---|
.. | .. |
---|
1371 | 1578 | return BCME_ERROR; |
---|
1372 | 1579 | } |
---|
1373 | 1580 | |
---|
1374 | | - iovalue = bus->sd_mode; |
---|
1375 | | - err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, |
---|
1376 | | - &iovalue, sizeof(iovalue), TRUE); |
---|
1377 | | - if (err) { |
---|
1378 | | - DHD_ERROR(("%s: error changing sd_mode: %d\n", |
---|
1379 | | - __FUNCTION__, err)); |
---|
1380 | | - return BCME_ERROR; |
---|
1381 | | - } |
---|
1382 | 1581 | } else if (bus->idleclock != DHD_IDLE_ACTIVE) { |
---|
1383 | 1582 | /* Restore clock speed */ |
---|
1384 | 1583 | iovalue = bus->sd_divisor; |
---|
.. | .. |
---|
1399 | 1598 | return BCME_ERROR; |
---|
1400 | 1599 | } |
---|
1401 | 1600 | if (bus->idleclock == DHD_IDLE_STOP) { |
---|
1402 | | - if (sd1idle) { |
---|
1403 | | - /* Change to SD1 mode and turn off clock */ |
---|
1404 | | - iovalue = 1; |
---|
1405 | | - err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, |
---|
1406 | | - &iovalue, sizeof(iovalue), TRUE); |
---|
1407 | | - if (err) { |
---|
1408 | | - DHD_ERROR(("%s: error changing sd_clock: %d\n", |
---|
1409 | | - __FUNCTION__, err)); |
---|
1410 | | - return BCME_ERROR; |
---|
1411 | | - } |
---|
1412 | | - } |
---|
1413 | | - |
---|
1414 | 1601 | iovalue = 0; |
---|
1415 | 1602 | err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, |
---|
1416 | 1603 | &iovalue, sizeof(iovalue), TRUE); |
---|
.. | .. |
---|
1432 | 1619 | } |
---|
1433 | 1620 | bus->clkstate = CLK_NONE; |
---|
1434 | 1621 | } |
---|
| 1622 | +#else /* BCMSPI */ |
---|
| 1623 | +#endif /* !BCMSPI */ |
---|
1435 | 1624 | |
---|
1436 | 1625 | return BCME_OK; |
---|
1437 | 1626 | } |
---|
.. | .. |
---|
1476 | 1665 | break; |
---|
1477 | 1666 | |
---|
1478 | 1667 | case CLK_SDONLY: |
---|
| 1668 | + |
---|
| 1669 | +#ifdef BT_OVER_SDIO |
---|
| 1670 | + /* |
---|
| 1671 | + * If the request is to switch off Back plane clock, |
---|
| 1672 | + * confirm that BT is inactive before doing so. |
---|
| 1673 | + * If this call had come from Non Watchdog context any way |
---|
| 1674 | + * the Watchdog would switch off the clock again when |
---|
| 1675 | + * nothing is to be done & Bt has finished using the bus. |
---|
| 1676 | + */ |
---|
| 1677 | + if (bus->bt_use_count != 0) { |
---|
| 1678 | + DHD_INFO(("%s(): Req CLK_SDONLY, BT is active %d not switching off \r\n", |
---|
| 1679 | + __FUNCTION__, bus->bt_use_count)); |
---|
| 1680 | + ret = BCME_OK; |
---|
| 1681 | + dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); |
---|
| 1682 | + break; |
---|
| 1683 | + } |
---|
| 1684 | + |
---|
| 1685 | + DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n", |
---|
| 1686 | + __FUNCTION__)); |
---|
| 1687 | +#endif /* BT_OVER_SDIO */ |
---|
| 1688 | + |
---|
1479 | 1689 | /* Remove HT request, or bring up SD clock */ |
---|
1480 | 1690 | if (bus->clkstate == CLK_NONE) |
---|
1481 | 1691 | ret = dhdsdio_sdclk(bus, TRUE); |
---|
.. | .. |
---|
1490 | 1700 | break; |
---|
1491 | 1701 | |
---|
1492 | 1702 | case CLK_NONE: |
---|
| 1703 | + |
---|
| 1704 | +#ifdef BT_OVER_SDIO |
---|
| 1705 | + /* |
---|
| 1706 | + * If the request is to switch off Back plane clock, |
---|
| 1707 | + * confirm that BT is inactive before doing so. |
---|
| 1708 | + * If this call had come from Non Watchdog context any way |
---|
| 1709 | + * the Watchdog would switch off the clock again when |
---|
| 1710 | + * nothing is to be done & Bt has finished using the bus. |
---|
| 1711 | + */ |
---|
| 1712 | + if (bus->bt_use_count != 0) { |
---|
| 1713 | + DHD_INFO(("%s(): Request CLK_NONE BT is active %d not switching off \r\n", |
---|
| 1714 | + __FUNCTION__, bus->bt_use_count)); |
---|
| 1715 | + ret = BCME_OK; |
---|
| 1716 | + break; |
---|
| 1717 | + } |
---|
| 1718 | + |
---|
| 1719 | + DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n", |
---|
| 1720 | + __FUNCTION__)); |
---|
| 1721 | +#endif /* BT_OVER_SDIO */ |
---|
| 1722 | + |
---|
1493 | 1723 | /* Make sure to remove HT request */ |
---|
1494 | 1724 | if (bus->clkstate == CLK_AVAIL) |
---|
1495 | 1725 | ret = dhdsdio_htclk(bus, FALSE, FALSE); |
---|
1496 | 1726 | /* Now remove the SD clock */ |
---|
1497 | 1727 | ret = dhdsdio_sdclk(bus, FALSE); |
---|
1498 | 1728 | #ifdef DHD_DEBUG |
---|
1499 | | - if (dhd_console_ms == 0) |
---|
| 1729 | + if (bus->dhd->dhd_console_ms == 0) |
---|
1500 | 1730 | #endif /* DHD_DEBUG */ |
---|
1501 | 1731 | if (bus->poll == 0) |
---|
1502 | 1732 | dhd_os_wd_timer(bus->dhd, 0); |
---|
.. | .. |
---|
1516 | 1746 | bcmsdh_info_t *sdh = bus->sdh; |
---|
1517 | 1747 | sdpcmd_regs_t *regs = bus->regs; |
---|
1518 | 1748 | uint retries = 0; |
---|
| 1749 | +#if defined(BCMSDIOH_STD) |
---|
| 1750 | + uint32 sd3_tuning_disable = FALSE; |
---|
| 1751 | +#endif /* BCMSDIOH_STD */ |
---|
1519 | 1752 | |
---|
1520 | 1753 | DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n", |
---|
1521 | 1754 | (sleep ? "SLEEP" : "WAKE"), |
---|
.. | .. |
---|
1531 | 1764 | /* Going to sleep: set the alarm and turn off the lights... */ |
---|
1532 | 1765 | if (sleep) { |
---|
1533 | 1766 | /* Don't sleep if something is pending */ |
---|
1534 | | - if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) |
---|
| 1767 | +#ifdef DHD_USE_IDLECOUNT |
---|
| 1768 | + if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq) || |
---|
| 1769 | + bus->readframes || bus->ctrl_frame_stat) |
---|
| 1770 | +#else |
---|
| 1771 | + if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq)) |
---|
| 1772 | +#endif /* DHD_USE_IDLECOUNT */ |
---|
1535 | 1773 | return BCME_BUSY; |
---|
1536 | 1774 | |
---|
| 1775 | +#ifdef BT_OVER_SDIO |
---|
| 1776 | + /* |
---|
| 1777 | + * The following is the assumption based on which the hook is placed. |
---|
| 1778 | + * From WLAN driver, either from the active contexts OR from the Watchdog contexts |
---|
| 1779 | + * we will be attempting to Go to Sleep. AT that moment if we see that BT is still |
---|
| 1780 | + * actively using the bus, we will return BCME_BUSY from here, but the bus->sleeping |
---|
| 1781 | + * state would not have changed. So the caller can then schedule the Watchdog again |
---|
| 1782 | + * which will come and attempt to sleep at a later point. |
---|
| 1783 | + * |
---|
| 1784 | + * In case if BT is the only one and is the last user, we don't switch off the clock |
---|
| 1785 | + * immediately, we allow the WLAN to decide when to sleep i.e from the watchdog. |
---|
| 1786 | + * Now if the watchdog becomes active and attempts to switch off the clock and if |
---|
| 1787 | + * another WLAN context is active they are any way serialized with sdlock. |
---|
| 1788 | + */ |
---|
| 1789 | + if (bus->bt_use_count != 0) { |
---|
| 1790 | + DHD_INFO(("%s(): Cannot sleep BT is active \r\n", __FUNCTION__)); |
---|
| 1791 | + return BCME_BUSY; |
---|
| 1792 | + } |
---|
| 1793 | +#endif /* !BT_OVER_SDIO */ |
---|
1537 | 1794 | |
---|
1538 | 1795 | if (!SLPAUTO_ENAB(bus)) { |
---|
1539 | 1796 | /* Disable SDIO interrupts (no longer interested) */ |
---|
.. | .. |
---|
1554 | 1811 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); |
---|
1555 | 1812 | |
---|
1556 | 1813 | /* Isolate the bus */ |
---|
1557 | | - if (bus->sih->chip != BCM4329_CHIP_ID && |
---|
1558 | | - bus->sih->chip != BCM4319_CHIP_ID) { |
---|
1559 | | - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, |
---|
| 1814 | + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, |
---|
1560 | 1815 | SBSDIO_DEVCTL_PADS_ISO, NULL); |
---|
1561 | | - } |
---|
1562 | 1816 | } else { |
---|
1563 | 1817 | /* Leave interrupts enabled since device can exit sleep and |
---|
1564 | 1818 | * interrupt host |
---|
.. | .. |
---|
1568 | 1822 | |
---|
1569 | 1823 | /* Change state */ |
---|
1570 | 1824 | bus->sleeping = TRUE; |
---|
1571 | | -#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16) |
---|
| 1825 | +#if defined(BCMSDIOH_STD) |
---|
| 1826 | + sd3_tuning_disable = TRUE; |
---|
| 1827 | + err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0, |
---|
| 1828 | + &sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE); |
---|
| 1829 | +#endif /* BCMSDIOH_STD */ |
---|
| 1830 | +#if defined(SUPPORT_P2P_GO_PS) |
---|
1572 | 1831 | wake_up(&bus->bus_sleep); |
---|
1573 | 1832 | #endif /* LINUX && SUPPORT_P2P_GO_PS */ |
---|
1574 | 1833 | } else { |
---|
.. | .. |
---|
1579 | 1838 | |
---|
1580 | 1839 | /* Force pad isolation off if possible (in case power never toggled) */ |
---|
1581 | 1840 | bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); |
---|
1582 | | - |
---|
1583 | 1841 | |
---|
1584 | 1842 | /* Make sure the controller has the bus up */ |
---|
1585 | 1843 | dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); |
---|
.. | .. |
---|
1602 | 1860 | } |
---|
1603 | 1861 | } else { |
---|
1604 | 1862 | err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */); |
---|
| 1863 | +#ifdef BT_OVER_SDIO |
---|
| 1864 | + if (err < 0) { |
---|
| 1865 | + struct net_device *net = NULL; |
---|
| 1866 | + dhd_pub_t *dhd = bus->dhd; |
---|
| 1867 | + net = dhd_idx2net(dhd, 0); |
---|
| 1868 | + if (net != NULL) { |
---|
| 1869 | + DHD_ERROR(("<< WIFI HANG by KSO Enabled failure\n")); |
---|
| 1870 | + dhd_os_sdunlock(dhd); |
---|
| 1871 | + net_os_send_hang_message(net); |
---|
| 1872 | + dhd_os_sdlock(dhd); |
---|
| 1873 | + } else { |
---|
| 1874 | + DHD_ERROR(("<< WIFI HANG Fail because net is NULL\n")); |
---|
| 1875 | + } |
---|
| 1876 | + } |
---|
| 1877 | +#endif /* BT_OVER_SDIO */ |
---|
1605 | 1878 | } |
---|
1606 | 1879 | |
---|
1607 | 1880 | if (err == 0) { |
---|
1608 | 1881 | /* Change state */ |
---|
1609 | 1882 | bus->sleeping = FALSE; |
---|
| 1883 | +#if defined(BCMSDIOH_STD) |
---|
| 1884 | + sd3_tuning_disable = FALSE; |
---|
| 1885 | + err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0, |
---|
| 1886 | + &sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE); |
---|
| 1887 | +#endif /* BCMSDIOH_STD */ |
---|
1610 | 1888 | } |
---|
1611 | 1889 | } |
---|
1612 | 1890 | |
---|
1613 | 1891 | return err; |
---|
1614 | 1892 | } |
---|
1615 | 1893 | |
---|
| 1894 | +#ifdef BT_OVER_SDIO |
---|
| 1895 | +/* |
---|
| 1896 | + * Call this function to Get the Clock running. |
---|
| 1897 | + * Assumes that the caller holds the sdlock. |
---|
| 1898 | + * bus - Pointer to the dhd_bus handle |
---|
| 1899 | + * can_wait - TRUE if the caller can wait until the clock becomes ready |
---|
| 1900 | + * FALSE if the caller cannot wait |
---|
| 1901 | + */ |
---|
| 1902 | +int __dhdsdio_clk_enable(struct dhd_bus *bus, bus_owner_t owner, int can_wait) |
---|
| 1903 | +{ |
---|
| 1904 | + int ret = BCME_ERROR; |
---|
1616 | 1905 | |
---|
1617 | | -#if defined(OOB_INTR_ONLY) |
---|
| 1906 | + BCM_REFERENCE(owner); |
---|
| 1907 | + |
---|
| 1908 | + bus->bt_use_count++; |
---|
| 1909 | + |
---|
| 1910 | + /* |
---|
| 1911 | + * We can call BUS_WAKE, clkctl multiple times, both of the items |
---|
| 1912 | + * have states and if its already ON, no new configuration is done |
---|
| 1913 | + */ |
---|
| 1914 | + |
---|
| 1915 | + /* Wake up the Dongle FW from SR */ |
---|
| 1916 | + BUS_WAKE(bus); |
---|
| 1917 | + |
---|
| 1918 | + /* |
---|
| 1919 | + * Make sure back plane ht clk is on |
---|
| 1920 | + * CLK_AVAIL - Turn On both SD & HT clock |
---|
| 1921 | + */ |
---|
| 1922 | + ret = dhdsdio_clkctl(bus, CLK_AVAIL, can_wait); |
---|
| 1923 | + |
---|
| 1924 | + DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__, |
---|
| 1925 | + bus->bt_use_count)); |
---|
| 1926 | + return ret; |
---|
| 1927 | +} |
---|
| 1928 | + |
---|
| 1929 | +/* |
---|
| 1930 | + * Call this function to relinquish the Clock. |
---|
| 1931 | + * Assumes that the caller holds the sdlock. |
---|
| 1932 | + * bus - Pointer to the dhd_bus handle |
---|
| 1933 | + * can_wait - TRUE if the caller can wait until the clock becomes ready |
---|
| 1934 | + * FALSE if the caller cannot wait |
---|
| 1935 | + */ |
---|
| 1936 | +int __dhdsdio_clk_disable(struct dhd_bus *bus, bus_owner_t owner, int can_wait) |
---|
| 1937 | +{ |
---|
| 1938 | + int ret = BCME_ERROR; |
---|
| 1939 | + |
---|
| 1940 | + BCM_REFERENCE(owner); |
---|
| 1941 | + BCM_REFERENCE(can_wait); |
---|
| 1942 | + |
---|
| 1943 | + if (bus->bt_use_count == 0) { |
---|
| 1944 | + DHD_ERROR(("%s(): Clocks are already turned off \r\n", |
---|
| 1945 | + __FUNCTION__)); |
---|
| 1946 | + return ret; |
---|
| 1947 | + } |
---|
| 1948 | + |
---|
| 1949 | + bus->bt_use_count--; |
---|
| 1950 | + |
---|
| 1951 | + /* |
---|
| 1952 | + * When the SDIO Bus is shared between BT & WLAN, we turn Off the clock |
---|
| 1953 | + * once the last user has relinqushed the same. But there are two schemes |
---|
| 1954 | + * in that too. We consider WLAN as the bus master (even if its not |
---|
| 1955 | + * active). Even when the WLAN is OFF the DHD Watchdog is active. |
---|
| 1956 | + * So this Bus Watchdog is the context whill put the Bus to sleep. |
---|
| 1957 | + * Refer dhd_bus_watchdog function |
---|
| 1958 | + */ |
---|
| 1959 | + |
---|
| 1960 | + ret = BCME_OK; |
---|
| 1961 | + DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__, |
---|
| 1962 | + bus->bt_use_count)); |
---|
| 1963 | + return ret; |
---|
| 1964 | +} |
---|
| 1965 | + |
---|
| 1966 | +void dhdsdio_reset_bt_use_count(struct dhd_bus *bus) |
---|
| 1967 | +{ |
---|
| 1968 | + /* reset bt use count */ |
---|
| 1969 | + bus->bt_use_count = 0; |
---|
| 1970 | +} |
---|
| 1971 | +#endif /* BT_OVER_SDIO */ |
---|
| 1972 | + |
---|
| 1973 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 1974 | +int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) |
---|
| 1975 | +{ |
---|
| 1976 | + int func_blk_size = function_num; |
---|
| 1977 | + int bcmerr = 0; |
---|
| 1978 | + int result; |
---|
| 1979 | + |
---|
| 1980 | + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, |
---|
| 1981 | + sizeof(int), &result, sizeof(int), IOV_GET); |
---|
| 1982 | + |
---|
| 1983 | + if (bcmerr != BCME_OK) { |
---|
| 1984 | + DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num)); |
---|
| 1985 | + return BCME_ERROR; |
---|
| 1986 | + } |
---|
| 1987 | + |
---|
| 1988 | + if (result != block_size) { |
---|
| 1989 | + DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n", |
---|
| 1990 | + __FUNCTION__, function_num, result, block_size)); |
---|
| 1991 | + func_blk_size = function_num << 16 | block_size; |
---|
| 1992 | + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL, |
---|
| 1993 | + 0, &func_blk_size, sizeof(int32), IOV_SET); |
---|
| 1994 | + if (bcmerr != BCME_OK) { |
---|
| 1995 | + DHD_ERROR(("%s: Set F%d Block size error\n", __FUNCTION__, function_num)); |
---|
| 1996 | + return BCME_ERROR; |
---|
| 1997 | + } |
---|
| 1998 | + } |
---|
| 1999 | + |
---|
| 2000 | + return BCME_OK; |
---|
| 2001 | +} |
---|
| 2002 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
| 2003 | + |
---|
| 2004 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
1618 | 2005 | void |
---|
1619 | 2006 | dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) |
---|
1620 | 2007 | { |
---|
1621 | | -#if defined(HW_OOB) |
---|
| 2008 | +#if defined(BCMSPI_ANDROID) |
---|
| 2009 | + bcmsdh_intr_enable(bus->sdh); |
---|
| 2010 | +#elif defined(HW_OOB) |
---|
1622 | 2011 | bcmsdh_enable_hw_oob_intr(bus->sdh, enable); |
---|
1623 | 2012 | #else |
---|
1624 | 2013 | sdpcmd_regs_t *regs = bus->regs; |
---|
.. | .. |
---|
1643 | 2032 | dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); |
---|
1644 | 2033 | #endif /* !defined(HW_OOB) */ |
---|
1645 | 2034 | } |
---|
1646 | | -#endif |
---|
| 2035 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
1647 | 2036 | |
---|
1648 | 2037 | int |
---|
1649 | 2038 | dhd_bus_txdata(struct dhd_bus *bus, void *pkt) |
---|
.. | .. |
---|
1651 | 2040 | int ret = BCME_ERROR; |
---|
1652 | 2041 | osl_t *osh; |
---|
1653 | 2042 | uint datalen, prec; |
---|
| 2043 | +#ifdef REVERSE_AIFSN |
---|
| 2044 | + uint prio; |
---|
| 2045 | +#endif /* REVERSE_AIFSN */ |
---|
1654 | 2046 | #if defined(DHD_TX_DUMP) |
---|
1655 | 2047 | uint8 *dump_data; |
---|
1656 | | - uint16 protocol; |
---|
1657 | 2048 | #endif /* DHD_TX_DUMP */ |
---|
1658 | 2049 | |
---|
1659 | 2050 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
.. | .. |
---|
1681 | 2072 | dhd_ulp_set_path(bus->dhd, DHD_ULP_TX_DATA); |
---|
1682 | 2073 | #endif /* DHD_ULP */ |
---|
1683 | 2074 | |
---|
1684 | | -#if defined(DHD_TX_DUMP) |
---|
| 2075 | +#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP) |
---|
1685 | 2076 | dump_data = PKTDATA(osh, pkt); |
---|
1686 | 2077 | dump_data += 4; /* skip 4 bytes header */ |
---|
1687 | | - protocol = (dump_data[12] << 8) | dump_data[13]; |
---|
1688 | | - |
---|
1689 | | - if (protocol == ETHER_TYPE_802_1X) { |
---|
1690 | | - DHD_ERROR(("ETHER_TYPE_802_1X [TX]: ver %d, type %d, replay %d\n", |
---|
1691 | | - dump_data[14], dump_data[15], dump_data[30])); |
---|
1692 | | - } |
---|
1693 | | -#endif /* DHD_TX_DUMP */ |
---|
1694 | | - |
---|
1695 | | -#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP) |
---|
1696 | 2078 | { |
---|
1697 | 2079 | int i; |
---|
1698 | 2080 | DHD_ERROR(("TX DUMP\n")); |
---|
.. | .. |
---|
1707 | 2089 | #endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */ |
---|
1708 | 2090 | |
---|
1709 | 2091 | prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); |
---|
| 2092 | +#ifdef REVERSE_AIFSN |
---|
| 2093 | + /* Updating the precedence value if aifsn are reverse than 802.11 */ |
---|
| 2094 | + if (bus->dhd->aifsn_reverse) { |
---|
| 2095 | + prio = PKTPRIO(pkt) & PRIOMASK; |
---|
| 2096 | + if (prio == PRIO_8021D_BE) { |
---|
| 2097 | + prec = PRIO2PREC((PRIO_8021D_VI & PRIOMASK)); |
---|
| 2098 | + } else if (prio == PRIO_8021D_VI) { |
---|
| 2099 | + prec = PRIO2PREC((PRIO_8021D_BE & PRIOMASK)); |
---|
| 2100 | + } |
---|
| 2101 | + } |
---|
| 2102 | +#endif /* REVERSE_AIFSN */ |
---|
1710 | 2103 | |
---|
1711 | 2104 | /* Check for existing queue, current flow-control, pending event, or pending clock */ |
---|
1712 | | - if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || |
---|
| 2105 | + if (dhd_deferred_tx || bus->fcstate || pktq_n_pkts_tot(&bus->txq) || bus->dpc_sched || |
---|
1713 | 2106 | (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || |
---|
1714 | 2107 | (bus->clkstate != CLK_AVAIL)) { |
---|
1715 | 2108 | bool deq_ret; |
---|
1716 | 2109 | int pkq_len; |
---|
1717 | 2110 | |
---|
1718 | | - DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq))); |
---|
| 2111 | + DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, |
---|
| 2112 | + pktq_n_pkts_tot(&bus->txq))); |
---|
1719 | 2113 | bus->fcqueued++; |
---|
1720 | 2114 | |
---|
1721 | 2115 | /* Priority based enq */ |
---|
.. | .. |
---|
1743 | 2137 | ret = BCME_OK; |
---|
1744 | 2138 | |
---|
1745 | 2139 | dhd_os_sdlock_txq(bus->dhd); |
---|
1746 | | - pkq_len = pktq_len(&bus->txq); |
---|
| 2140 | + pkq_len = pktq_n_pkts_tot(&bus->txq); |
---|
1747 | 2141 | dhd_os_sdunlock_txq(bus->dhd); |
---|
1748 | 2142 | if (pkq_len >= FCHI) { |
---|
1749 | 2143 | bool wlfc_enabled = FALSE; |
---|
1750 | 2144 | #ifdef PROP_TXSTATUS |
---|
1751 | 2145 | wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) != |
---|
1752 | 2146 | WLFC_UNSUPPORTED); |
---|
1753 | | -#endif |
---|
| 2147 | +#endif // endif |
---|
1754 | 2148 | if (!wlfc_enabled && dhd_doflow) { |
---|
1755 | 2149 | dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); |
---|
1756 | 2150 | } |
---|
.. | .. |
---|
1758 | 2152 | |
---|
1759 | 2153 | #ifdef DHD_DEBUG |
---|
1760 | 2154 | dhd_os_sdlock_txq(bus->dhd); |
---|
1761 | | - if (pktq_plen(&bus->txq, prec) > qcount[prec]) |
---|
1762 | | - qcount[prec] = pktq_plen(&bus->txq, prec); |
---|
| 2155 | + if (pktqprec_n_pkts(&bus->txq, prec) > qcount[prec]) |
---|
| 2156 | + qcount[prec] = pktqprec_n_pkts(&bus->txq, prec); |
---|
1763 | 2157 | dhd_os_sdunlock_txq(bus->dhd); |
---|
1764 | | -#endif |
---|
| 2158 | +#endif // endif |
---|
1765 | 2159 | |
---|
1766 | 2160 | /* Schedule DPC if needed to send queued packet(s) */ |
---|
1767 | 2161 | if (dhd_deferred_tx && !bus->dpc_sched) { |
---|
.. | .. |
---|
1773 | 2167 | |
---|
1774 | 2168 | #ifdef SDTEST |
---|
1775 | 2169 | chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL); |
---|
1776 | | -#endif |
---|
| 2170 | +#endif // endif |
---|
1777 | 2171 | /* Lock: we're about to use shared data/code (and SDIO) */ |
---|
1778 | 2172 | dhd_os_sdlock(bus->dhd); |
---|
1779 | 2173 | |
---|
.. | .. |
---|
1789 | 2183 | else |
---|
1790 | 2184 | bus->dhd->dstats.tx_bytes += datalen; |
---|
1791 | 2185 | |
---|
1792 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { |
---|
| 2186 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 2187 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
1793 | 2188 | bus->activity = FALSE; |
---|
1794 | 2189 | dhdsdio_bussleep(bus, TRUE); |
---|
1795 | 2190 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
1848 | 2243 | frame = (uint8*)PKTDATA(osh, pkt); |
---|
1849 | 2244 | pkt_len = (uint16)PKTLEN(osh, pkt); |
---|
1850 | 2245 | |
---|
1851 | | -#ifdef WLMEDIA_HTSF |
---|
1852 | | - frame = (uint8*)PKTDATA(osh, pkt); |
---|
1853 | | - if (PKTLEN(osh, pkt) >= 100) { |
---|
1854 | | - htsf_ts = (htsfts_t*) (frame + HTSF_HOSTOFFSET + 12); |
---|
1855 | | - if (htsf_ts->magic == HTSFMAGIC) { |
---|
1856 | | - htsf_ts->c20 = get_cycles(); |
---|
1857 | | - htsf_ts->t20 = dhd_get_htsf(bus->dhd->info, 0); |
---|
1858 | | - } |
---|
1859 | | - } |
---|
1860 | | -#endif /* WLMEDIA_HTSF */ |
---|
1861 | 2246 | #ifdef DHD_DEBUG |
---|
1862 | 2247 | if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets)) |
---|
1863 | 2248 | tx_packets[PKTPRIO(pkt)]++; |
---|
.. | .. |
---|
1866 | 2251 | /* align the data pointer, allocate a new packet if there is not enough space (new |
---|
1867 | 2252 | * packet data pointer will be aligned thus no padding will be needed) |
---|
1868 | 2253 | */ |
---|
1869 | | - head_padding = (ulong)frame % DHD_SDALIGN; |
---|
| 2254 | + head_padding = (uintptr)frame % DHD_SDALIGN; |
---|
1870 | 2255 | if (PKTHEADROOM(osh, pkt) < head_padding) { |
---|
1871 | 2256 | head_padding = 0; |
---|
1872 | 2257 | alloc_new_pkt = TRUE; |
---|
1873 | 2258 | } else { |
---|
| 2259 | + /* gSPI expects that hw-header-len is equal to spi-command-len */ |
---|
| 2260 | +#ifndef BCMSPI |
---|
1874 | 2261 | uint cur_chain_total_len; |
---|
1875 | 2262 | int chain_tail_padding = 0; |
---|
1876 | 2263 | |
---|
.. | .. |
---|
1919 | 2306 | */ |
---|
1920 | 2307 | #endif /* DHDENABLE_TAILPAD */ |
---|
1921 | 2308 | tail_padding += chain_tail_padding; |
---|
| 2309 | +#endif /* !BCMSPI */ |
---|
1922 | 2310 | } |
---|
1923 | 2311 | |
---|
1924 | 2312 | DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n", |
---|
.. | .. |
---|
1945 | 2333 | (cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) { |
---|
1946 | 2334 | modulo = cur_total_len % bus->blocksize; |
---|
1947 | 2335 | tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0; |
---|
1948 | | - } |
---|
1949 | | - else { |
---|
| 2336 | + } else { |
---|
1950 | 2337 | modulo = pkt_len % DHD_SDALIGN; |
---|
1951 | 2338 | tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0; |
---|
1952 | 2339 | } |
---|
.. | .. |
---|
2092 | 2479 | if (bus->dhd->dongle_reset) |
---|
2093 | 2480 | return BCME_NOTREADY; |
---|
2094 | 2481 | |
---|
| 2482 | + if (num_pkt <= 0) |
---|
| 2483 | + return BCME_BADARG; |
---|
| 2484 | + |
---|
2095 | 2485 | sdh = bus->sdh; |
---|
2096 | 2486 | osh = bus->dhd->osh; |
---|
2097 | 2487 | /* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */ |
---|
.. | .. |
---|
2202 | 2592 | uint datalen = 0; |
---|
2203 | 2593 | dhd_pub_t *dhd = bus->dhd; |
---|
2204 | 2594 | sdpcmd_regs_t *regs = bus->regs; |
---|
| 2595 | +#ifdef DHD_LOSSLESS_ROAMING |
---|
| 2596 | + uint8 *pktdata; |
---|
| 2597 | + struct ether_header *eh; |
---|
| 2598 | +#ifdef BDC |
---|
| 2599 | + struct bdc_header *bdc_header; |
---|
| 2600 | + uint8 data_offset; |
---|
| 2601 | +#endif // endif |
---|
| 2602 | +#endif /* DHD_LOSSLESS_ROAMING */ |
---|
2205 | 2603 | |
---|
2206 | 2604 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
2207 | 2605 | |
---|
.. | .. |
---|
2214 | 2612 | tx_prec_map = ~bus->flowcontrol; |
---|
2215 | 2613 | #ifdef DHD_LOSSLESS_ROAMING |
---|
2216 | 2614 | tx_prec_map &= dhd->dequeue_prec_map; |
---|
2217 | | -#endif |
---|
| 2615 | +#endif /* DHD_LOSSLESS_ROAMING */ |
---|
2218 | 2616 | for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) { |
---|
2219 | 2617 | int i; |
---|
2220 | 2618 | int num_pkt = 1; |
---|
.. | .. |
---|
2241 | 2639 | ASSERT(0); |
---|
2242 | 2640 | break; |
---|
2243 | 2641 | } |
---|
| 2642 | +#ifdef DHD_LOSSLESS_ROAMING |
---|
| 2643 | + pktdata = (uint8 *)PKTDATA(osh, pkts[i]); |
---|
| 2644 | +#ifdef BDC |
---|
| 2645 | + /* Skip BDC header */ |
---|
| 2646 | + bdc_header = (struct bdc_header *)pktdata; |
---|
| 2647 | + data_offset = bdc_header->dataOffset; |
---|
| 2648 | + pktdata += BDC_HEADER_LEN + (data_offset << 2); |
---|
| 2649 | +#endif // endif |
---|
| 2650 | + eh = (struct ether_header *)pktdata; |
---|
| 2651 | + if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) { |
---|
| 2652 | + uint8 prio = (uint8)PKTPRIO(pkts[i]); |
---|
| 2653 | + |
---|
| 2654 | + /* Restore to original priority for 802.1X packet */ |
---|
| 2655 | + if (prio == PRIO_8021D_NC) { |
---|
| 2656 | + PKTSETPRIO(pkts[i], dhd->prio_8021x); |
---|
| 2657 | +#ifdef BDC |
---|
| 2658 | + /* Restore to original priority in BDC header */ |
---|
| 2659 | + bdc_header->priority = |
---|
| 2660 | + (dhd->prio_8021x & BDC_PRIORITY_MASK); |
---|
| 2661 | +#endif // endif |
---|
| 2662 | + } |
---|
| 2663 | + } |
---|
| 2664 | +#endif /* DHD_LOSSLESS_ROAMING */ |
---|
2244 | 2665 | PKTORPHAN(pkts[i]); |
---|
2245 | 2666 | datalen += PKTLEN(osh, pkts[i]); |
---|
2246 | 2667 | } |
---|
.. | .. |
---|
2269 | 2690 | } |
---|
2270 | 2691 | |
---|
2271 | 2692 | dhd_os_sdlock_txq(bus->dhd); |
---|
2272 | | - txpktqlen = pktq_len(&bus->txq); |
---|
| 2693 | + txpktqlen = pktq_n_pkts_tot(&bus->txq); |
---|
2273 | 2694 | dhd_os_sdunlock_txq(bus->dhd); |
---|
2274 | 2695 | |
---|
2275 | 2696 | /* Do flow-control if needed */ |
---|
.. | .. |
---|
2277 | 2698 | bool wlfc_enabled = FALSE; |
---|
2278 | 2699 | #ifdef PROP_TXSTATUS |
---|
2279 | 2700 | wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED); |
---|
2280 | | -#endif |
---|
| 2701 | +#endif // endif |
---|
2281 | 2702 | if (!wlfc_enabled && dhd_doflow && dhd->txoff) { |
---|
2282 | 2703 | dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); |
---|
2283 | 2704 | } |
---|
.. | .. |
---|
2345 | 2766 | } |
---|
2346 | 2767 | doff += sdpcm_hdrlen; |
---|
2347 | 2768 | |
---|
| 2769 | +#ifndef BCMSPI |
---|
2348 | 2770 | /* Round send length to next SDIO block */ |
---|
2349 | 2771 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { |
---|
2350 | 2772 | uint16 pad = bus->blocksize - (len % bus->blocksize); |
---|
.. | .. |
---|
2353 | 2775 | } else if (len % DHD_SDALIGN) { |
---|
2354 | 2776 | len += DHD_SDALIGN - (len % DHD_SDALIGN); |
---|
2355 | 2777 | } |
---|
| 2778 | +#endif /* BCMSPI */ |
---|
2356 | 2779 | |
---|
2357 | 2780 | /* Satisfy length-alignment requirements */ |
---|
2358 | 2781 | if (forcealign && (len & (ALIGNMENT - 1))) |
---|
2359 | 2782 | len = ROUNDUP(len, ALIGNMENT); |
---|
2360 | 2783 | |
---|
2361 | 2784 | ASSERT(ISALIGNED((uintptr)frame, 2)); |
---|
2362 | | - |
---|
2363 | 2785 | |
---|
2364 | 2786 | /* Need to lock here to protect txseq and SDIO tx calls */ |
---|
2365 | 2787 | dhd_os_sdlock(bus->dhd); |
---|
.. | .. |
---|
2404 | 2826 | if (!TXCTLOK(bus) || !dhd_ulp_f2_ready(bus->dhd, bus->sdh)) |
---|
2405 | 2827 | #else |
---|
2406 | 2828 | if (!TXCTLOK(bus)) |
---|
2407 | | -#endif |
---|
| 2829 | +#endif // endif |
---|
2408 | 2830 | { |
---|
2409 | 2831 | DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n", |
---|
2410 | 2832 | __FUNCTION__, bus->tx_max, bus->tx_seq)); |
---|
.. | .. |
---|
2427 | 2849 | } else { |
---|
2428 | 2850 | bus->dhd->txcnt_timeout++; |
---|
2429 | 2851 | if (!bus->dhd->hang_was_sent) { |
---|
| 2852 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 2853 | + uint32 status, retry = 0; |
---|
| 2854 | + R_SDREG(status, &bus->regs->intstatus, retry); |
---|
| 2855 | + DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n", |
---|
| 2856 | + __FUNCTION__, status)); |
---|
| 2857 | + DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n", |
---|
| 2858 | + __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); |
---|
| 2859 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
2430 | 2860 | DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n", |
---|
2431 | 2861 | __FUNCTION__, bus->dhd->txcnt_timeout)); |
---|
2432 | 2862 | } |
---|
| 2863 | +#ifdef DHD_FW_COREDUMP |
---|
| 2864 | + /* Collect socram dump */ |
---|
| 2865 | + if ((bus->dhd->memdump_enabled) && |
---|
| 2866 | + (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)) { |
---|
| 2867 | + /* collect core dump */ |
---|
| 2868 | + bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_TX; |
---|
| 2869 | + dhd_os_sdunlock(bus->dhd); |
---|
| 2870 | + dhd_bus_mem_dump(bus->dhd); |
---|
| 2871 | + dhd_os_sdlock(bus->dhd); |
---|
| 2872 | + } |
---|
| 2873 | +#endif /* DHD_FW_COREDUMP */ |
---|
2433 | 2874 | ret = -1; |
---|
2434 | 2875 | bus->ctrl_frame_stat = FALSE; |
---|
2435 | 2876 | goto done; |
---|
.. | .. |
---|
2446 | 2887 | } else if (DHD_HDRS_ON()) { |
---|
2447 | 2888 | prhex("TxHdr", frame, MIN(len, 16)); |
---|
2448 | 2889 | } |
---|
2449 | | -#endif |
---|
| 2890 | +#endif // endif |
---|
2450 | 2891 | ret = dhd_bcmsdh_send_buffer(bus, frame, len); |
---|
2451 | | - |
---|
2452 | 2892 | } |
---|
2453 | 2893 | bus->ctrl_frame_stat = FALSE; |
---|
2454 | 2894 | #ifdef DHD_ULP |
---|
.. | .. |
---|
2456 | 2896 | #endif /* DHD_ULP */ |
---|
2457 | 2897 | |
---|
2458 | 2898 | done: |
---|
2459 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { |
---|
| 2899 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 2900 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
2460 | 2901 | bus->activity = FALSE; |
---|
2461 | 2902 | dhdsdio_bussleep(bus, TRUE); |
---|
2462 | 2903 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
2469 | 2910 | else |
---|
2470 | 2911 | bus->dhd->tx_ctlpkts++; |
---|
2471 | 2912 | |
---|
2472 | | - if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) |
---|
| 2913 | + if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) { |
---|
| 2914 | +#ifdef DHD_PM_CONTROL_FROM_FILE |
---|
| 2915 | + if (g_pm_control == TRUE) { |
---|
| 2916 | + return -BCME_ERROR; |
---|
| 2917 | + } else { |
---|
2473 | 2918 | return -ETIMEDOUT; |
---|
2474 | | - |
---|
| 2919 | + } |
---|
| 2920 | +#else |
---|
| 2921 | + return -ETIMEDOUT; |
---|
| 2922 | +#endif /* DHD_PM_CONTROL_FROM_FILE */ |
---|
| 2923 | + } |
---|
2475 | 2924 | if (ret == BCME_NODEVICE) |
---|
2476 | 2925 | err_nodevice++; |
---|
2477 | 2926 | else |
---|
.. | .. |
---|
2503 | 2952 | if (rxlen) { |
---|
2504 | 2953 | DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", |
---|
2505 | 2954 | __FUNCTION__, rxlen, msglen)); |
---|
2506 | | - } else if (timeleft == 0) { |
---|
2507 | | -#ifdef DHD_DEBUG |
---|
2508 | | - uint32 status, retry = 0; |
---|
2509 | | - R_SDREG(status, &bus->regs->intstatus, retry); |
---|
2510 | | - DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n", |
---|
2511 | | - __FUNCTION__, status)); |
---|
2512 | | -#else |
---|
2513 | | - DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__)); |
---|
2514 | | -#endif /* DHD_DEBUG */ |
---|
2515 | | - dhd_os_sdlock(bus->dhd); |
---|
2516 | | - dhdsdio_checkdied(bus, NULL, 0); |
---|
2517 | | - dhd_os_sdunlock(bus->dhd); |
---|
2518 | 2955 | } else { |
---|
2519 | | - DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); |
---|
2520 | | - dhd_os_sdlock(bus->dhd); |
---|
2521 | | - dhdsdio_checkdied(bus, NULL, 0); |
---|
2522 | | - dhd_os_sdunlock(bus->dhd); |
---|
| 2956 | + if (timeleft == 0) { |
---|
| 2957 | +#ifdef DHD_DEBUG |
---|
| 2958 | + uint32 status, retry = 0; |
---|
| 2959 | + R_SDREG(status, &bus->regs->intstatus, retry); |
---|
| 2960 | + DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n", |
---|
| 2961 | + __FUNCTION__, status)); |
---|
| 2962 | +#else |
---|
| 2963 | + DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__)); |
---|
| 2964 | +#endif /* DHD_DEBUG */ |
---|
| 2965 | + if (!bus->dhd->dongle_trap_occured) { |
---|
| 2966 | +#ifdef DHD_FW_COREDUMP |
---|
| 2967 | + bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT; |
---|
| 2968 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 2969 | + dhd_os_sdlock(bus->dhd); |
---|
| 2970 | + dhdsdio_checkdied(bus, NULL, 0); |
---|
| 2971 | + dhd_os_sdunlock(bus->dhd); |
---|
| 2972 | + } |
---|
| 2973 | + } else { |
---|
| 2974 | + DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); |
---|
| 2975 | + if (!bus->dhd->dongle_trap_occured) { |
---|
| 2976 | +#ifdef DHD_FW_COREDUMP |
---|
| 2977 | + bus->dhd->memdump_type = DUMP_TYPE_RESUMED_UNKNOWN; |
---|
| 2978 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 2979 | + dhd_os_sdlock(bus->dhd); |
---|
| 2980 | + dhdsdio_checkdied(bus, NULL, 0); |
---|
| 2981 | + dhd_os_sdunlock(bus->dhd); |
---|
| 2982 | + } |
---|
| 2983 | + } |
---|
| 2984 | +#ifdef DHD_FW_COREDUMP |
---|
| 2985 | + /* Dump the ram image */ |
---|
| 2986 | + if (bus->dhd->memdump_enabled && !bus->dhd->dongle_trap_occured) |
---|
| 2987 | + dhdsdio_mem_dump(bus); |
---|
| 2988 | +#endif /* DHD_FW_COREDUMP */ |
---|
2523 | 2989 | } |
---|
2524 | 2990 | if (timeleft == 0) { |
---|
2525 | 2991 | if (rxlen == 0) |
---|
2526 | 2992 | bus->dhd->rxcnt_timeout++; |
---|
2527 | 2993 | DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__, |
---|
2528 | 2994 | bus->dhd->rxcnt_timeout, rxlen)); |
---|
2529 | | - } |
---|
2530 | | - else |
---|
| 2995 | +#ifdef DHD_FW_COREDUMP |
---|
| 2996 | + /* collect socram dump */ |
---|
| 2997 | + if (bus->dhd->memdump_enabled) { |
---|
| 2998 | + bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_RX; |
---|
| 2999 | + dhd_bus_mem_dump(bus->dhd); |
---|
| 3000 | + } |
---|
| 3001 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 3002 | + } else { |
---|
2531 | 3003 | bus->dhd->rxcnt_timeout = 0; |
---|
| 3004 | + } |
---|
2532 | 3005 | |
---|
2533 | 3006 | if (rxlen) |
---|
2534 | 3007 | bus->dhd->rx_ctlpkts++; |
---|
2535 | 3008 | else |
---|
2536 | 3009 | bus->dhd->rx_ctlerrs++; |
---|
2537 | 3010 | |
---|
2538 | | - if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) |
---|
| 3011 | + if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) { |
---|
| 3012 | +#ifdef DHD_PM_CONTROL_FROM_FILE |
---|
| 3013 | + if (g_pm_control == TRUE) { |
---|
| 3014 | + return -BCME_ERROR; |
---|
| 3015 | + } else { |
---|
| 3016 | + return -ETIMEDOUT; |
---|
| 3017 | + } |
---|
| 3018 | +#else |
---|
2539 | 3019 | return -ETIMEDOUT; |
---|
2540 | | - |
---|
| 3020 | +#endif /* DHD_PM_CONTROL_FROM_FILE */ |
---|
| 3021 | + } |
---|
2541 | 3022 | if (bus->dhd->dongle_trap_occured) |
---|
2542 | 3023 | return -EREMOTEIO; |
---|
2543 | 3024 | |
---|
.. | .. |
---|
2551 | 3032 | IOV_SDREG, |
---|
2552 | 3033 | IOV_SBREG, |
---|
2553 | 3034 | IOV_SDCIS, |
---|
| 3035 | +#ifdef DHD_BUS_MEM_ACCESS |
---|
2554 | 3036 | IOV_MEMBYTES, |
---|
| 3037 | +#endif /* DHD_BUS_MEM_ACCESS */ |
---|
2555 | 3038 | IOV_RAMSIZE, |
---|
2556 | 3039 | IOV_RAMSTART, |
---|
2557 | 3040 | #ifdef DHD_DEBUG |
---|
.. | .. |
---|
2572 | 3055 | IOV_WATERMARK, |
---|
2573 | 3056 | IOV_MESBUSYCTRL, |
---|
2574 | 3057 | #endif /* USE_SDIOFIFO_IOVAR */ |
---|
| 3058 | +#if defined(BT_OVER_SDIO) |
---|
| 3059 | + IOV_SDF3, |
---|
| 3060 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
2575 | 3061 | #ifdef SDTEST |
---|
2576 | 3062 | IOV_PKTGEN, |
---|
2577 | 3063 | IOV_EXTLOOP, |
---|
.. | .. |
---|
2591 | 3077 | IOV_VARS, |
---|
2592 | 3078 | #ifdef SOFTAP |
---|
2593 | 3079 | IOV_FWPATH, |
---|
2594 | | -#endif |
---|
| 3080 | +#endif // endif |
---|
2595 | 3081 | IOV_TXGLOMSIZE, |
---|
2596 | 3082 | IOV_TXGLOMMODE, |
---|
2597 | 3083 | IOV_HANGREPORT, |
---|
2598 | | - IOV_TXINRX_THRES |
---|
| 3084 | + IOV_TXINRX_THRES, |
---|
| 3085 | + IOV_SDIO_SUSPEND |
---|
| 3086 | +#if defined(DEBUGGER) || defined(DHD_DSCOPE) |
---|
| 3087 | + IOV_GDB_SERVER, /**< starts gdb server on given interface */ |
---|
| 3088 | +#endif /* DEBUGGER || DHD_DSCOPE */ |
---|
2599 | 3089 | }; |
---|
2600 | 3090 | |
---|
2601 | 3091 | const bcm_iovar_t dhdsdio_iovars[] = { |
---|
2602 | | - {"intr", IOV_INTR, 0, IOVT_BOOL, 0 }, |
---|
2603 | | - {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 }, |
---|
2604 | | - {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 }, |
---|
2605 | | - {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 }, |
---|
2606 | | - {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 }, |
---|
2607 | | - {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 }, |
---|
2608 | | - {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) }, |
---|
2609 | | - {"ramsize", IOV_RAMSIZE, 0, IOVT_UINT32, 0 }, |
---|
2610 | | - {"ramstart", IOV_RAMSTART, 0, IOVT_UINT32, 0 }, |
---|
2611 | | - {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 }, |
---|
2612 | | - {"socram_state", IOV_SOCRAM_STATE, 0, IOVT_BOOL, 0 }, |
---|
2613 | | - {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 }, |
---|
2614 | | - {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 }, |
---|
2615 | | - {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 }, |
---|
2616 | | - {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 }, |
---|
2617 | | - {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 }, |
---|
2618 | | - {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 }, |
---|
2619 | | - {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 }, |
---|
| 3092 | + {"intr", IOV_INTR, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3093 | + {"sleep", IOV_SLEEP, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3094 | + {"pollrate", IOV_POLLRATE, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3095 | + {"idletime", IOV_IDLETIME, 0, 0, IOVT_INT32, 0 }, |
---|
| 3096 | + {"idleclock", IOV_IDLECLOCK, 0, 0, IOVT_INT32, 0 }, |
---|
| 3097 | + {"sd1idle", IOV_SD1IDLE, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3098 | +#ifdef DHD_BUS_MEM_ACCESS |
---|
| 3099 | + {"membytes", IOV_MEMBYTES, 0, 0, IOVT_BUFFER, 2 * sizeof(int) }, |
---|
| 3100 | +#endif /* DHD_BUS_MEM_ACCESS */ |
---|
| 3101 | + {"ramsize", IOV_RAMSIZE, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3102 | + {"ramstart", IOV_RAMSTART, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3103 | + {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3104 | + {"socram_state", IOV_SOCRAM_STATE, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3105 | + {"vars", IOV_VARS, 0, 0, IOVT_BUFFER, 0 }, |
---|
| 3106 | + {"sdiod_drive", IOV_SDIOD_DRIVE, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3107 | + {"readahead", IOV_READAHEAD, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3108 | + {"sdrxchain", IOV_SDRXCHAIN, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3109 | + {"alignctl", IOV_ALIGNCTL, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3110 | + {"sdalign", IOV_SDALIGN, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3111 | + {"devreset", IOV_DEVRESET, 0, 0, IOVT_BOOL, 0 }, |
---|
2620 | 3112 | #ifdef DHD_DEBUG |
---|
2621 | | - {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, |
---|
2622 | | - {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, |
---|
2623 | | - {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, |
---|
2624 | | - {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 }, |
---|
2625 | | - {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 }, |
---|
2626 | | - {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 }, |
---|
2627 | | - {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 }, |
---|
2628 | | - {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 }, |
---|
| 3113 | + {"sdreg", IOV_SDREG, 0, 0, IOVT_BUFFER, sizeof(sdreg_t) }, |
---|
| 3114 | + {"sbreg", IOV_SBREG, 0, 0, IOVT_BUFFER, sizeof(sdreg_t) }, |
---|
| 3115 | + {"sd_cis", IOV_SDCIS, 0, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, |
---|
| 3116 | + {"forcealign", IOV_FORCEEVEN, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3117 | + {"txbound", IOV_TXBOUND, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3118 | + {"rxbound", IOV_RXBOUND, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3119 | + {"txminmax", IOV_TXMINMAX, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3120 | + {"cpu", IOV_CPU, 0, 0, IOVT_BOOL, 0 }, |
---|
2629 | 3121 | #ifdef DHD_DEBUG |
---|
2630 | | - {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 }, |
---|
2631 | | - {"serial", IOV_SERIALCONS, 0, IOVT_UINT32, 0 }, |
---|
| 3122 | + {"checkdied", IOV_CHECKDIED, 0, 0, IOVT_BUFFER, 0 }, |
---|
| 3123 | + {"serial", IOV_SERIALCONS, 0, 0, IOVT_UINT32, 0 }, |
---|
2632 | 3124 | #endif /* DHD_DEBUG */ |
---|
2633 | 3125 | #endif /* DHD_DEBUG */ |
---|
2634 | 3126 | #ifdef SDTEST |
---|
2635 | | - {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, |
---|
2636 | | - {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, |
---|
| 3127 | + {"extloop", IOV_EXTLOOP, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3128 | + {"pktgen", IOV_PKTGEN, 0, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, |
---|
2637 | 3129 | #endif /* SDTEST */ |
---|
2638 | 3130 | #if defined(USE_SDIOFIFO_IOVAR) |
---|
2639 | | - {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 }, |
---|
2640 | | - {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 }, |
---|
| 3131 | + {"watermark", IOV_WATERMARK, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3132 | + {"mesbusyctrl", IOV_MESBUSYCTRL, 0, 0, IOVT_UINT32, 0 }, |
---|
2641 | 3133 | #endif /* USE_SDIOFIFO_IOVAR */ |
---|
2642 | | - {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 }, |
---|
2643 | | - {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 }, |
---|
2644 | | - {"kso", IOV_KSO, 0, IOVT_UINT32, 0 }, |
---|
2645 | | - {"devsleep", IOV_DEVSLEEP, 0, IOVT_UINT32, 0 }, |
---|
| 3134 | +#if defined(BT_OVER_SDIO) |
---|
| 3135 | + {"sdf3", IOV_SDF3, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3136 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 3137 | + {"devcap", IOV_DEVCAP, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3138 | + {"dngl_isolation", IOV_DONGLEISOLATION, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3139 | + {"kso", IOV_KSO, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3140 | + {"devsleep", IOV_DEVSLEEP, 0, 0, IOVT_UINT32, 0 }, |
---|
2646 | 3141 | #ifdef SOFTAP |
---|
2647 | | - {"fwpath", IOV_FWPATH, 0, IOVT_BUFFER, 0 }, |
---|
2648 | | -#endif |
---|
2649 | | - {"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 }, |
---|
2650 | | - {"fw_hang_report", IOV_HANGREPORT, 0, IOVT_BOOL, 0 }, |
---|
2651 | | - {"txinrx_thres", IOV_TXINRX_THRES, 0, IOVT_INT32, 0 }, |
---|
2652 | | - {NULL, 0, 0, 0, 0 } |
---|
| 3142 | + {"fwpath", IOV_FWPATH, 0, 0, IOVT_BUFFER, 0 }, |
---|
| 3143 | +#endif // endif |
---|
| 3144 | + {"txglomsize", IOV_TXGLOMSIZE, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3145 | + {"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 }, |
---|
| 3146 | + {"txinrx_thres", IOV_TXINRX_THRES, 0, 0, IOVT_INT32, 0 }, |
---|
| 3147 | + {"sdio_suspend", IOV_SDIO_SUSPEND, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3148 | +#if defined(DEBUGGER) || defined(DHD_DSCOPE) |
---|
| 3149 | + {"gdb_server", IOV_GDB_SERVER, 0, 0, IOVT_UINT32, 0 }, |
---|
| 3150 | +#endif /* DEBUGGER || DHD_DSCOPE */ |
---|
| 3151 | + {NULL, 0, 0, 0, 0, 0 } |
---|
2653 | 3152 | }; |
---|
2654 | 3153 | |
---|
2655 | 3154 | static void |
---|
.. | .. |
---|
2670 | 3169 | dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) |
---|
2671 | 3170 | { |
---|
2672 | 3171 | dhd_bus_t *bus = dhdp->bus; |
---|
| 3172 | +#if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS) |
---|
| 3173 | + int i; |
---|
| 3174 | +#endif // endif |
---|
2673 | 3175 | |
---|
2674 | 3176 | bcm_bprintf(strbuf, "Bus SDIO structure:\n"); |
---|
2675 | 3177 | bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", |
---|
2676 | 3178 | bus->hostintmask, bus->intstatus, bus->sdpcm_ver); |
---|
2677 | 3179 | bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n", |
---|
2678 | | - bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, |
---|
| 3180 | + bus->fcstate, pktq_n_pkts_tot(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, |
---|
2679 | 3181 | bus->rxlen, bus->rx_seq); |
---|
2680 | 3182 | bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n", |
---|
2681 | 3183 | bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); |
---|
| 3184 | + |
---|
| 3185 | +#ifdef DHD_WAKE_STATUS |
---|
| 3186 | + bcm_bprintf(strbuf, "wake %u rxwake %u readctrlwake %u\n", |
---|
| 3187 | + bcmsdh_get_total_wake(bus->sdh), bus->wake_counts.rxwake, |
---|
| 3188 | + bus->wake_counts.rcwake); |
---|
| 3189 | +#ifdef DHD_WAKE_RX_STATUS |
---|
| 3190 | + bcm_bprintf(strbuf, " unicast %u multicast %u broadcast %u arp %u\n", |
---|
| 3191 | + bus->wake_counts.rx_ucast, bus->wake_counts.rx_mcast, |
---|
| 3192 | + bus->wake_counts.rx_bcast, bus->wake_counts.rx_arp); |
---|
| 3193 | + bcm_bprintf(strbuf, " multi4 %u multi6 %u icmp6 %u multiother %u\n", |
---|
| 3194 | + bus->wake_counts.rx_multi_ipv4, bus->wake_counts.rx_multi_ipv6, |
---|
| 3195 | + bus->wake_counts.rx_icmpv6, bus->wake_counts.rx_multi_other); |
---|
| 3196 | + bcm_bprintf(strbuf, " icmp6_ra %u, icmp6_na %u, icmp6_ns %u\n", |
---|
| 3197 | + bus->wake_counts.rx_icmpv6_ra, bus->wake_counts.rx_icmpv6_na, |
---|
| 3198 | + bus->wake_counts.rx_icmpv6_ns); |
---|
| 3199 | +#endif /* DHD_WAKE_RX_STATUS */ |
---|
| 3200 | +#ifdef DHD_WAKE_EVENT_STATUS |
---|
| 3201 | + for (i = 0; i < WLC_E_LAST; i++) |
---|
| 3202 | + if (bus->wake_counts.rc_event[i] != 0) |
---|
| 3203 | + bcm_bprintf(strbuf, " %s = %u\n", bcmevent_get_name(i), |
---|
| 3204 | + bus->wake_counts.rc_event[i]); |
---|
| 3205 | + bcm_bprintf(strbuf, "\n"); |
---|
| 3206 | +#endif /* DHD_WAKE_EVENT_STATUS */ |
---|
| 3207 | +#endif /* DHD_WAKE_STATUS */ |
---|
| 3208 | + |
---|
2682 | 3209 | bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n", |
---|
2683 | 3210 | bus->pollrate, bus->pollcnt, bus->regfails); |
---|
2684 | 3211 | |
---|
.. | .. |
---|
2862 | 3389 | else |
---|
2863 | 3390 | dsize = size; |
---|
2864 | 3391 | |
---|
2865 | | - if (dsize > MAX_MEM_BUF) { |
---|
2866 | | - DHD_ERROR(("%s: dsize %d > %d\n", __FUNCTION__, dsize, MAX_MEM_BUF)); |
---|
2867 | | - goto xfer_done; |
---|
2868 | | - } |
---|
2869 | | - |
---|
2870 | 3392 | /* Set the backplane window to include the start address */ |
---|
2871 | 3393 | if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { |
---|
2872 | 3394 | DHD_ERROR(("%s: window change failed\n", __FUNCTION__)); |
---|
.. | .. |
---|
2878 | 3400 | DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", |
---|
2879 | 3401 | __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, |
---|
2880 | 3402 | (address & SBSDIO_SBWINDOW_MASK))); |
---|
2881 | | - if (write) { |
---|
2882 | | - memcpy(bus->membuf, data, dsize); |
---|
2883 | | - } |
---|
2884 | | - if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, bus->membuf, dsize))) { |
---|
| 3403 | + if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) { |
---|
2885 | 3404 | DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__)); |
---|
2886 | 3405 | break; |
---|
2887 | | - } |
---|
2888 | | - if (!write) { |
---|
2889 | | - memcpy(data, bus->membuf, dsize); |
---|
2890 | 3406 | } |
---|
2891 | 3407 | |
---|
2892 | 3408 | /* Adjust for next transfer (if any) */ |
---|
.. | .. |
---|
2919 | 3435 | uint32 addr; |
---|
2920 | 3436 | int rv, i; |
---|
2921 | 3437 | uint32 shaddr = 0; |
---|
| 3438 | + |
---|
| 3439 | + /* This temporary WAR for now */ |
---|
| 3440 | +#if defined(PLATFORM_IMX) |
---|
| 3441 | + return BCME_OK; |
---|
| 3442 | +#endif /* defined(PLATFORM_IMX) */ |
---|
2922 | 3443 | |
---|
2923 | 3444 | if (bus->sih == NULL) { |
---|
2924 | 3445 | if (bus->dhd && bus->dhd->dongle_reset) { |
---|
.. | .. |
---|
2989 | 3510 | return BCME_OK; |
---|
2990 | 3511 | } |
---|
2991 | 3512 | |
---|
| 3513 | +static int |
---|
| 3514 | +dhdsdio_readshared_console(dhd_bus_t *bus) |
---|
| 3515 | +{ |
---|
| 3516 | + uint32 addr; |
---|
| 3517 | + int rv, i; |
---|
| 3518 | + uint32 shaddr = 0; |
---|
| 3519 | + sdpcm_shared_t sh_info; |
---|
| 3520 | + sdpcm_shared_t *sh = &sh_info; |
---|
| 3521 | + int retry = 10; |
---|
| 3522 | + |
---|
| 3523 | + shaddr = bus->dongle_ram_base + bus->ramsize - 4; |
---|
| 3524 | + i = 0; |
---|
| 3525 | + |
---|
| 3526 | + do { |
---|
| 3527 | + /* Read last word in memory to determine address of sdpcm_shared structure */ |
---|
| 3528 | + if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0) |
---|
| 3529 | + return rv; |
---|
| 3530 | + |
---|
| 3531 | + addr = ltoh32(addr); |
---|
| 3532 | + |
---|
| 3533 | + DHD_INFO(("sdpcm_shared address 0x%08X\n", addr)); |
---|
| 3534 | + |
---|
| 3535 | + /* |
---|
| 3536 | + * Check if addr is valid. |
---|
| 3537 | + * NVRAM length at the end of memory should have been overwritten. |
---|
| 3538 | + */ |
---|
| 3539 | + if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) { |
---|
| 3540 | + if ((bus->srmemsize > 0) && (i++ == 0)) { |
---|
| 3541 | + shaddr -= bus->srmemsize; |
---|
| 3542 | + } else { |
---|
| 3543 | + DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", |
---|
| 3544 | + __FUNCTION__, addr)); |
---|
| 3545 | + OSL_SLEEP(50); |
---|
| 3546 | + } |
---|
| 3547 | + } else |
---|
| 3548 | + break; |
---|
| 3549 | + } while (i < retry); |
---|
| 3550 | + |
---|
| 3551 | + if (i == retry) |
---|
| 3552 | + return BCME_ERROR; |
---|
| 3553 | + |
---|
| 3554 | + /* Read hndrte_shared structure */ |
---|
| 3555 | + if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0) |
---|
| 3556 | + return rv; |
---|
| 3557 | + |
---|
| 3558 | + /* Endianness */ |
---|
| 3559 | + sh->console_addr = ltoh32(sh->console_addr); |
---|
| 3560 | + /* load bus console address */ |
---|
| 3561 | + bus->console_addr = sh->console_addr; |
---|
| 3562 | + |
---|
| 3563 | + return BCME_OK; |
---|
| 3564 | +} |
---|
| 3565 | + |
---|
2992 | 3566 | #define CONSOLE_LINE_MAX 192 |
---|
2993 | 3567 | |
---|
2994 | 3568 | #ifdef DHD_DEBUG |
---|
.. | .. |
---|
3000 | 3574 | uint32 n, idx, addr; |
---|
3001 | 3575 | int rv; |
---|
3002 | 3576 | |
---|
| 3577 | + if (!DHD_FWLOG_ON()) |
---|
| 3578 | + return 0; |
---|
| 3579 | + |
---|
3003 | 3580 | /* Don't do anything until FWREADY updates console address */ |
---|
3004 | 3581 | if (bus->console_addr == 0) |
---|
3005 | 3582 | return 0; |
---|
.. | .. |
---|
3009 | 3586 | |
---|
3010 | 3587 | /* Read console log struct */ |
---|
3011 | 3588 | addr = bus->console_addr + OFFSETOF(hnd_cons_t, log); |
---|
| 3589 | + |
---|
| 3590 | + /* Check if console log struct addr has changed */ |
---|
| 3591 | + /* Save the address(Local copy) */ |
---|
| 3592 | + if (c->log_addr != addr) { |
---|
| 3593 | + /* Reset last index pointer */ |
---|
| 3594 | + c->last = 0; |
---|
| 3595 | + /* Re-allocate memory if console address changes */ |
---|
| 3596 | + if (c->buf) { |
---|
| 3597 | + MFREE(bus->dhd->osh, c->buf, c->bufsize); |
---|
| 3598 | + c->buf = NULL; |
---|
| 3599 | + } |
---|
| 3600 | + /* Save new console address */ |
---|
| 3601 | + c->log_addr = addr; |
---|
| 3602 | + } |
---|
| 3603 | + |
---|
3012 | 3604 | if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0) |
---|
3013 | 3605 | return rv; |
---|
3014 | 3606 | |
---|
.. | .. |
---|
3028 | 3620 | /* Skip reading the console buffer if the index pointer has not moved */ |
---|
3029 | 3621 | if (idx == c->last) |
---|
3030 | 3622 | return BCME_OK; |
---|
| 3623 | + |
---|
| 3624 | + DHD_ERROR(("conlog: addr=0x%x, idx=0x%x, last=0x%x \n", c->log.buf, |
---|
| 3625 | + idx, c->last)); |
---|
3031 | 3626 | |
---|
3032 | 3627 | /* Read the console buffer */ |
---|
3033 | 3628 | addr = ltoh32(c->log.buf); |
---|
.. | .. |
---|
3078 | 3673 | char *console_buffer = NULL; |
---|
3079 | 3674 | uint maxstrlen = 256; |
---|
3080 | 3675 | char *str = NULL; |
---|
3081 | | - trap_t tr; |
---|
3082 | | - sdpcm_shared_t sdpcm_shared; |
---|
| 3676 | + sdpcm_shared_t l_sdpcm_shared; |
---|
3083 | 3677 | struct bcmstrbuf strbuf; |
---|
3084 | 3678 | uint32 console_ptr, console_size, console_index; |
---|
3085 | 3679 | uint8 line[CONSOLE_LINE_MAX], ch; |
---|
.. | .. |
---|
3111 | 3705 | goto done; |
---|
3112 | 3706 | } |
---|
3113 | 3707 | |
---|
3114 | | - if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0) |
---|
| 3708 | + if ((bcmerror = dhdsdio_readshared(bus, &l_sdpcm_shared)) < 0) |
---|
3115 | 3709 | goto done; |
---|
3116 | 3710 | |
---|
3117 | 3711 | bcm_binit(&strbuf, data, size); |
---|
3118 | 3712 | |
---|
3119 | 3713 | bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n", |
---|
3120 | | - sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr); |
---|
| 3714 | + l_sdpcm_shared.msgtrace_addr, l_sdpcm_shared.console_addr); |
---|
3121 | 3715 | |
---|
3122 | | - if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { |
---|
| 3716 | + if ((l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { |
---|
3123 | 3717 | /* NOTE: Misspelled assert is intentional - DO NOT FIX. |
---|
3124 | 3718 | * (Avoids conflict with real asserts for programmatic parsing of output.) |
---|
3125 | 3719 | */ |
---|
3126 | 3720 | bcm_bprintf(&strbuf, "Assrt not built in dongle\n"); |
---|
3127 | 3721 | } |
---|
3128 | 3722 | |
---|
3129 | | - if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) { |
---|
| 3723 | + if ((l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) { |
---|
3130 | 3724 | /* NOTE: Misspelled assert is intentional - DO NOT FIX. |
---|
3131 | 3725 | * (Avoids conflict with real asserts for programmatic parsing of output.) |
---|
3132 | 3726 | */ |
---|
3133 | 3727 | bcm_bprintf(&strbuf, "No trap%s in dongle", |
---|
3134 | | - (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) |
---|
| 3728 | + (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) |
---|
3135 | 3729 | ?"/assrt" :""); |
---|
3136 | 3730 | } else { |
---|
3137 | | - if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) { |
---|
| 3731 | + if (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT) { |
---|
3138 | 3732 | /* Download assert */ |
---|
3139 | 3733 | bcm_bprintf(&strbuf, "Dongle assert"); |
---|
3140 | | - if (sdpcm_shared.assert_exp_addr != 0) { |
---|
| 3734 | + if (l_sdpcm_shared.assert_exp_addr != 0) { |
---|
3141 | 3735 | str[0] = '\0'; |
---|
3142 | 3736 | if ((bcmerror = dhdsdio_membytes(bus, FALSE, |
---|
3143 | | - sdpcm_shared.assert_exp_addr, |
---|
| 3737 | + l_sdpcm_shared.assert_exp_addr, |
---|
3144 | 3738 | (uint8 *)str, maxstrlen)) < 0) |
---|
3145 | 3739 | goto done; |
---|
3146 | 3740 | |
---|
.. | .. |
---|
3148 | 3742 | bcm_bprintf(&strbuf, " expr \"%s\"", str); |
---|
3149 | 3743 | } |
---|
3150 | 3744 | |
---|
3151 | | - if (sdpcm_shared.assert_file_addr != 0) { |
---|
| 3745 | + if (l_sdpcm_shared.assert_file_addr != 0) { |
---|
3152 | 3746 | str[0] = '\0'; |
---|
3153 | 3747 | if ((bcmerror = dhdsdio_membytes(bus, FALSE, |
---|
3154 | | - sdpcm_shared.assert_file_addr, |
---|
| 3748 | + l_sdpcm_shared.assert_file_addr, |
---|
3155 | 3749 | (uint8 *)str, maxstrlen)) < 0) |
---|
3156 | 3750 | goto done; |
---|
3157 | 3751 | |
---|
.. | .. |
---|
3159 | 3753 | bcm_bprintf(&strbuf, " file \"%s\"", str); |
---|
3160 | 3754 | } |
---|
3161 | 3755 | |
---|
3162 | | - bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line); |
---|
| 3756 | + bcm_bprintf(&strbuf, " line %d ", l_sdpcm_shared.assert_line); |
---|
3163 | 3757 | } |
---|
3164 | 3758 | |
---|
3165 | | - if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { |
---|
| 3759 | + if (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP) { |
---|
| 3760 | + trap_t *tr = &bus->dhd->last_trap_info; |
---|
3166 | 3761 | bus->dhd->dongle_trap_occured = TRUE; |
---|
3167 | 3762 | if ((bcmerror = dhdsdio_membytes(bus, FALSE, |
---|
3168 | | - sdpcm_shared.trap_addr, |
---|
3169 | | - (uint8*)&tr, sizeof(trap_t))) < 0) |
---|
| 3763 | + l_sdpcm_shared.trap_addr, |
---|
| 3764 | + (uint8*)tr, sizeof(trap_t))) < 0) |
---|
3170 | 3765 | goto done; |
---|
3171 | 3766 | |
---|
3172 | | - bcm_bprintf(&strbuf, |
---|
3173 | | - "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x," |
---|
3174 | | - "lp 0x%x, rpc 0x%x Trap offset 0x%x, " |
---|
3175 | | - "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, " |
---|
3176 | | - "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n", |
---|
3177 | | - ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr), |
---|
3178 | | - ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc), |
---|
3179 | | - ltoh32(sdpcm_shared.trap_addr), |
---|
3180 | | - ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3), |
---|
3181 | | - ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7)); |
---|
| 3767 | + bus->dongle_trap_addr = ltoh32(l_sdpcm_shared.trap_addr); |
---|
3182 | 3768 | |
---|
3183 | | - addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log); |
---|
| 3769 | + dhd_bus_dump_trap_info(bus, &strbuf); |
---|
| 3770 | + |
---|
| 3771 | + addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log); |
---|
3184 | 3772 | if ((rv = dhdsdio_membytes(bus, FALSE, addr, |
---|
3185 | 3773 | (uint8 *)&console_ptr, sizeof(console_ptr))) < 0) |
---|
3186 | 3774 | goto printbuf; |
---|
3187 | 3775 | |
---|
3188 | | - addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size); |
---|
| 3776 | + addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size); |
---|
3189 | 3777 | if ((rv = dhdsdio_membytes(bus, FALSE, addr, |
---|
3190 | 3778 | (uint8 *)&console_size, sizeof(console_size))) < 0) |
---|
3191 | 3779 | goto printbuf; |
---|
3192 | 3780 | |
---|
3193 | | - addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx); |
---|
| 3781 | + addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx); |
---|
3194 | 3782 | if ((rv = dhdsdio_membytes(bus, FALSE, addr, |
---|
3195 | 3783 | (uint8 *)&console_index, sizeof(console_index))) < 0) |
---|
3196 | 3784 | goto printbuf; |
---|
.. | .. |
---|
3215 | 3803 | line[n] = ch; |
---|
3216 | 3804 | } |
---|
3217 | 3805 | |
---|
3218 | | - |
---|
3219 | 3806 | if (n > 0) { |
---|
3220 | 3807 | if (line[n - 1] == '\r') |
---|
3221 | 3808 | n--; |
---|
.. | .. |
---|
3233 | 3820 | } |
---|
3234 | 3821 | |
---|
3235 | 3822 | printbuf: |
---|
3236 | | - if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) { |
---|
| 3823 | + if (l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) { |
---|
3237 | 3824 | DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf)); |
---|
3238 | 3825 | } |
---|
3239 | 3826 | |
---|
3240 | 3827 | #if defined(DHD_FW_COREDUMP) |
---|
3241 | | - if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { |
---|
| 3828 | + if (bus->dhd->memdump_enabled && (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP)) { |
---|
3242 | 3829 | /* Mem dump to a file on device */ |
---|
| 3830 | + bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP; |
---|
| 3831 | + dhd_os_sdunlock(bus->dhd); |
---|
3243 | 3832 | dhdsdio_mem_dump(bus); |
---|
| 3833 | + dhd_os_sdlock(bus->dhd); |
---|
3244 | 3834 | } |
---|
3245 | 3835 | #endif /* #if defined(DHD_FW_COREDUMP) */ |
---|
3246 | 3836 | |
---|
.. | .. |
---|
3256 | 3846 | } |
---|
3257 | 3847 | |
---|
3258 | 3848 | #if defined(DHD_FW_COREDUMP) |
---|
3259 | | -static int |
---|
3260 | | -dhdsdio_mem_dump(dhd_bus_t *bus) |
---|
| 3849 | +int |
---|
| 3850 | +dhd_bus_mem_dump(dhd_pub_t *dhdp) |
---|
3261 | 3851 | { |
---|
3262 | | - int ret = 0; |
---|
3263 | | - int size; /* Full mem size */ |
---|
3264 | | - int start = bus->dongle_ram_base; /* Start address */ |
---|
3265 | | - int read_size = 0; /* Read size of each iteration */ |
---|
3266 | | - uint8 *buf = NULL, *databuf = NULL; |
---|
| 3852 | + dhd_bus_t *bus = dhdp->bus; |
---|
| 3853 | + if (dhdp->busstate == DHD_BUS_SUSPEND) { |
---|
| 3854 | + DHD_ERROR(("%s: Bus is suspend so skip\n", __FUNCTION__)); |
---|
| 3855 | + return 0; |
---|
| 3856 | + } |
---|
| 3857 | + return dhdsdio_mem_dump(bus); |
---|
| 3858 | +} |
---|
3267 | 3859 | |
---|
3268 | | - /* Get full mem size */ |
---|
3269 | | - size = bus->ramsize; |
---|
3270 | | - buf = dhd_get_fwdump_buf(bus->dhd, size); |
---|
3271 | | - if (!buf) { |
---|
3272 | | - printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size); |
---|
3273 | | - return -1; |
---|
| 3860 | +int |
---|
| 3861 | +dhd_bus_get_mem_dump(dhd_pub_t *dhdp) |
---|
| 3862 | +{ |
---|
| 3863 | + if (!dhdp) { |
---|
| 3864 | + DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); |
---|
| 3865 | + return BCME_ERROR; |
---|
3274 | 3866 | } |
---|
3275 | 3867 | |
---|
| 3868 | + return dhdsdio_get_mem_dump(dhdp->bus); |
---|
| 3869 | +} |
---|
| 3870 | + |
---|
| 3871 | +static int |
---|
| 3872 | +dhdsdio_get_mem_dump(dhd_bus_t *bus) |
---|
| 3873 | +{ |
---|
| 3874 | + int ret = BCME_ERROR; |
---|
| 3875 | + int size = bus->ramsize; /* Full mem size */ |
---|
| 3876 | + uint32 start = bus->dongle_ram_base; /* Start address */ |
---|
| 3877 | + uint read_size = 0; /* Read size of each iteration */ |
---|
| 3878 | + uint8 *p_buf = NULL, *databuf = NULL; |
---|
| 3879 | + |
---|
| 3880 | + /* Get full mem size */ |
---|
| 3881 | + p_buf = dhd_get_fwdump_buf(bus->dhd, size); |
---|
| 3882 | + if (!p_buf) { |
---|
| 3883 | + DHD_ERROR(("%s: Out of memory (%d bytes)\n", |
---|
| 3884 | + __FUNCTION__, size)); |
---|
| 3885 | + return BCME_ERROR; |
---|
| 3886 | + } |
---|
| 3887 | + if (!tcm_dump_enable) { |
---|
| 3888 | + dhd_os_sdlock(bus->dhd); |
---|
| 3889 | + } |
---|
| 3890 | + BUS_WAKE(bus); |
---|
| 3891 | + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); |
---|
| 3892 | + |
---|
3276 | 3893 | /* Read mem content */ |
---|
3277 | | - printf("Dump dongle memory"); |
---|
3278 | | - databuf = buf; |
---|
3279 | | - while (size) |
---|
3280 | | - { |
---|
| 3894 | + DHD_ERROR(("Dump dongle memory\n")); |
---|
| 3895 | + databuf = p_buf; |
---|
| 3896 | + while (size) { |
---|
3281 | 3897 | read_size = MIN(MEMBLOCK, size); |
---|
3282 | | - if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size))) |
---|
3283 | | - { |
---|
3284 | | - printf("%s: Error membytes %d\n", __FUNCTION__, ret); |
---|
3285 | | - return -1; |
---|
| 3898 | + ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size); |
---|
| 3899 | + if (ret) { |
---|
| 3900 | + DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret)); |
---|
| 3901 | + ret = BCME_ERROR; |
---|
| 3902 | + break; |
---|
3286 | 3903 | } |
---|
3287 | 3904 | /* Decrement size and increment start address */ |
---|
3288 | 3905 | size -= read_size; |
---|
3289 | 3906 | start += read_size; |
---|
3290 | 3907 | databuf += read_size; |
---|
3291 | 3908 | } |
---|
3292 | | - printf("Done\n"); |
---|
3293 | 3909 | |
---|
3294 | | - /* buf, actually soc_ram free handled in dhd_{free,clear} */ |
---|
3295 | | - if (write_to_file(bus->dhd, buf, bus->ramsize)) |
---|
3296 | | - { |
---|
3297 | | - printf("%s: Error writing to files\n", __FUNCTION__); |
---|
3298 | | - return -1; |
---|
| 3910 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 3911 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
| 3912 | + bus->activity = FALSE; |
---|
| 3913 | + dhdsdio_clkctl(bus, CLK_NONE, TRUE); |
---|
3299 | 3914 | } |
---|
3300 | 3915 | |
---|
3301 | | - return 0; |
---|
| 3916 | + dhd_os_sdunlock(bus->dhd); |
---|
| 3917 | + |
---|
| 3918 | + return ret; |
---|
| 3919 | +} |
---|
| 3920 | + |
---|
| 3921 | +static int |
---|
| 3922 | +dhdsdio_mem_dump(dhd_bus_t *bus) |
---|
| 3923 | +{ |
---|
| 3924 | + dhd_pub_t *dhdp; |
---|
| 3925 | + int ret = BCME_ERROR; |
---|
| 3926 | + |
---|
| 3927 | + dhdp = bus->dhd; |
---|
| 3928 | + if (!dhdp) { |
---|
| 3929 | + DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); |
---|
| 3930 | + return ret; |
---|
| 3931 | + } |
---|
| 3932 | + |
---|
| 3933 | + ret = dhdsdio_get_mem_dump(bus); |
---|
| 3934 | + if (ret) { |
---|
| 3935 | + DHD_ERROR(("%s: failed to get mem dump, err=%d\n", |
---|
| 3936 | + __FUNCTION__, ret)); |
---|
| 3937 | + } else { |
---|
| 3938 | + /* schedule a work queue to perform actual memdump. |
---|
| 3939 | + * dhd_mem_dump() performs the job |
---|
| 3940 | + */ |
---|
| 3941 | + dhd_schedule_memdump(dhdp, dhdp->soc_ram, dhdp->soc_ram_length); |
---|
| 3942 | + /* soc_ram free handled in dhd_{free,clear} */ |
---|
| 3943 | + } |
---|
| 3944 | + |
---|
| 3945 | + return ret; |
---|
3302 | 3946 | } |
---|
3303 | 3947 | #endif /* DHD_FW_COREDUMP */ |
---|
3304 | 3948 | |
---|
.. | .. |
---|
3309 | 3953 | return (dhdsdio_mem_dump(bus)); |
---|
3310 | 3954 | #else |
---|
3311 | 3955 | return -1; |
---|
3312 | | -#endif |
---|
| 3956 | +#endif // endif |
---|
3313 | 3957 | } |
---|
3314 | 3958 | |
---|
3315 | 3959 | int |
---|
.. | .. |
---|
3350 | 3994 | } |
---|
3351 | 3995 | |
---|
3352 | 3996 | #ifdef DHD_DEBUG |
---|
3353 | | - |
---|
3354 | | -#define CC_PLL_CHIPCTRL_SERIAL_ENAB (1 << 24) |
---|
3355 | | -#define CC_CHIPCTRL_JTAG_SEL (1 << 3) |
---|
3356 | | -#define CC_CHIPCTRL_GPIO_SEL (0x3) |
---|
3357 | | -#define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334 (1 << 28) |
---|
3358 | | - |
---|
3359 | 3997 | static int |
---|
3360 | 3998 | dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) |
---|
3361 | 3999 | { |
---|
3362 | 4000 | int int_val; |
---|
3363 | 4001 | uint32 addr, data, uart_enab = 0; |
---|
3364 | | - uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL; |
---|
3365 | | - uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL; |
---|
3366 | 4002 | |
---|
3367 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
3368 | | - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
| 4003 | + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); |
---|
| 4004 | + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); |
---|
3369 | 4005 | *bcmerror = 0; |
---|
3370 | 4006 | |
---|
3371 | 4007 | bcmsdh_reg_write(bus->sdh, addr, 4, 1); |
---|
.. | .. |
---|
3377 | 4013 | if (bcmsdh_regfail(bus->sdh)) { |
---|
3378 | 4014 | *bcmerror = BCME_SDIO_ERROR; |
---|
3379 | 4015 | return -1; |
---|
3380 | | - } |
---|
3381 | | - if (bus->sih->chip == BCM4330_CHIP_ID) { |
---|
3382 | | - uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; |
---|
3383 | | - } |
---|
3384 | | - else if (bus->sih->chip == BCM4334_CHIP_ID || |
---|
3385 | | - bus->sih->chip == BCM43340_CHIP_ID || |
---|
3386 | | - bus->sih->chip == BCM43341_CHIP_ID || |
---|
3387 | | - bus->sih->chip == BCM43342_CHIP_ID || |
---|
3388 | | - 0) { |
---|
3389 | | - if (enable) { |
---|
3390 | | - /* Moved to PMU chipcontrol 1 from 4330 */ |
---|
3391 | | - int_val &= ~gpio_sel; |
---|
3392 | | - int_val |= jtag_sel; |
---|
3393 | | - } else { |
---|
3394 | | - int_val |= gpio_sel; |
---|
3395 | | - int_val &= ~jtag_sel; |
---|
3396 | | - } |
---|
3397 | | - uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334; |
---|
3398 | 4016 | } |
---|
3399 | 4017 | |
---|
3400 | 4018 | if (!set) |
---|
.. | .. |
---|
3408 | 4026 | *bcmerror = BCME_SDIO_ERROR; |
---|
3409 | 4027 | return -1; |
---|
3410 | 4028 | } |
---|
3411 | | - if (bus->sih->chip == BCM4330_CHIP_ID) { |
---|
3412 | | - uint32 chipcontrol; |
---|
3413 | | - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol); |
---|
3414 | | - chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4); |
---|
3415 | | - chipcontrol &= ~jtag_sel; |
---|
3416 | | - if (enable) { |
---|
3417 | | - chipcontrol |= jtag_sel; |
---|
3418 | | - chipcontrol &= ~gpio_sel; |
---|
3419 | | - } |
---|
3420 | | - bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol); |
---|
3421 | | - } |
---|
3422 | 4029 | |
---|
3423 | 4030 | return (int_val & uart_enab); |
---|
3424 | 4031 | } |
---|
3425 | | -#endif |
---|
| 4032 | +#endif // endif |
---|
3426 | 4033 | |
---|
3427 | 4034 | static int |
---|
3428 | 4035 | dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, |
---|
.. | .. |
---|
3442 | 4049 | bcopy(params, &int_val, sizeof(int_val)); |
---|
3443 | 4050 | |
---|
3444 | 4051 | bool_val = (int_val != 0) ? TRUE : FALSE; |
---|
3445 | | - |
---|
3446 | 4052 | |
---|
3447 | 4053 | /* Some ioctls use the bus */ |
---|
3448 | 4054 | dhd_os_sdlock(bus->dhd); |
---|
.. | .. |
---|
3553 | 4159 | sd1idle = bool_val; |
---|
3554 | 4160 | break; |
---|
3555 | 4161 | |
---|
| 4162 | +#ifdef DHD_DEBUG |
---|
| 4163 | + case IOV_GVAL(IOV_CHECKDIED): |
---|
| 4164 | + bcmerror = dhdsdio_checkdied(bus, arg, len); |
---|
| 4165 | + break; |
---|
| 4166 | +#endif /* DHD_DEBUG */ |
---|
3556 | 4167 | |
---|
| 4168 | +#ifdef DHD_BUS_MEM_ACCESS |
---|
3557 | 4169 | case IOV_SVAL(IOV_MEMBYTES): |
---|
3558 | 4170 | case IOV_GVAL(IOV_MEMBYTES): |
---|
3559 | 4171 | { |
---|
.. | .. |
---|
3580 | 4192 | |
---|
3581 | 4193 | DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, |
---|
3582 | 4194 | (set ? "write" : "read"), size, address)); |
---|
3583 | | - |
---|
| 4195 | +#if defined(BT_OVER_SDIO) |
---|
| 4196 | + /* Check if address is within BT range */ |
---|
| 4197 | + if ((address & BTMEM_OFFSET_MASK) == BTMEM_OFFSET) { |
---|
| 4198 | + DHD_INFO(("%s: Access BTMEM, bypass check\n", __FUNCTION__)); |
---|
| 4199 | + } |
---|
| 4200 | + else |
---|
| 4201 | +#endif // endif |
---|
3584 | 4202 | /* check if CR4 */ |
---|
3585 | 4203 | if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { |
---|
3586 | 4204 | /* |
---|
.. | .. |
---|
3642 | 4260 | |
---|
3643 | 4261 | break; |
---|
3644 | 4262 | } |
---|
| 4263 | +#endif /* DHD_BUS_MEM_ACCESS */ |
---|
3645 | 4264 | |
---|
3646 | 4265 | case IOV_GVAL(IOV_RAMSIZE): |
---|
3647 | 4266 | int_val = (int32)bus->ramsize; |
---|
.. | .. |
---|
3697 | 4316 | else |
---|
3698 | 4317 | bus->use_rxchain = bool_val; |
---|
3699 | 4318 | break; |
---|
| 4319 | +#ifndef BCMSPI |
---|
3700 | 4320 | case IOV_GVAL(IOV_ALIGNCTL): |
---|
3701 | 4321 | int_val = (int32)dhd_alignctl; |
---|
3702 | 4322 | bcopy(&int_val, arg, val_size); |
---|
.. | .. |
---|
3705 | 4325 | case IOV_SVAL(IOV_ALIGNCTL): |
---|
3706 | 4326 | dhd_alignctl = bool_val; |
---|
3707 | 4327 | break; |
---|
| 4328 | +#endif /* BCMSPI */ |
---|
3708 | 4329 | |
---|
3709 | 4330 | case IOV_GVAL(IOV_SDALIGN): |
---|
3710 | 4331 | int_val = DHD_SDALIGN; |
---|
.. | .. |
---|
3724 | 4345 | case IOV_GVAL(IOV_SDREG): |
---|
3725 | 4346 | { |
---|
3726 | 4347 | sdreg_t *sd_ptr; |
---|
3727 | | - uint32 addr, size; |
---|
| 4348 | + uintptr addr; |
---|
| 4349 | + uint size; |
---|
3728 | 4350 | |
---|
3729 | 4351 | sd_ptr = (sdreg_t *)params; |
---|
3730 | 4352 | |
---|
3731 | | - addr = (uint32)((ulong)bus->regs + sd_ptr->offset); |
---|
| 4353 | + addr = ((uintptr)bus->regs + sd_ptr->offset); |
---|
3732 | 4354 | size = sd_ptr->func; |
---|
3733 | 4355 | int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); |
---|
3734 | 4356 | if (bcmsdh_regfail(bus->sdh)) |
---|
.. | .. |
---|
3740 | 4362 | case IOV_SVAL(IOV_SDREG): |
---|
3741 | 4363 | { |
---|
3742 | 4364 | sdreg_t *sd_ptr; |
---|
3743 | | - uint32 addr, size; |
---|
| 4365 | + uintptr addr; |
---|
| 4366 | + uint size; |
---|
3744 | 4367 | |
---|
3745 | 4368 | sd_ptr = (sdreg_t *)params; |
---|
3746 | 4369 | |
---|
3747 | | - addr = (uint32)((ulong)bus->regs + sd_ptr->offset); |
---|
| 4370 | + addr = ((uintptr)bus->regs + sd_ptr->offset); |
---|
3748 | 4371 | size = sd_ptr->func; |
---|
3749 | 4372 | bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value); |
---|
3750 | 4373 | if (bcmsdh_regfail(bus->sdh)) |
---|
.. | .. |
---|
3760 | 4383 | |
---|
3761 | 4384 | bcopy(params, &sdreg, sizeof(sdreg)); |
---|
3762 | 4385 | |
---|
3763 | | - addr = SI_ENUM_BASE + sdreg.offset; |
---|
| 4386 | + addr = SI_ENUM_BASE(bus->sih) + sdreg.offset; |
---|
3764 | 4387 | size = sdreg.func; |
---|
3765 | 4388 | int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); |
---|
3766 | 4389 | if (bcmsdh_regfail(bus->sdh)) |
---|
.. | .. |
---|
3776 | 4399 | |
---|
3777 | 4400 | bcopy(params, &sdreg, sizeof(sdreg)); |
---|
3778 | 4401 | |
---|
3779 | | - addr = SI_ENUM_BASE + sdreg.offset; |
---|
| 4402 | + addr = SI_ENUM_BASE(bus->sih) + sdreg.offset; |
---|
3780 | 4403 | size = sdreg.func; |
---|
3781 | 4404 | bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value); |
---|
3782 | 4405 | if (bcmsdh_regfail(bus->sdh)) |
---|
.. | .. |
---|
3833 | 4456 | dhd_txminmax = (uint)int_val; |
---|
3834 | 4457 | break; |
---|
3835 | 4458 | |
---|
| 4459 | +#ifdef DHD_DEBUG |
---|
3836 | 4460 | case IOV_GVAL(IOV_SERIALCONS): |
---|
3837 | 4461 | int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror); |
---|
3838 | 4462 | if (bcmerror != 0) |
---|
.. | .. |
---|
3844 | 4468 | case IOV_SVAL(IOV_SERIALCONS): |
---|
3845 | 4469 | dhd_serialconsole(bus, TRUE, bool_val, &bcmerror); |
---|
3846 | 4470 | break; |
---|
3847 | | - |
---|
3848 | | - |
---|
3849 | 4471 | #endif /* DHD_DEBUG */ |
---|
3850 | 4472 | |
---|
| 4473 | +#endif /* DHD_DEBUG */ |
---|
3851 | 4474 | |
---|
3852 | 4475 | #ifdef SDTEST |
---|
3853 | 4476 | case IOV_GVAL(IOV_EXTLOOP): |
---|
.. | .. |
---|
3894 | 4517 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, |
---|
3895 | 4518 | ((uint8)mesbusyctrl | 0x80), NULL); |
---|
3896 | 4519 | break; |
---|
3897 | | -#endif |
---|
| 4520 | +#endif // endif |
---|
3898 | 4521 | |
---|
| 4522 | +#if defined(BT_OVER_SDIO) |
---|
| 4523 | + case IOV_GVAL(IOV_SDF3): |
---|
| 4524 | + case IOV_SVAL(IOV_SDF3): |
---|
| 4525 | + { |
---|
| 4526 | + uint8 *buf; |
---|
| 4527 | + int ret = BCME_OK; |
---|
| 4528 | + uint size; |
---|
| 4529 | + bool set = (actionid == IOV_SVAL(IOV_SDF3)); |
---|
| 4530 | + ASSERT(plen >= sizeof(int)); |
---|
3899 | 4531 | |
---|
| 4532 | + size = (uint)int_val; |
---|
| 4533 | + /* Generate the actual data pointer */ |
---|
| 4534 | + buf = set ? (uint8*)params + sizeof(int): (uint8*)arg; |
---|
| 4535 | + |
---|
| 4536 | + if (actionid == IOV_SVAL(IOV_SDF3)) { |
---|
| 4537 | + ret = dhd_bcmsdh_send_buf(bus, 0, SDIO_FUNC_3, |
---|
| 4538 | + F2SYNC, buf, size, NULL, NULL, NULL, 1); |
---|
| 4539 | + } else { |
---|
| 4540 | + ret = dhd_bcmsdh_recv_buf(bus, 0, SDIO_FUNC_3, |
---|
| 4541 | + F2SYNC, buf, size, NULL, NULL, NULL); |
---|
| 4542 | + } |
---|
| 4543 | + if (ret != BCME_OK) { |
---|
| 4544 | + bcmerror = BCME_SDIO_ERROR; |
---|
| 4545 | + } |
---|
| 4546 | + break; |
---|
| 4547 | + } |
---|
| 4548 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
3900 | 4549 | case IOV_GVAL(IOV_DONGLEISOLATION): |
---|
3901 | 4550 | int_val = bus->dhd->dongle_isolation; |
---|
3902 | 4551 | bcopy(&int_val, arg, val_size); |
---|
.. | .. |
---|
3914 | 4563 | ASSERT(bus->dhd->osh); |
---|
3915 | 4564 | /* ASSERT(bus->cl_devid); */ |
---|
3916 | 4565 | |
---|
| 4566 | + /* must release sdlock, since devreset also acquires it */ |
---|
| 4567 | + dhd_os_sdunlock(bus->dhd); |
---|
3917 | 4568 | dhd_bus_devreset(bus->dhd, (uint8)bool_val); |
---|
3918 | | - |
---|
| 4569 | + dhd_os_sdlock(bus->dhd); |
---|
3919 | 4570 | break; |
---|
3920 | 4571 | /* |
---|
3921 | 4572 | * softap firmware is updated through module parameter or android private command |
---|
.. | .. |
---|
3977 | 4628 | } |
---|
3978 | 4629 | break; |
---|
3979 | 4630 | |
---|
| 4631 | + case IOV_GVAL(IOV_SDIO_SUSPEND): |
---|
| 4632 | + int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0; |
---|
| 4633 | + bcopy(&int_val, arg, val_size); |
---|
| 4634 | + break; |
---|
| 4635 | + |
---|
| 4636 | + case IOV_SVAL(IOV_SDIO_SUSPEND): |
---|
| 4637 | + if (bool_val) { /* Suspend */ |
---|
| 4638 | + dhdsdio_suspend(bus); |
---|
| 4639 | + } |
---|
| 4640 | + else { /* Resume */ |
---|
| 4641 | + dhdsdio_resume(bus); |
---|
| 4642 | + } |
---|
| 4643 | + break; |
---|
| 4644 | + |
---|
| 4645 | +#if defined(DEBUGGER) || defined(DHD_DSCOPE) |
---|
| 4646 | + case IOV_SVAL(IOV_GDB_SERVER): |
---|
| 4647 | + if (bool_val == TRUE) { |
---|
| 4648 | + debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih)); |
---|
| 4649 | + } else { |
---|
| 4650 | + debugger_close(); |
---|
| 4651 | + } |
---|
| 4652 | + break; |
---|
| 4653 | +#endif /* DEBUGGER || DHD_DSCOPE */ |
---|
| 4654 | + |
---|
3980 | 4655 | default: |
---|
3981 | 4656 | bcmerror = BCME_UNSUPPORTED; |
---|
3982 | 4657 | break; |
---|
3983 | 4658 | } |
---|
3984 | 4659 | |
---|
3985 | 4660 | exit: |
---|
3986 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { |
---|
| 4661 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 4662 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
3987 | 4663 | bus->activity = FALSE; |
---|
3988 | 4664 | dhdsdio_bussleep(bus, TRUE); |
---|
3989 | 4665 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
4006 | 4682 | uint8 *nvram_ularray; |
---|
4007 | 4683 | #endif /* DHD_DEBUG */ |
---|
4008 | 4684 | |
---|
| 4685 | +#define TOKENSIZE 4 |
---|
4009 | 4686 | /* Even if there are no vars are to be written, we still need to set the ramsize. */ |
---|
4010 | 4687 | varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0; |
---|
4011 | | - varaddr = (bus->ramsize - 4) - varsize; |
---|
4012 | | - |
---|
| 4688 | + varaddr = bus->ramsize - varsize - TOKENSIZE; |
---|
4013 | 4689 | varaddr += bus->dongle_ram_base; |
---|
4014 | 4690 | |
---|
4015 | 4691 | if (bus->vars) { |
---|
.. | .. |
---|
4021 | 4697 | } |
---|
4022 | 4698 | } |
---|
4023 | 4699 | |
---|
4024 | | - vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize); |
---|
| 4700 | + vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize + TOKENSIZE); |
---|
4025 | 4701 | if (!vbuffer) |
---|
4026 | 4702 | return BCME_NOMEM; |
---|
4027 | 4703 | |
---|
4028 | | - bzero(vbuffer, varsize); |
---|
| 4704 | + bzero(vbuffer, varsize + TOKENSIZE); |
---|
4029 | 4705 | bcopy(bus->vars, vbuffer, bus->varsz); |
---|
4030 | 4706 | |
---|
| 4707 | + /* |
---|
| 4708 | + * Determine the length token: |
---|
| 4709 | + * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. |
---|
| 4710 | + */ |
---|
| 4711 | + varsizew = varsize / 4; |
---|
| 4712 | + varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); |
---|
| 4713 | + varsizew = htol32(varsizew); |
---|
| 4714 | + |
---|
| 4715 | + DHD_INFO(("length token=0x%08x\n", varsizew)); |
---|
| 4716 | + /* Write the length token to the last word */ |
---|
| 4717 | + bcopy((uint8*)&varsizew, &vbuffer[varsize], 4); |
---|
| 4718 | + |
---|
4031 | 4719 | /* Write the vars list */ |
---|
4032 | | - bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize); |
---|
| 4720 | + bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize + TOKENSIZE); |
---|
| 4721 | + if (bcmerror) { |
---|
| 4722 | + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
| 4723 | + __FUNCTION__, bcmerror, varsize, varaddr)); |
---|
| 4724 | + return bcmerror; |
---|
| 4725 | + } |
---|
| 4726 | + |
---|
4033 | 4727 | #ifdef DHD_DEBUG |
---|
4034 | 4728 | /* Verify NVRAM bytes */ |
---|
4035 | 4729 | DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize)); |
---|
4036 | 4730 | nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize); |
---|
4037 | | - if (!nvram_ularray) |
---|
| 4731 | + if (!nvram_ularray) { |
---|
| 4732 | + MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE); |
---|
4038 | 4733 | return BCME_NOMEM; |
---|
| 4734 | + } |
---|
4039 | 4735 | |
---|
4040 | 4736 | /* Upload image to verify downloaded contents. */ |
---|
4041 | 4737 | memset(nvram_ularray, 0xaa, varsize); |
---|
.. | .. |
---|
4055 | 4751 | |
---|
4056 | 4752 | MFREE(bus->dhd->osh, nvram_ularray, varsize); |
---|
4057 | 4753 | #endif /* DHD_DEBUG */ |
---|
| 4754 | + MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE); |
---|
4058 | 4755 | |
---|
4059 | | - MFREE(bus->dhd->osh, vbuffer, varsize); |
---|
4060 | 4756 | } |
---|
4061 | 4757 | |
---|
4062 | 4758 | phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize; |
---|
.. | .. |
---|
4068 | 4764 | phys_size, bus->ramsize)); |
---|
4069 | 4765 | DHD_INFO(("Vars are at %d, orig varsize is %d\n", |
---|
4070 | 4766 | varaddr, varsize)); |
---|
4071 | | - varsize = ((phys_size - 4) - varaddr); |
---|
4072 | | - |
---|
4073 | | - /* |
---|
4074 | | - * Determine the length token: |
---|
4075 | | - * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. |
---|
4076 | | - */ |
---|
4077 | | - if (bcmerror) { |
---|
4078 | | - varsizew = 0; |
---|
4079 | | - } else { |
---|
4080 | | - varsizew = varsize / 4; |
---|
4081 | | - varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); |
---|
4082 | | - varsizew = htol32(varsizew); |
---|
4083 | | - } |
---|
4084 | | - |
---|
4085 | | - DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew)); |
---|
4086 | | - |
---|
4087 | | - /* Write the length token to the last word */ |
---|
4088 | | - bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4), |
---|
4089 | | - (uint8*)&varsizew, 4); |
---|
4090 | 4767 | |
---|
4091 | 4768 | return bcmerror; |
---|
| 4769 | +} |
---|
| 4770 | + |
---|
| 4771 | +bool |
---|
| 4772 | +dhd_bus_is_multibp_capable(struct dhd_bus *bus) |
---|
| 4773 | +{ |
---|
| 4774 | + return MULTIBP_CAP(bus->sih); |
---|
4092 | 4775 | } |
---|
4093 | 4776 | |
---|
4094 | 4777 | static int |
---|
.. | .. |
---|
4097 | 4780 | uint retries; |
---|
4098 | 4781 | int bcmerror = 0; |
---|
4099 | 4782 | int foundcr4 = 0; |
---|
| 4783 | + hs_addrs_t bl_hs_addrs = {NULL, NULL}; |
---|
4100 | 4784 | |
---|
4101 | 4785 | if (!bus->sih) |
---|
4102 | 4786 | return BCME_ERROR; |
---|
| 4787 | + |
---|
| 4788 | + if (bus->secureboot) { |
---|
| 4789 | + /* Host bootloader handshake TCM/REGS addresses init */ |
---|
| 4790 | + bcmerror = dhdsdio_dongle_host_get_handshake_address(bus, &bl_hs_addrs); |
---|
| 4791 | + if (bcmerror) { |
---|
| 4792 | + DHD_ERROR(("%s: REGS/TCM addresses not initialized\n", __FUNCTION__)); |
---|
| 4793 | + goto fail; |
---|
| 4794 | + } |
---|
| 4795 | + } |
---|
| 4796 | + |
---|
4103 | 4797 | /* To enter download state, disable ARM and reset SOCRAM. |
---|
4104 | 4798 | * To exit download state, simply reset ARM (default is RAM boot). |
---|
4105 | 4799 | */ |
---|
.. | .. |
---|
4165 | 4859 | * [next] Download firmware |
---|
4166 | 4860 | * [done at else] Populate the reset vector |
---|
4167 | 4861 | * [done at else] Remove ARM halt |
---|
4168 | | - */ |
---|
4169 | | - /* Halt ARM & remove reset */ |
---|
4170 | | - si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT); |
---|
| 4862 | + */ |
---|
| 4863 | + if (bus->secureboot) { |
---|
| 4864 | + /* Skip ARM halt and reset in case of security bootloader */ |
---|
| 4865 | + |
---|
| 4866 | + /* Bootloader host pre handshake function */ |
---|
| 4867 | + if ((bcmerror = dhdsdio_dongle_host_pre_handshake |
---|
| 4868 | + (bus, &bl_hs_addrs))) { |
---|
| 4869 | + DHD_ERROR(("%s: error %d dongle host pre handshake\n", |
---|
| 4870 | + __FUNCTION__, bcmerror)); |
---|
| 4871 | + goto fail; |
---|
| 4872 | + } |
---|
| 4873 | + DHD_ERROR(("%s: dongle host pre handshake successful, dl FW\n", |
---|
| 4874 | + __FUNCTION__)); |
---|
| 4875 | + |
---|
| 4876 | + /* This is necessary for console buffer initialization */ |
---|
| 4877 | + /* Read SDIO shared structure here */ |
---|
| 4878 | + if ((bcmerror = dhdsdio_readshared_console(bus)) < 0) { |
---|
| 4879 | + DHD_ERROR(("%s: Shared region not initialized\n", |
---|
| 4880 | + __FUNCTION__)); |
---|
| 4881 | + } |
---|
| 4882 | +#ifdef DHD_DEBUG |
---|
| 4883 | + /* Console buffer read - First pass */ |
---|
| 4884 | + if ((bcmerror = dhdsdio_readconsole(bus)) < 0) { |
---|
| 4885 | + DHD_ERROR(("%s: First pass console buffer read failed\n", |
---|
| 4886 | + __FUNCTION__)); |
---|
| 4887 | + } |
---|
| 4888 | +#endif /* DHD_DEBUG */ |
---|
| 4889 | + } else { |
---|
| 4890 | + /* Halt ARM & remove reset */ |
---|
| 4891 | + si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT); |
---|
| 4892 | + } |
---|
4171 | 4893 | } |
---|
4172 | 4894 | } else { |
---|
4173 | 4895 | if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { |
---|
.. | .. |
---|
4193 | 4915 | */ |
---|
4194 | 4916 | if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) |
---|
4195 | 4917 | dhdsdio_devram_remap(bus, TRUE); |
---|
4196 | | - |
---|
| 4918 | +#ifdef BCMSDIOLITE |
---|
| 4919 | + if (!si_setcore(bus->sih, CC_CORE_ID, 0)) { |
---|
| 4920 | + DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__)); |
---|
| 4921 | + bcmerror = BCME_ERROR; |
---|
| 4922 | + goto fail; |
---|
| 4923 | + } |
---|
| 4924 | +#else |
---|
4197 | 4925 | if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && |
---|
4198 | 4926 | !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { |
---|
4199 | 4927 | DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); |
---|
4200 | 4928 | bcmerror = BCME_ERROR; |
---|
4201 | 4929 | goto fail; |
---|
4202 | 4930 | } |
---|
| 4931 | +#endif // endif |
---|
4203 | 4932 | W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); |
---|
4204 | | - |
---|
4205 | 4933 | |
---|
4206 | 4934 | if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && |
---|
4207 | 4935 | !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { |
---|
.. | .. |
---|
4210 | 4938 | goto fail; |
---|
4211 | 4939 | } |
---|
4212 | 4940 | } else { |
---|
| 4941 | + if (bus->secureboot) { |
---|
| 4942 | +#ifdef DHD_DEBUG |
---|
| 4943 | + /* Console buffer read - Second pass */ |
---|
| 4944 | + if ((bcmerror = dhdsdio_readconsole(bus)) < 0) { |
---|
| 4945 | + DHD_ERROR(("%s: Second pass console buffer read failed\n", |
---|
| 4946 | + __FUNCTION__)); |
---|
| 4947 | + } |
---|
| 4948 | +#endif /* DHD_DEBUG */ |
---|
| 4949 | + /* FW and NVRAM download done notification to bootloader */ |
---|
| 4950 | + if ((bcmerror = dhdsdio_dongle_host_post_handshake(bus, |
---|
| 4951 | + &bl_hs_addrs))) { |
---|
| 4952 | + DHD_ERROR(("%s: error %d dongle host post handshake\n", |
---|
| 4953 | + __FUNCTION__, bcmerror)); |
---|
| 4954 | + goto fail; |
---|
| 4955 | + } |
---|
| 4956 | + DHD_ERROR(("%s: FW download successful\n", __FUNCTION__)); |
---|
| 4957 | + |
---|
| 4958 | + /* |
---|
| 4959 | + * Check signature validation function |
---|
| 4960 | + * D2H_VALDN_DONE bit will be set in the following cases: |
---|
| 4961 | + * 1. Open mode: when a signature is not sent |
---|
| 4962 | + * 2. Secure mode: when a valid signature is sent |
---|
| 4963 | + * Write vars and nvram download only if the D2H_VALDN_DONE |
---|
| 4964 | + * bit has been set |
---|
| 4965 | + */ |
---|
| 4966 | + if ((bcmerror = dhdsdio_dongle_host_chk_validation(bus, |
---|
| 4967 | + &bl_hs_addrs))) { |
---|
| 4968 | + DHD_ERROR(("%s: error %d dongle host validation\n", |
---|
| 4969 | + __FUNCTION__, bcmerror)); |
---|
| 4970 | + goto fail; |
---|
| 4971 | + } |
---|
| 4972 | + } |
---|
| 4973 | + |
---|
4213 | 4974 | /* cr4 has no socram, but tcm's */ |
---|
4214 | 4975 | /* write vars */ |
---|
4215 | 4976 | if ((bcmerror = dhdsdio_write_vars(bus))) { |
---|
4216 | 4977 | DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); |
---|
4217 | 4978 | goto fail; |
---|
4218 | 4979 | } |
---|
4219 | | - |
---|
| 4980 | +#ifdef BCMSDIOLITE |
---|
| 4981 | + if (!si_setcore(bus->sih, CC_CORE_ID, 0)) { |
---|
| 4982 | + DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__)); |
---|
| 4983 | + bcmerror = BCME_ERROR; |
---|
| 4984 | + goto fail; |
---|
| 4985 | + } |
---|
| 4986 | +#else |
---|
4220 | 4987 | if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && |
---|
4221 | 4988 | !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { |
---|
4222 | 4989 | DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); |
---|
4223 | 4990 | bcmerror = BCME_ERROR; |
---|
4224 | 4991 | goto fail; |
---|
4225 | 4992 | } |
---|
| 4993 | +#endif // endif |
---|
4226 | 4994 | W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); |
---|
4227 | 4995 | |
---|
4228 | 4996 | /* switch back to arm core again */ |
---|
.. | .. |
---|
4232 | 5000 | goto fail; |
---|
4233 | 5001 | } |
---|
4234 | 5002 | /* write address 0 with reset instruction */ |
---|
4235 | | - bcmerror = dhdsdio_membytes(bus, TRUE, 0, |
---|
4236 | | - (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr)); |
---|
| 5003 | + /* Except for chips eg. CYW555x0, which runs bootloader */ |
---|
| 5004 | + if (!bus->secureboot) { |
---|
| 5005 | + bcmerror = dhdsdio_membytes(bus, TRUE, 0, |
---|
| 5006 | + (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr)); |
---|
4237 | 5007 | |
---|
4238 | | - if (bcmerror == BCME_OK) { |
---|
4239 | | - uint32 tmp; |
---|
| 5008 | + if (bcmerror == BCME_OK) { |
---|
| 5009 | + uint32 tmp; |
---|
4240 | 5010 | |
---|
4241 | | - /* verify write */ |
---|
4242 | | - bcmerror = dhdsdio_membytes(bus, FALSE, 0, |
---|
4243 | | - (uint8 *)&tmp, sizeof(tmp)); |
---|
| 5011 | + /* verify write */ |
---|
| 5012 | + bcmerror = dhdsdio_membytes(bus, FALSE, 0, (uint8 *)&tmp, |
---|
| 5013 | + sizeof(tmp)); |
---|
4244 | 5014 | |
---|
4245 | | - if (bcmerror == BCME_OK && tmp != bus->resetinstr) { |
---|
4246 | | - DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n", |
---|
4247 | | - __FUNCTION__, bus->resetinstr)); |
---|
4248 | | - DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n", |
---|
4249 | | - __FUNCTION__, tmp)); |
---|
4250 | | - bcmerror = BCME_SDIO_ERROR; |
---|
4251 | | - goto fail; |
---|
| 5015 | + if (bcmerror == BCME_OK && tmp != bus->resetinstr) { |
---|
| 5016 | + DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n", |
---|
| 5017 | + __FUNCTION__, bus->resetinstr)); |
---|
| 5018 | + DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n", |
---|
| 5019 | + __FUNCTION__, tmp)); |
---|
| 5020 | + bcmerror = BCME_SDIO_ERROR; |
---|
| 5021 | + goto fail; |
---|
| 5022 | + } |
---|
4252 | 5023 | } |
---|
4253 | 5024 | } |
---|
4254 | | - |
---|
4255 | | - /* now remove reset and halt and continue to run CR4 */ |
---|
4256 | 5025 | } |
---|
4257 | 5026 | |
---|
4258 | | - si_core_reset(bus->sih, 0, 0); |
---|
| 5027 | + /* now remove reset and halt and continue to run CR4 */ |
---|
| 5028 | + if (bus->secureboot) { |
---|
| 5029 | +#ifdef DHD_DEBUG |
---|
| 5030 | + /* Console buffer read - Final pass */ |
---|
| 5031 | + if ((bcmerror = dhdsdio_readconsole(bus)) < 0) { |
---|
| 5032 | + DHD_ERROR(("%s: Final pass console buffer read failed\n", |
---|
| 5033 | + __FUNCTION__)); |
---|
| 5034 | + } |
---|
| 5035 | +#endif /* DHD_DEBUG */ |
---|
| 5036 | + /* Set write_vars done bit to let BL jump to mainline FW */ |
---|
| 5037 | + if ((bcmerror = dhdsdio_dongle_host_post_varswrite(bus, &bl_hs_addrs))) { |
---|
| 5038 | + DHD_ERROR(("%s: error %d dongle_host_post_varswrite\n", |
---|
| 5039 | + __FUNCTION__, bcmerror)); |
---|
| 5040 | + goto fail; |
---|
| 5041 | + } |
---|
| 5042 | + DHD_ERROR(("%s VARS done bit set, BL can jump to mainline FW\n", |
---|
| 5043 | + __FUNCTION__)); |
---|
| 5044 | + } else { |
---|
| 5045 | + si_core_reset(bus->sih, 0, 0); |
---|
| 5046 | + } |
---|
4259 | 5047 | if (bcmsdh_regfail(bus->sdh)) { |
---|
4260 | 5048 | DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__)); |
---|
4261 | 5049 | bcmerror = BCME_SDIO_ERROR; |
---|
.. | .. |
---|
4269 | 5057 | } |
---|
4270 | 5058 | |
---|
4271 | 5059 | fail: |
---|
| 5060 | + if (bcmerror) { |
---|
| 5061 | + if (bus->secureboot) { |
---|
| 5062 | + /* Read the shared structure to determine console address */ |
---|
| 5063 | + if (dhdsdio_readshared_console(bus) < 0) { |
---|
| 5064 | + DHD_ERROR(("%s: Shared region not initialized\n", |
---|
| 5065 | + __FUNCTION__)); |
---|
| 5066 | + } else { |
---|
| 5067 | +#ifdef DHD_DEBUG |
---|
| 5068 | + /* Console buffer read */ |
---|
| 5069 | + if (dhdsdio_readconsole(bus) < 0) { |
---|
| 5070 | + DHD_ERROR( |
---|
| 5071 | + ("%s: console buffer read failed\n", |
---|
| 5072 | + __FUNCTION__)); |
---|
| 5073 | + } |
---|
| 5074 | +#endif /* DHD_DEBUG */ |
---|
| 5075 | + } |
---|
| 5076 | + } |
---|
| 5077 | + } |
---|
4272 | 5078 | /* Always return to SDIOD core */ |
---|
4273 | 5079 | if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) |
---|
4274 | 5080 | si_setcore(bus->sih, SDIOD_CORE_ID, 0); |
---|
| 5081 | + |
---|
| 5082 | + return bcmerror; |
---|
| 5083 | +} |
---|
| 5084 | + |
---|
| 5085 | +static int |
---|
| 5086 | +dhdsdio_dongle_host_get_handshake_address(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5087 | +{ |
---|
| 5088 | + int bcmerror = BCME_OK; |
---|
| 5089 | + |
---|
| 5090 | +#ifndef HS_IN_TCM |
---|
| 5091 | + addr->d2h = (uint32 *)SDIO_FN1_MSG_D2H_REG0; |
---|
| 5092 | + addr->h2d = (uint32 *)SDIO_FN1_MSG_H2D_REG0; |
---|
| 5093 | +#endif /* HS_IN_TCM */ |
---|
| 5094 | + |
---|
| 5095 | + return bcmerror; |
---|
| 5096 | +} |
---|
| 5097 | + |
---|
| 5098 | +static int |
---|
| 5099 | +dhdsdio_wait_bootloader_ready(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5100 | +{ |
---|
| 5101 | + int bcmerror = BCME_OK; |
---|
| 5102 | + int h2d_reg = 0x00000000; |
---|
| 5103 | + |
---|
| 5104 | + /* Host initialization for dongle to host handshake */ |
---|
| 5105 | + bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5106 | + if (bcmerror) { |
---|
| 5107 | + goto err; |
---|
| 5108 | + } |
---|
| 5109 | + |
---|
| 5110 | + bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h, |
---|
| 5111 | + D2H_READY_SHIFT, D2H_READY_TIMEOUT_MS); |
---|
| 5112 | + |
---|
| 5113 | +err: |
---|
| 5114 | + return bcmerror; |
---|
| 5115 | +} |
---|
| 5116 | + |
---|
| 5117 | +static int |
---|
| 5118 | +dhdsdio_dongle_host_pre_handshake(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5119 | +{ |
---|
| 5120 | + int bcmerror = BCME_OK; |
---|
| 5121 | + int h2d_reg = 0x00000000; |
---|
| 5122 | + |
---|
| 5123 | + /* Set H2D_DL_START indication to dongle that Host shall start FW download */ |
---|
| 5124 | + setbit(&h2d_reg, H2D_DL_START_SHIFT); |
---|
| 5125 | + bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5126 | + |
---|
| 5127 | + return bcmerror; |
---|
| 5128 | +} |
---|
| 5129 | + |
---|
| 5130 | +static int |
---|
| 5131 | +dhdsdio_dongle_host_post_handshake(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5132 | +{ |
---|
| 5133 | + int bcmerror = BCME_OK; |
---|
| 5134 | + int h2d_reg = 0x00000000; |
---|
| 5135 | + |
---|
| 5136 | + /* Reset download start */ |
---|
| 5137 | + clrbit(&h2d_reg, H2D_DL_START_SHIFT); |
---|
| 5138 | + |
---|
| 5139 | + /* download done */ |
---|
| 5140 | + setbit(&h2d_reg, H2D_DL_DONE_SHIFT); |
---|
| 5141 | + bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5142 | + if (bcmerror) { |
---|
| 5143 | + goto err; |
---|
| 5144 | + } |
---|
| 5145 | + |
---|
| 5146 | + bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h, |
---|
| 5147 | + D2H_TRX_HDR_PARSE_DONE_SHIFT, D2H_TRX_HDR_PARSE_DONE_TIMEOUT_MS); |
---|
| 5148 | + |
---|
| 5149 | + if (bcmerror) { |
---|
| 5150 | + /* Host notification to bootloader to get reset on error */ |
---|
| 5151 | + dhdsdio_handshake_msg_reg_read(bus, addr->h2d, &h2d_reg); |
---|
| 5152 | + setbit(&h2d_reg, H2D_BL_RESET_ON_ERROR_SHIFT); |
---|
| 5153 | + dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5154 | + } |
---|
| 5155 | + |
---|
| 5156 | +err: |
---|
| 5157 | + return bcmerror; |
---|
| 5158 | +} |
---|
| 5159 | + |
---|
| 5160 | +static int |
---|
| 5161 | +dhdsdio_dongle_host_chk_validation(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5162 | +{ |
---|
| 5163 | + int bcmerror = BCME_OK; |
---|
| 5164 | + uint d2h_reg = 0x00000000; |
---|
| 5165 | + uint h2d_reg = 0x00000000; |
---|
| 5166 | + |
---|
| 5167 | + setbit(&h2d_reg, D2H_VALDN_DONE_SHIFT); |
---|
| 5168 | + bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h, |
---|
| 5169 | + D2H_VALDN_DONE_SHIFT, D2H_VALDN_DONE_TIMEOUT_MS); |
---|
| 5170 | + if (!bcmerror) { |
---|
| 5171 | + |
---|
| 5172 | + bcmerror = dhdsdio_handshake_msg_reg_read(bus, addr->d2h, &d2h_reg); |
---|
| 5173 | + if (!bcmerror) { |
---|
| 5174 | + |
---|
| 5175 | + if (isset(&d2h_reg, D2H_VALDN_RESULT_SHIFT)) { |
---|
| 5176 | + DHD_ERROR(("%s: TRX img validation check successful\n", |
---|
| 5177 | + __FUNCTION__)); |
---|
| 5178 | + } else { |
---|
| 5179 | + DHD_ERROR(("%s: TRX img validation check failed\n", __FUNCTION__)); |
---|
| 5180 | + bcmerror = BCME_ERROR; |
---|
| 5181 | + } |
---|
| 5182 | + } |
---|
| 5183 | + } |
---|
| 5184 | + |
---|
| 5185 | + if (bcmerror) { |
---|
| 5186 | + /* Host notification to bootloader to get reset on error |
---|
| 5187 | + * To avoid the race condition betweeen host and dongle |
---|
| 5188 | + */ |
---|
| 5189 | + dhdsdio_handshake_msg_reg_read(bus, addr->h2d, &h2d_reg); |
---|
| 5190 | + setbit(&h2d_reg, H2D_BL_RESET_ON_ERROR_SHIFT); |
---|
| 5191 | + dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5192 | + } |
---|
| 5193 | + |
---|
| 5194 | + return bcmerror; |
---|
| 5195 | +} |
---|
| 5196 | + |
---|
| 5197 | +static int |
---|
| 5198 | +dhdsdio_dongle_host_post_varswrite(dhd_bus_t *bus, hs_addrs_t *addr) |
---|
| 5199 | +{ |
---|
| 5200 | + int bcmerror = BCME_OK; |
---|
| 5201 | + uint h2d_reg = 0x00000000; |
---|
| 5202 | + |
---|
| 5203 | + /* Set NVRAM done bit (Download done is already set) */ |
---|
| 5204 | + setbit(&h2d_reg, (H2D_DL_DONE_SHIFT)); |
---|
| 5205 | + setbit(&h2d_reg, (H2D_DL_NVRAM_DONE_SHIFT)); |
---|
| 5206 | + bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg); |
---|
| 5207 | + |
---|
| 5208 | + return bcmerror; |
---|
| 5209 | +} |
---|
| 5210 | + |
---|
| 5211 | +int |
---|
| 5212 | +dhdsdio_dongle_host_pre_wd_reset_sequence(dhd_bus_t *bus) |
---|
| 5213 | +{ |
---|
| 5214 | + uint h2d_reg = 0; |
---|
| 5215 | + volatile void *regs = NULL; |
---|
| 5216 | + int32 bcmerror = BCME_ERROR; |
---|
| 5217 | + |
---|
| 5218 | + regs = (uint32 *)SDIO_FN1_MSG_H2D_REG0; |
---|
| 5219 | + bcmerror = dhdsdio_handshake_msg_reg_write(bus, regs, &h2d_reg); |
---|
| 5220 | + |
---|
| 5221 | + return bcmerror; |
---|
| 5222 | +} |
---|
| 5223 | + |
---|
| 5224 | +static int |
---|
| 5225 | +dhdsdio_handshake_msg_reg_write(dhd_bus_t *bus, volatile void *addr, uint32 *buffer) |
---|
| 5226 | +{ |
---|
| 5227 | + int bcmerror = BCME_OK; |
---|
| 5228 | + |
---|
| 5229 | +#ifndef HS_IN_TCM |
---|
| 5230 | + BCM_REFERENCE(bcmerror); |
---|
| 5231 | + bcmerror = dhdsdio_cfg_write_buffer(bus, buffer, (uint)(uintptr)addr); |
---|
| 5232 | +#endif // endif |
---|
| 5233 | + |
---|
| 5234 | + return bcmerror; |
---|
| 5235 | +} |
---|
| 5236 | + |
---|
| 5237 | +static int |
---|
| 5238 | +dhdsdio_handshake_msg_reg_read(dhd_bus_t *bus, volatile void *addr, uint32 *buffer) |
---|
| 5239 | +{ |
---|
| 5240 | + int bcmerror = BCME_OK; |
---|
| 5241 | + |
---|
| 5242 | +#ifndef HS_IN_TCM |
---|
| 5243 | + BCM_REFERENCE(bcmerror); |
---|
| 5244 | + dhdsdio_cfg_read_buffer(bus, buffer, (uint)(uintptr)addr); |
---|
| 5245 | +#endif // endif |
---|
| 5246 | + |
---|
| 5247 | + return bcmerror; |
---|
| 5248 | +} |
---|
| 5249 | + |
---|
| 5250 | +static int |
---|
| 5251 | +dhdsdio_cfg_write_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset) |
---|
| 5252 | +{ |
---|
| 5253 | + int err = BCME_ERROR; |
---|
| 5254 | + |
---|
| 5255 | + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset, ((*buffer) >> 0) |
---|
| 5256 | + & CFG_WRITE_BYTE_MASK, &err); |
---|
| 5257 | + if (!err) { |
---|
| 5258 | + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+1, ((*buffer) >> 8) |
---|
| 5259 | + & CFG_WRITE_BYTE_MASK, &err); |
---|
| 5260 | + } |
---|
| 5261 | + if (!err) { |
---|
| 5262 | + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+2, ((*buffer) >> 16) |
---|
| 5263 | + & CFG_WRITE_BYTE_MASK, &err); |
---|
| 5264 | + } |
---|
| 5265 | + if (!err) { |
---|
| 5266 | + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+3, ((*buffer) >> 24) |
---|
| 5267 | + & CFG_WRITE_BYTE_MASK, &err); |
---|
| 5268 | + } |
---|
| 5269 | + |
---|
| 5270 | + return err; |
---|
| 5271 | +} |
---|
| 5272 | + |
---|
| 5273 | +static int |
---|
| 5274 | +dhdsdio_cfg_read_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset) |
---|
| 5275 | +{ |
---|
| 5276 | + *buffer = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+0, NULL) << 0; |
---|
| 5277 | + *buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+1, NULL) << 8; |
---|
| 5278 | + *buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+2, NULL) << 16; |
---|
| 5279 | + *buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+3, NULL) << 24; |
---|
| 5280 | + |
---|
| 5281 | + return *buffer; |
---|
| 5282 | +} |
---|
| 5283 | + |
---|
| 5284 | +static int |
---|
| 5285 | +dhdsdio_dongle_host_handshake_spinwait(dhd_bus_t *bus, volatile void *addr, |
---|
| 5286 | + uint32 bitshift, uint32 us) |
---|
| 5287 | +{ |
---|
| 5288 | + uint32 countdown_; |
---|
| 5289 | + uint32 read_addr = 0; |
---|
| 5290 | + int bcmerror = BCME_OK; |
---|
| 5291 | + |
---|
| 5292 | + for (countdown_ = (us) + (HS_POLL_PERIOD_MS - 1U); countdown_ >= HS_POLL_PERIOD_MS; |
---|
| 5293 | + countdown_ -= HS_POLL_PERIOD_MS) { |
---|
| 5294 | + |
---|
| 5295 | + bcmerror = dhdsdio_handshake_msg_reg_read(bus, addr, &read_addr); |
---|
| 5296 | + if (bcmerror) { |
---|
| 5297 | + bcmerror = BCME_ERROR; |
---|
| 5298 | + break; |
---|
| 5299 | + } |
---|
| 5300 | + |
---|
| 5301 | + if (isset(&read_addr, bitshift)) { |
---|
| 5302 | + bcmerror = BCME_OK; |
---|
| 5303 | + break; |
---|
| 5304 | + } |
---|
| 5305 | + |
---|
| 5306 | + OSL_SLEEP(HS_POLL_PERIOD_MS); |
---|
| 5307 | + } |
---|
| 5308 | + |
---|
| 5309 | + if (countdown_ <= HS_POLL_PERIOD_MS) { |
---|
| 5310 | + bcmerror = BCME_NOTREADY; |
---|
| 5311 | + } |
---|
4275 | 5312 | |
---|
4276 | 5313 | return bcmerror; |
---|
4277 | 5314 | } |
---|
.. | .. |
---|
4338 | 5375 | if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32), |
---|
4339 | 5376 | &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { |
---|
4340 | 5377 | bus->blocksize = 0; |
---|
4341 | | - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); |
---|
| 5378 | + DHD_ERROR(("%s: fail on fn %d %s get\n", |
---|
| 5379 | + __FUNCTION__, fnum, "sd_blocksize")); |
---|
4342 | 5380 | } else { |
---|
4343 | | - DHD_INFO(("%s: noted %s update, value now %d\n", |
---|
4344 | | - __FUNCTION__, "sd_blocksize", bus->blocksize)); |
---|
| 5381 | + DHD_INFO(("%s: noted fn %d %s update, value now %d\n", |
---|
| 5382 | + __FUNCTION__, fnum, "sd_blocksize", bus->blocksize)); |
---|
4345 | 5383 | |
---|
4346 | 5384 | dhdsdio_tune_fifoparam(bus); |
---|
4347 | 5385 | } |
---|
4348 | 5386 | } |
---|
4349 | 5387 | bus->roundup = MIN(max_roundup, bus->blocksize); |
---|
4350 | 5388 | |
---|
4351 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { |
---|
| 5389 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 5390 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
4352 | 5391 | bus->activity = FALSE; |
---|
4353 | 5392 | dhdsdio_bussleep(bus, TRUE); |
---|
4354 | 5393 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
4408 | 5447 | |
---|
4409 | 5448 | if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) { |
---|
4410 | 5449 | /* if Firmware already hangs disbale any interrupt */ |
---|
| 5450 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
4411 | 5451 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
4412 | 5452 | bus->hostintmask = 0; |
---|
4413 | 5453 | bcmsdh_intr_disable(bus->sdh); |
---|
.. | .. |
---|
4426 | 5466 | bus->hostintmask = 0; |
---|
4427 | 5467 | |
---|
4428 | 5468 | /* Change our idea of bus state */ |
---|
4429 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 5469 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 5470 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
4430 | 5471 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
4431 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 5472 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
4432 | 5473 | |
---|
4433 | 5474 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
---|
4434 | 5475 | saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
.. | .. |
---|
4444 | 5485 | /* Turn off the bus (F2), free any pending packets */ |
---|
4445 | 5486 | DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); |
---|
4446 | 5487 | bcmsdh_intr_disable(bus->sdh); |
---|
| 5488 | +#ifndef BCMSPI |
---|
4447 | 5489 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); |
---|
| 5490 | +#endif /* !BCMSPI */ |
---|
4448 | 5491 | |
---|
4449 | 5492 | /* Clear any pending interrupts now that F2 is disabled */ |
---|
4450 | 5493 | W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); |
---|
.. | .. |
---|
4456 | 5499 | |
---|
4457 | 5500 | #ifdef PROP_TXSTATUS |
---|
4458 | 5501 | wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED); |
---|
4459 | | -#endif |
---|
| 5502 | +#endif // endif |
---|
4460 | 5503 | if (!wlfc_enabled) { |
---|
4461 | 5504 | #ifdef DHDTCPACK_SUPPRESS |
---|
4462 | 5505 | /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt, |
---|
.. | .. |
---|
4464 | 5507 | */ |
---|
4465 | 5508 | dhd_tcpack_info_tbl_clean(bus->dhd); |
---|
4466 | 5509 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
| 5510 | + dhd_os_sdlock_txq(bus->dhd); |
---|
4467 | 5511 | /* Clear the data packet queues */ |
---|
4468 | | - pktq_flush(osh, &bus->txq, TRUE, NULL, 0); |
---|
| 5512 | + pktq_flush(osh, &bus->txq, TRUE); |
---|
| 5513 | + dhd_os_sdunlock_txq(bus->dhd); |
---|
4469 | 5514 | } |
---|
4470 | 5515 | |
---|
4471 | 5516 | /* Clear any held glomming stuff */ |
---|
.. | .. |
---|
4491 | 5536 | dhd_os_sdunlock(bus->dhd); |
---|
4492 | 5537 | } |
---|
4493 | 5538 | |
---|
4494 | | -#if defined(BCMSDIOH_TXGLOM) && (defined(BCMSDIOH_STD) || defined(BCMLXSDMMC)) |
---|
| 5539 | +#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD) |
---|
4495 | 5540 | extern uint sd_txglom; |
---|
4496 | | -#endif |
---|
| 5541 | +#endif // endif |
---|
4497 | 5542 | void |
---|
4498 | 5543 | dhd_txglom_enable(dhd_pub_t *dhdp, bool enable) |
---|
4499 | 5544 | { |
---|
.. | .. |
---|
4508 | 5553 | |
---|
4509 | 5554 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
4510 | 5555 | |
---|
4511 | | -#if defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) |
---|
| 5556 | +#ifdef BCMSDIOH_STD |
---|
4512 | 5557 | if (enable) |
---|
4513 | 5558 | enable = sd_txglom; |
---|
4514 | | -#endif /* defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) */ |
---|
| 5559 | +#endif /* BCMSDIOH_STD */ |
---|
4515 | 5560 | |
---|
4516 | 5561 | if (enable) { |
---|
4517 | 5562 | rxglom = 1; |
---|
4518 | 5563 | ret = dhd_iovar(dhdp, 0, "bus:rxglom", (char *)&rxglom, sizeof(rxglom), NULL, 0, |
---|
4519 | | - TRUE); |
---|
| 5564 | + TRUE); |
---|
4520 | 5565 | if (ret >= 0) |
---|
4521 | 5566 | bus->txglom_enable = TRUE; |
---|
4522 | 5567 | else { |
---|
4523 | | -#if defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) |
---|
| 5568 | +#ifdef BCMSDIOH_STD |
---|
4524 | 5569 | sd_txglom = 0; |
---|
4525 | | -#endif /* defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) */ |
---|
| 5570 | +#endif /* BCMSDIOH_STD */ |
---|
4526 | 5571 | bus->txglom_enable = FALSE; |
---|
4527 | 5572 | } |
---|
4528 | 5573 | } else |
---|
.. | .. |
---|
4538 | 5583 | uint retries = 0; |
---|
4539 | 5584 | uint8 ready, enable; |
---|
4540 | 5585 | int err, ret = 0; |
---|
| 5586 | +#ifdef BCMSPI |
---|
| 5587 | + uint32 dstatus = 0; /* gSPI device-status bits */ |
---|
| 5588 | +#else /* BCMSPI */ |
---|
4541 | 5589 | uint8 saveclk; |
---|
| 5590 | +#endif /* BCMSPI */ |
---|
4542 | 5591 | |
---|
4543 | 5592 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
4544 | 5593 | |
---|
4545 | 5594 | ASSERT(bus->dhd); |
---|
4546 | 5595 | if (!bus->dhd) |
---|
4547 | 5596 | return 0; |
---|
| 5597 | + |
---|
| 5598 | + if ((ret = dhdsdio_readshared_console(bus)) >= 0) { |
---|
| 5599 | + DHD_ERROR(("initialized console")); |
---|
| 5600 | +#ifdef DHD_DEBUG |
---|
| 5601 | + if ((ret = dhdsdio_readconsole(bus)) < 0) { |
---|
| 5602 | + DHD_ERROR(("%s: Console buffer read failed\n", |
---|
| 5603 | + __FUNCTION__)); |
---|
| 5604 | + } |
---|
| 5605 | +#endif /* DHD_DEBUG */ |
---|
| 5606 | + } |
---|
4548 | 5607 | |
---|
4549 | 5608 | if (enforce_mutex) |
---|
4550 | 5609 | dhd_os_sdlock(bus->dhd); |
---|
.. | .. |
---|
4557 | 5616 | goto exit; |
---|
4558 | 5617 | } |
---|
4559 | 5618 | |
---|
| 5619 | +#ifdef BCMSPI |
---|
| 5620 | + /* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */ |
---|
| 5621 | + ready = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); |
---|
| 5622 | + enable = 0; |
---|
| 5623 | + |
---|
| 5624 | + /* Give the dongle some time to do its thing and set IOR2 */ |
---|
| 5625 | + dhd_timeout_start(&tmo, WAIT_F2RXFIFORDY * WAIT_F2RXFIFORDY_DELAY * 1000); |
---|
| 5626 | + while (!enable && !dhd_timeout_expired(&tmo)) { |
---|
| 5627 | + dstatus = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL); |
---|
| 5628 | + if (dstatus & STATUS_F2_RX_READY) |
---|
| 5629 | + enable = TRUE; |
---|
| 5630 | + } |
---|
| 5631 | + |
---|
| 5632 | + if (enable) { |
---|
| 5633 | + DHD_ERROR(("Took %u usec before dongle is ready\n", tmo.elapsed)); |
---|
| 5634 | + enable = ready; |
---|
| 5635 | + } else { |
---|
| 5636 | + DHD_ERROR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus)); |
---|
| 5637 | + DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed)); |
---|
| 5638 | + ret = -1; |
---|
| 5639 | + goto exit; |
---|
| 5640 | + } |
---|
| 5641 | + |
---|
| 5642 | +#else /* !BCMSPI */ |
---|
4560 | 5643 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
---|
4561 | 5644 | saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
4562 | 5645 | |
---|
4563 | 5646 | if (!err) { |
---|
4564 | | - if (bus->sih->chip == BCM43012_CHIP_ID) { |
---|
| 5647 | + if (bus->sih->chip == BCM43012_CHIP_ID || |
---|
| 5648 | + bus->sih->chip == CYW55500_CHIP_ID || |
---|
| 5649 | + bus->sih->chip == CYW55560_CHIP_ID) { |
---|
4565 | 5650 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, |
---|
4566 | 5651 | (saveclk | SBSDIO_HT_AVAIL_REQ), &err); |
---|
4567 | 5652 | } else { |
---|
.. | .. |
---|
4590 | 5675 | while (ready != enable && !dhd_timeout_expired(&tmo)) |
---|
4591 | 5676 | ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); |
---|
4592 | 5677 | |
---|
| 5678 | +#endif /* !BCMSPI */ |
---|
| 5679 | + |
---|
4593 | 5680 | DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", |
---|
4594 | 5681 | __FUNCTION__, enable, ready, tmo.elapsed)); |
---|
4595 | | - |
---|
4596 | 5682 | |
---|
4597 | 5683 | /* If F2 successfully enabled, set core and enable interrupts */ |
---|
4598 | 5684 | if (ready == enable) { |
---|
4599 | 5685 | /* Make sure we're talking to the core. */ |
---|
| 5686 | +#ifdef BCMSDIOLITE |
---|
| 5687 | + bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0); |
---|
| 5688 | + ASSERT(bus->regs != NULL); |
---|
| 5689 | +#else |
---|
4600 | 5690 | if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0))) |
---|
4601 | 5691 | bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0); |
---|
4602 | 5692 | ASSERT(bus->regs != NULL); |
---|
4603 | | - |
---|
| 5693 | +#endif // endif |
---|
4604 | 5694 | /* Set up the interrupt mask and enable interrupts */ |
---|
4605 | 5695 | bus->hostintmask = HOSTINTMASK; |
---|
4606 | 5696 | /* corerev 4 could use the newer interrupt logic to detect the frames */ |
---|
| 5697 | +#ifndef BCMSPI |
---|
4607 | 5698 | if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) && |
---|
4608 | 5699 | (bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) { |
---|
4609 | 5700 | bus->hostintmask &= ~I_HMB_FRAME_IND; |
---|
4610 | 5701 | bus->hostintmask |= I_XMTDATA_AVAIL; |
---|
4611 | 5702 | } |
---|
| 5703 | +#endif /* BCMSPI */ |
---|
| 5704 | + /* Tell the device which interrupts are of our interest */ |
---|
4612 | 5705 | W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); |
---|
4613 | 5706 | |
---|
4614 | 5707 | if (bus->sih->buscorerev < 15) { |
---|
.. | .. |
---|
4631 | 5724 | bus->intdis = FALSE; |
---|
4632 | 5725 | if (bus->intr) { |
---|
4633 | 5726 | DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__)); |
---|
| 5727 | +#ifndef BCMSPI_ANDROID |
---|
4634 | 5728 | bcmsdh_intr_enable(bus->sdh); |
---|
| 5729 | +#endif /* !BCMSPI_ANDROID */ |
---|
4635 | 5730 | } else { |
---|
4636 | 5731 | DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); |
---|
4637 | 5732 | bcmsdh_intr_disable(bus->sdh); |
---|
.. | .. |
---|
4639 | 5734 | |
---|
4640 | 5735 | } |
---|
4641 | 5736 | |
---|
| 5737 | +#ifndef BCMSPI |
---|
4642 | 5738 | |
---|
4643 | 5739 | else { |
---|
4644 | 5740 | /* Disable F2 again */ |
---|
4645 | 5741 | enable = SDIO_FUNC_ENABLE_1; |
---|
4646 | 5742 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); |
---|
4647 | 5743 | } |
---|
| 5744 | + |
---|
| 5745 | +#ifdef DHD_FW_COREDUMP |
---|
| 5746 | + if (bus->dhd->memdump_enabled && tcm_dump_enable) { |
---|
| 5747 | + DHD_ERROR(("%s : Dumping the RAM", __FUNCTION__)); |
---|
| 5748 | + dhd_bus_mem_dump(bus->dhd); |
---|
| 5749 | + } |
---|
| 5750 | +#endif /* DHD_FW_COREDUMP */ |
---|
4648 | 5751 | |
---|
4649 | 5752 | if (dhdsdio_sr_cap(bus)) { |
---|
4650 | 5753 | dhdsdio_sr_init(bus); |
---|
.. | .. |
---|
4653 | 5756 | W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); |
---|
4654 | 5757 | DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n", |
---|
4655 | 5758 | __FUNCTION__, bus->hostintmask)); |
---|
4656 | | - } |
---|
4657 | | - else |
---|
| 5759 | + } else { |
---|
4658 | 5760 | bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, |
---|
4659 | 5761 | SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); |
---|
| 5762 | + } |
---|
| 5763 | +#else /* BCMSPI */ |
---|
| 5764 | + { |
---|
| 5765 | + if (dhdsdio_sr_cap(bus)) { |
---|
| 5766 | + dhdsdio_sr_init(bus); |
---|
| 5767 | + /* Masking the chip active interrupt permanantly */ |
---|
| 5768 | + bus->hostintmask &= ~I_CHIPACTIVE; |
---|
| 5769 | + W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); |
---|
| 5770 | + DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n", |
---|
| 5771 | + __FUNCTION__, bus->hostintmask)); |
---|
| 5772 | + } |
---|
| 5773 | + } |
---|
| 5774 | +#endif /* !BCMSPI */ |
---|
4660 | 5775 | |
---|
4661 | 5776 | /* If we didn't come up, turn off backplane clock */ |
---|
4662 | 5777 | if (dhdp->busstate != DHD_BUS_DATA) |
---|
.. | .. |
---|
4739 | 5854 | |
---|
4740 | 5855 | fail: |
---|
4741 | 5856 | /* If we can't reach the device, signal failure */ |
---|
4742 | | - if (err || bcmsdh_regfail(sdh)) |
---|
| 5857 | + if (err || bcmsdh_regfail(sdh)) { |
---|
| 5858 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
4743 | 5859 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
| 5860 | + } |
---|
4744 | 5861 | } |
---|
4745 | 5862 | |
---|
4746 | 5863 | static void |
---|
.. | .. |
---|
4811 | 5928 | goto done; |
---|
4812 | 5929 | } |
---|
4813 | 5930 | |
---|
4814 | | - |
---|
4815 | 5931 | /* Read remainder of frame body into the rxctl buffer */ |
---|
4816 | 5932 | sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, |
---|
4817 | 5933 | (bus->rxctl + firstread), rdlen, NULL, NULL, NULL); |
---|
.. | .. |
---|
4832 | 5948 | if (DHD_BYTES_ON() && DHD_CTL_ON()) { |
---|
4833 | 5949 | prhex("RxCtrl", bus->rxctl, len); |
---|
4834 | 5950 | } |
---|
4835 | | -#endif |
---|
| 5951 | +#endif // endif |
---|
4836 | 5952 | |
---|
4837 | 5953 | /* Point to valid data and indicate its length */ |
---|
4838 | 5954 | bus->rxctl += doff; |
---|
.. | .. |
---|
4994 | 6110 | errcode = -1; |
---|
4995 | 6111 | } |
---|
4996 | 6112 | pnext = NULL; |
---|
| 6113 | + BCM_REFERENCE(pnext); |
---|
4997 | 6114 | } else { |
---|
4998 | 6115 | DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen)); |
---|
4999 | 6116 | errcode = -1; |
---|
.. | .. |
---|
5026 | 6143 | prhex("SUPERFRAME", PKTDATA(osh, pfirst), |
---|
5027 | 6144 | MIN(PKTLEN(osh, pfirst), 48)); |
---|
5028 | 6145 | } |
---|
5029 | | -#endif |
---|
5030 | | - |
---|
| 6146 | +#endif // endif |
---|
5031 | 6147 | |
---|
5032 | 6148 | /* Validate the superframe header */ |
---|
5033 | 6149 | dptr = (uint8 *)PKTDATA(osh, pfirst); |
---|
.. | .. |
---|
5102 | 6218 | if (DHD_GLOM_ON()) { |
---|
5103 | 6219 | prhex("subframe", dptr, 32); |
---|
5104 | 6220 | } |
---|
5105 | | -#endif |
---|
| 6221 | +#endif // endif |
---|
5106 | 6222 | |
---|
5107 | 6223 | if ((uint16)~(sublen^check)) { |
---|
5108 | 6224 | DHD_ERROR(("%s (subframe %d): HW hdr error: " |
---|
.. | .. |
---|
5177 | 6293 | if (DHD_BYTES_ON() && DHD_DATA_ON()) { |
---|
5178 | 6294 | prhex("Rx Subframe Data", dptr, dlen); |
---|
5179 | 6295 | } |
---|
5180 | | -#endif |
---|
| 6296 | +#endif // endif |
---|
5181 | 6297 | |
---|
5182 | 6298 | PKTSETLEN(osh, pfirst, sublen); |
---|
5183 | 6299 | PKTPULL(osh, pfirst, doff); |
---|
.. | .. |
---|
5205 | 6321 | |
---|
5206 | 6322 | if (free_buf_count == 0) { |
---|
5207 | 6323 | continue; |
---|
5208 | | - } |
---|
5209 | | - else { |
---|
| 6324 | + } else { |
---|
5210 | 6325 | void *temp; |
---|
5211 | 6326 | |
---|
5212 | 6327 | /* go to the end of the chain and attach the pnext there */ |
---|
.. | .. |
---|
5223 | 6338 | } |
---|
5224 | 6339 | |
---|
5225 | 6340 | num += (uint8)free_buf_count; |
---|
5226 | | - } |
---|
5227 | | - else { |
---|
| 6341 | + } else { |
---|
5228 | 6342 | /* this packet will go up, link back into chain and count it */ |
---|
5229 | 6343 | |
---|
5230 | 6344 | if (list_tail[ifidx] == NULL) { |
---|
5231 | 6345 | list_head[ifidx] = list_tail[ifidx] = pfirst; |
---|
5232 | | - } |
---|
5233 | | - else { |
---|
| 6346 | + } else { |
---|
5234 | 6347 | PKTSETNEXT(osh, list_tail[ifidx], pfirst); |
---|
5235 | 6348 | list_tail[ifidx] = pfirst; |
---|
5236 | 6349 | } |
---|
.. | .. |
---|
5262 | 6375 | dhd_os_sdunlock(bus->dhd); |
---|
5263 | 6376 | dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0); |
---|
5264 | 6377 | dhd_os_sdlock(bus->dhd); |
---|
5265 | | -#if defined(SDIO_ISR_THREAD) |
---|
5266 | | - BUS_WAKE(bus); |
---|
5267 | | -#endif |
---|
5268 | 6378 | } |
---|
5269 | 6379 | } |
---|
5270 | 6380 | } |
---|
.. | .. |
---|
5273 | 6383 | } |
---|
5274 | 6384 | return num; |
---|
5275 | 6385 | } |
---|
5276 | | - |
---|
5277 | 6386 | |
---|
5278 | 6387 | /* Return TRUE if there may be more frames to read */ |
---|
5279 | 6388 | static uint |
---|
.. | .. |
---|
5294 | 6403 | uint rxleft = 0; /* Remaining number of frames allowed */ |
---|
5295 | 6404 | int sdret; /* Return code from bcmsdh calls */ |
---|
5296 | 6405 | uint8 txmax; /* Maximum tx sequence offered */ |
---|
| 6406 | +#ifdef BCMSPI |
---|
| 6407 | + uint32 dstatus = 0; /* gSPI device status bits of */ |
---|
| 6408 | +#endif /* BCMSPI */ |
---|
5297 | 6409 | bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */ |
---|
5298 | 6410 | uint8 *rxbuf; |
---|
5299 | 6411 | int ifidx = 0; |
---|
.. | .. |
---|
5304 | 6416 | |
---|
5305 | 6417 | #if defined(DHD_DEBUG) || defined(SDTEST) |
---|
5306 | 6418 | bool sdtest = FALSE; /* To limit message spew from test mode */ |
---|
5307 | | -#endif |
---|
| 6419 | +#endif // endif |
---|
5308 | 6420 | |
---|
5309 | 6421 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
5310 | | - |
---|
5311 | 6422 | bus->readframes = TRUE; |
---|
5312 | 6423 | |
---|
5313 | 6424 | if (!KSO_ENAB(bus)) { |
---|
.. | .. |
---|
5324 | 6435 | maxframes = bus->pktgen_count; |
---|
5325 | 6436 | sdtest = TRUE; |
---|
5326 | 6437 | } |
---|
5327 | | -#endif |
---|
| 6438 | +#endif // endif |
---|
5328 | 6439 | |
---|
5329 | 6440 | /* Not finished unless we encounter no more frames indication */ |
---|
5330 | 6441 | *finished = FALSE; |
---|
5331 | 6442 | |
---|
| 6443 | +#ifdef BCMSPI |
---|
| 6444 | + /* Get pktlen from gSPI device F0 reg. */ |
---|
| 6445 | + if (bus->bus == SPI_BUS) { |
---|
| 6446 | + /* Peek in dstatus bits and find out size to do rx-read. */ |
---|
| 6447 | + dstatus = bcmsdh_get_dstatus(bus->sdh); |
---|
| 6448 | + if (dstatus == 0) |
---|
| 6449 | + DHD_ERROR(("%s:ZERO spi dstatus, a case observed in PR61352 hit !!!\n", |
---|
| 6450 | + __FUNCTION__)); |
---|
| 6451 | + |
---|
| 6452 | + DHD_TRACE(("Device status from regread = 0x%x\n", dstatus)); |
---|
| 6453 | + DHD_TRACE(("Device status from bit-reconstruction = 0x%x\n", |
---|
| 6454 | + bcmsdh_get_dstatus((void *)bus->sdh))); |
---|
| 6455 | + |
---|
| 6456 | + if ((dstatus & STATUS_F2_PKT_AVAILABLE) && (((dstatus & STATUS_UNDERFLOW)) == 0)) { |
---|
| 6457 | + bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >> |
---|
| 6458 | + STATUS_F2_PKT_LEN_SHIFT); |
---|
| 6459 | + /* '0' size with pkt-available interrupt is eqvt to 2048 bytes */ |
---|
| 6460 | + bus->nextlen = (bus->nextlen == 0) ? SPI_MAX_PKT_LEN : bus->nextlen; |
---|
| 6461 | + if (bus->dwordmode) |
---|
| 6462 | + bus->nextlen = bus->nextlen << 2; |
---|
| 6463 | + DHD_TRACE(("Entering %s: length to be read from gSPI = %d\n", |
---|
| 6464 | + __FUNCTION__, bus->nextlen)); |
---|
| 6465 | + } else { |
---|
| 6466 | + if (dstatus & STATUS_F2_PKT_AVAILABLE) |
---|
| 6467 | + DHD_ERROR(("Underflow during %s.\n", __FUNCTION__)); |
---|
| 6468 | + else |
---|
| 6469 | + DHD_ERROR(("False pkt-available intr.\n")); |
---|
| 6470 | + *finished = TRUE; |
---|
| 6471 | + return (maxframes - rxleft); |
---|
| 6472 | + } |
---|
| 6473 | + } |
---|
| 6474 | +#endif /* BCMSPI */ |
---|
5332 | 6475 | |
---|
5333 | 6476 | for (rxseq = bus->rx_seq, rxleft = maxframes; |
---|
5334 | 6477 | !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; |
---|
.. | .. |
---|
5360 | 6503 | */ |
---|
5361 | 6504 | bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ? |
---|
5362 | 6505 | FALSE : TRUE; |
---|
5363 | | -#endif |
---|
| 6506 | +#endif // endif |
---|
5364 | 6507 | } |
---|
5365 | 6508 | |
---|
5366 | 6509 | /* Handle glomming separately */ |
---|
.. | .. |
---|
5382 | 6525 | |
---|
5383 | 6526 | if (bus->bus == SPI_BUS) { |
---|
5384 | 6527 | rdlen = len = nextlen; |
---|
5385 | | - } |
---|
5386 | | - else { |
---|
| 6528 | + } else { |
---|
5387 | 6529 | rdlen = len = nextlen << 4; |
---|
5388 | 6530 | |
---|
5389 | 6531 | /* Pad read to blocksize for efficiency */ |
---|
.. | .. |
---|
5426 | 6568 | bus->f2rxdata++; |
---|
5427 | 6569 | ASSERT(sdret != BCME_PENDING); |
---|
5428 | 6570 | |
---|
| 6571 | +#ifdef BCMSPI |
---|
| 6572 | + if (bcmsdh_get_dstatus((void *)bus->sdh) & |
---|
| 6573 | + STATUS_UNDERFLOW) { |
---|
| 6574 | + bus->nextlen = 0; |
---|
| 6575 | + *finished = TRUE; |
---|
| 6576 | + DHD_ERROR(("%s: read %d control bytes failed " |
---|
| 6577 | + "due to spi underflow\n", |
---|
| 6578 | + __FUNCTION__, rdlen)); |
---|
| 6579 | + /* dhd.rx_ctlerrs is higher level */ |
---|
| 6580 | + bus->rxc_errors++; |
---|
| 6581 | + dhd_os_sdunlock_rxq(bus->dhd); |
---|
| 6582 | + continue; |
---|
| 6583 | + } |
---|
| 6584 | +#endif /* BCMSPI */ |
---|
5429 | 6585 | |
---|
5430 | 6586 | /* Control frame failures need retransmission */ |
---|
5431 | 6587 | if (sdret < 0) { |
---|
.. | .. |
---|
5461 | 6617 | pkt, NULL, NULL); |
---|
5462 | 6618 | bus->f2rxdata++; |
---|
5463 | 6619 | ASSERT(sdret != BCME_PENDING); |
---|
| 6620 | +#ifdef BCMSPI |
---|
| 6621 | + if (bcmsdh_get_dstatus((void *)bus->sdh) & STATUS_UNDERFLOW) { |
---|
| 6622 | + bus->nextlen = 0; |
---|
| 6623 | + *finished = TRUE; |
---|
| 6624 | + DHD_ERROR(("%s (nextlen): read %d bytes failed due " |
---|
| 6625 | + "to spi underflow\n", |
---|
| 6626 | + __FUNCTION__, rdlen)); |
---|
| 6627 | + PKTFREE(bus->dhd->osh, pkt, FALSE); |
---|
| 6628 | + bus->dhd->rx_errors++; |
---|
| 6629 | + dhd_os_sdunlock_rxq(bus->dhd); |
---|
| 6630 | + continue; |
---|
| 6631 | + } |
---|
| 6632 | +#endif /* BCMSPI */ |
---|
5464 | 6633 | |
---|
5465 | 6634 | if (sdret < 0) { |
---|
5466 | 6635 | DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n", |
---|
.. | .. |
---|
5522 | 6691 | } |
---|
5523 | 6692 | |
---|
5524 | 6693 | /* Check for consistency with readahead info */ |
---|
| 6694 | +#ifdef BCMSPI |
---|
| 6695 | + if (bus->bus == SPI_BUS) { |
---|
| 6696 | + if (bus->dwordmode) { |
---|
| 6697 | + uint16 spilen; |
---|
| 6698 | + spilen = ROUNDUP(len, 4); |
---|
| 6699 | + len_consistent = (nextlen != spilen); |
---|
| 6700 | + } else |
---|
| 6701 | + len_consistent = (nextlen != len); |
---|
| 6702 | + } else |
---|
| 6703 | +#endif /* BCMSPI */ |
---|
5525 | 6704 | len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4)); |
---|
5526 | 6705 | if (len_consistent) { |
---|
5527 | 6706 | /* Mismatch, force retry w/normal header (may be >4K) */ |
---|
.. | .. |
---|
5536 | 6715 | continue; |
---|
5537 | 6716 | } |
---|
5538 | 6717 | |
---|
5539 | | - |
---|
5540 | 6718 | /* Extract software header fields */ |
---|
5541 | 6719 | chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); |
---|
5542 | 6720 | seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); |
---|
5543 | 6721 | doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); |
---|
5544 | 6722 | txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); |
---|
5545 | 6723 | |
---|
| 6724 | +#ifdef BCMSPI |
---|
| 6725 | + /* Save the readahead length if there is one */ |
---|
| 6726 | + if (bus->bus == SPI_BUS) { |
---|
| 6727 | + /* Use reconstructed dstatus bits and find out readahead size */ |
---|
| 6728 | + dstatus = bcmsdh_get_dstatus((void *)bus->sdh); |
---|
| 6729 | + DHD_INFO(("Device status from bit-reconstruction = 0x%x\n", |
---|
| 6730 | + bcmsdh_get_dstatus((void *)bus->sdh))); |
---|
| 6731 | + if (dstatus & STATUS_F2_PKT_AVAILABLE) { |
---|
| 6732 | + bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >> |
---|
| 6733 | + STATUS_F2_PKT_LEN_SHIFT); |
---|
| 6734 | + bus->nextlen = (bus->nextlen == 0) ? |
---|
| 6735 | + SPI_MAX_PKT_LEN : bus->nextlen; |
---|
| 6736 | + if (bus->dwordmode) |
---|
| 6737 | + bus->nextlen = bus->nextlen << 2; |
---|
| 6738 | + DHD_INFO(("readahead len from gSPI = %d \n", |
---|
| 6739 | + bus->nextlen)); |
---|
| 6740 | + bus->dhd->rx_readahead_cnt ++; |
---|
| 6741 | + } else { |
---|
| 6742 | + bus->nextlen = 0; |
---|
| 6743 | + *finished = TRUE; |
---|
| 6744 | + } |
---|
| 6745 | + } else { |
---|
| 6746 | +#endif /* BCMSPI */ |
---|
5546 | 6747 | bus->nextlen = |
---|
5547 | 6748 | bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; |
---|
5548 | 6749 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { |
---|
.. | .. |
---|
5553 | 6754 | } |
---|
5554 | 6755 | |
---|
5555 | 6756 | bus->dhd->rx_readahead_cnt ++; |
---|
| 6757 | +#ifdef BCMSPI |
---|
| 6758 | + } |
---|
| 6759 | +#endif /* BCMSPI */ |
---|
5556 | 6760 | /* Handle Flow Control */ |
---|
5557 | 6761 | fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); |
---|
5558 | 6762 | |
---|
.. | .. |
---|
5581 | 6785 | |
---|
5582 | 6786 | /* Check window for sanity */ |
---|
5583 | 6787 | if ((uint8)(txmax - bus->tx_seq) > 0x70) { |
---|
| 6788 | +#ifdef BCMSPI |
---|
| 6789 | + if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) { |
---|
| 6790 | + DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", |
---|
| 6791 | + __FUNCTION__, txmax, bus->tx_seq)); |
---|
| 6792 | + txmax = bus->tx_seq + 2; |
---|
| 6793 | + } else { |
---|
| 6794 | +#endif /* BCMSPI */ |
---|
5584 | 6795 | DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", |
---|
5585 | 6796 | __FUNCTION__, txmax, bus->tx_seq)); |
---|
5586 | 6797 | txmax = bus->tx_max; |
---|
| 6798 | +#ifdef BCMSPI |
---|
| 6799 | + } |
---|
| 6800 | +#endif /* BCMSPI */ |
---|
5587 | 6801 | } |
---|
5588 | 6802 | bus->tx_max = txmax; |
---|
5589 | 6803 | |
---|
.. | .. |
---|
5593 | 6807 | } else if (DHD_HDRS_ON()) { |
---|
5594 | 6808 | prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); |
---|
5595 | 6809 | } |
---|
5596 | | -#endif |
---|
| 6810 | +#endif // endif |
---|
5597 | 6811 | |
---|
5598 | 6812 | if (chan == SDPCM_CONTROL_CHANNEL) { |
---|
5599 | 6813 | if (bus->bus == SPI_BUS) { |
---|
.. | .. |
---|
5660 | 6874 | if (DHD_BYTES_ON() || DHD_HDRS_ON()) { |
---|
5661 | 6875 | prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); |
---|
5662 | 6876 | } |
---|
5663 | | -#endif |
---|
| 6877 | +#endif // endif |
---|
5664 | 6878 | |
---|
5665 | 6879 | /* Extract hardware header fields */ |
---|
5666 | 6880 | len = ltoh16_ua(bus->rxhdr); |
---|
.. | .. |
---|
5823 | 7037 | if (DHD_BYTES_ON() && DHD_DATA_ON()) { |
---|
5824 | 7038 | prhex("Rx Data", PKTDATA(osh, pkt), len); |
---|
5825 | 7039 | } |
---|
5826 | | -#endif |
---|
| 7040 | +#endif // endif |
---|
5827 | 7041 | |
---|
5828 | 7042 | deliver: |
---|
5829 | 7043 | /* Save superframe descriptor and allocate packet frame */ |
---|
.. | .. |
---|
5835 | 7049 | if (DHD_GLOM_ON()) { |
---|
5836 | 7050 | prhex("Glom Data", PKTDATA(osh, pkt), len); |
---|
5837 | 7051 | } |
---|
5838 | | -#endif |
---|
| 7052 | +#endif // endif |
---|
5839 | 7053 | PKTSETLEN(osh, pkt, len); |
---|
5840 | 7054 | ASSERT(doff == SDPCM_HDRLEN); |
---|
5841 | 7055 | PKTPULL(osh, pkt, SDPCM_HDRLEN); |
---|
.. | .. |
---|
5859 | 7073 | } |
---|
5860 | 7074 | #endif /* SDTEST */ |
---|
5861 | 7075 | |
---|
5862 | | - if (PKTLEN(osh, pkt) == 0) { |
---|
| 7076 | +#if defined(BCMSPI) |
---|
| 7077 | + if ((chan == SDPCM_EVENT_CHANNEL) && (bus->sdpcmrev >= 17 && bus->sdpcmrev <= 22)) { |
---|
| 7078 | +#else |
---|
| 7079 | + if (PKTLEN(osh, pkt) == 0) { |
---|
| 7080 | +#endif /* BCMSPI */ |
---|
5863 | 7081 | dhd_os_sdlock_rxq(bus->dhd); |
---|
5864 | 7082 | PKTFREE(bus->dhd->osh, pkt, FALSE); |
---|
5865 | 7083 | dhd_os_sdunlock_rxq(bus->dhd); |
---|
.. | .. |
---|
5873 | 7091 | bus->dhd->rx_errors++; |
---|
5874 | 7092 | continue; |
---|
5875 | 7093 | } |
---|
| 7094 | + |
---|
5876 | 7095 | if (reorder_info_len) { |
---|
5877 | 7096 | /* Reordering info from the firmware */ |
---|
5878 | 7097 | dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len, |
---|
5879 | 7098 | &pkt, &pkt_count); |
---|
5880 | 7099 | if (pkt_count == 0) |
---|
5881 | 7100 | continue; |
---|
5882 | | - } |
---|
5883 | | - else |
---|
| 7101 | + } else { |
---|
5884 | 7102 | pkt_count = 1; |
---|
| 7103 | + } |
---|
5885 | 7104 | |
---|
5886 | 7105 | /* Unlock during rx call */ |
---|
5887 | 7106 | dhd_os_sdunlock(bus->dhd); |
---|
5888 | 7107 | dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan); |
---|
5889 | 7108 | dhd_os_sdlock(bus->dhd); |
---|
5890 | | -#if defined(SDIO_ISR_THREAD) |
---|
5891 | | - BUS_WAKE(bus); |
---|
5892 | | -#endif |
---|
5893 | 7109 | } |
---|
5894 | 7110 | rxcount = maxframes - rxleft; |
---|
5895 | 7111 | #ifdef DHD_DEBUG |
---|
.. | .. |
---|
5951 | 7167 | bus->sdpcm_ver, SDPCM_PROT_VERSION)); |
---|
5952 | 7168 | else |
---|
5953 | 7169 | DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver)); |
---|
| 7170 | +#ifndef BCMSPI |
---|
5954 | 7171 | /* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */ |
---|
5955 | 7172 | if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) && |
---|
5956 | 7173 | (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) { |
---|
.. | .. |
---|
5963 | 7180 | |
---|
5964 | 7181 | val = R_REG(bus->dhd->osh, &bus->regs->corecontrol); |
---|
5965 | 7182 | } |
---|
| 7183 | +#endif /* BCMSPI */ |
---|
5966 | 7184 | |
---|
5967 | 7185 | #ifdef DHD_DEBUG |
---|
5968 | 7186 | /* Retrieve console state address now that firmware should have updated it */ |
---|
.. | .. |
---|
5970 | 7188 | sdpcm_shared_t shared; |
---|
5971 | 7189 | if (dhdsdio_readshared(bus, &shared) == 0) |
---|
5972 | 7190 | bus->console_addr = shared.console_addr; |
---|
5973 | | - } |
---|
| 7191 | + } |
---|
5974 | 7192 | #endif /* DHD_DEBUG */ |
---|
5975 | 7193 | } |
---|
5976 | 7194 | |
---|
.. | .. |
---|
5995 | 7213 | if (hmb_data & HMB_DATA_FWHALT) { |
---|
5996 | 7214 | DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n")); |
---|
5997 | 7215 | dhdsdio_checkdied(bus, NULL, 0); |
---|
5998 | | - bus->dhd->busstate = DHD_BUS_DOWN; |
---|
| 7216 | + DHD_ERROR(("Not doing bus down untill memdump done \n")); |
---|
5999 | 7217 | } |
---|
6000 | 7218 | |
---|
6001 | 7219 | /* Shouldn't be any others */ |
---|
.. | .. |
---|
6016 | 7234 | return intstatus; |
---|
6017 | 7235 | } |
---|
6018 | 7236 | |
---|
6019 | | -void |
---|
6020 | | -dhdsdio_isr(void *arg) |
---|
6021 | | -{ |
---|
6022 | | - dhd_bus_t *bus = (dhd_bus_t*)arg; |
---|
6023 | | - bcmsdh_info_t *sdh; |
---|
6024 | | - |
---|
6025 | | - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
6026 | | - |
---|
6027 | | - if (!bus) { |
---|
6028 | | - DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__)); |
---|
6029 | | - return; |
---|
6030 | | - } |
---|
6031 | | - sdh = bus->sdh; |
---|
6032 | | - |
---|
6033 | | - if (bus->dhd->busstate == DHD_BUS_DOWN) { |
---|
6034 | | - DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); |
---|
6035 | | - return; |
---|
6036 | | - } |
---|
6037 | | - |
---|
6038 | | - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
6039 | | - |
---|
6040 | | - /* Count the interrupt call */ |
---|
6041 | | - bus->intrcount++; |
---|
6042 | | - bus->ipend = TRUE; |
---|
6043 | | - |
---|
6044 | | - /* Shouldn't get this interrupt if we're sleeping? */ |
---|
6045 | | - if (!SLPAUTO_ENAB(bus)) { |
---|
6046 | | - if (bus->sleeping) { |
---|
6047 | | - DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n")); |
---|
6048 | | - return; |
---|
6049 | | - } else if (!KSO_ENAB(bus)) { |
---|
6050 | | - DHD_ERROR(("ISR in devsleep 1\n")); |
---|
6051 | | - } |
---|
6052 | | - } |
---|
6053 | | - |
---|
6054 | | - /* Disable additional interrupts (is this needed now)? */ |
---|
6055 | | - if (bus->intr) { |
---|
6056 | | - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); |
---|
6057 | | - } else { |
---|
6058 | | - DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n")); |
---|
6059 | | - } |
---|
6060 | | - |
---|
6061 | | - bcmsdh_intr_disable(sdh); |
---|
6062 | | - bus->intdis = TRUE; |
---|
6063 | | - |
---|
6064 | | - DHD_OS_WAKE_LOCK(bus->dhd); |
---|
6065 | | - if (dhdsdio_dpc(bus)) { |
---|
6066 | | - bus->dpc_sched = TRUE; |
---|
6067 | | - dhd_sched_dpc(bus->dhd); |
---|
6068 | | - } |
---|
6069 | | - DHD_OS_WAKE_UNLOCK(bus->dhd); |
---|
6070 | | - |
---|
6071 | | -} |
---|
6072 | | - |
---|
6073 | 7237 | static bool |
---|
6074 | 7238 | dhdsdio_dpc(dhd_bus_t *bus) |
---|
6075 | 7239 | { |
---|
.. | .. |
---|
6083 | 7247 | bool rxdone = TRUE; /* Flag for no more read data */ |
---|
6084 | 7248 | bool resched = FALSE; /* Flag indicating resched wanted */ |
---|
6085 | 7249 | unsigned long flags; |
---|
| 7250 | +#ifdef DEBUG_DPC_THREAD_WATCHDOG |
---|
| 7251 | + bool is_resched_by_readframe = FALSE; |
---|
| 7252 | +#endif /* DEBUG_DPC_THREAD_WATCHDOG */ |
---|
6086 | 7253 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
6087 | 7254 | |
---|
6088 | | - if (in_irq()) |
---|
6089 | | - return TRUE; |
---|
6090 | | - |
---|
6091 | 7255 | dhd_os_sdlock(bus->dhd); |
---|
6092 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 7256 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
6093 | 7257 | if (bus->dhd->busstate == DHD_BUS_DOWN) { |
---|
6094 | 7258 | DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__)); |
---|
6095 | 7259 | bus->intstatus = 0; |
---|
6096 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 7260 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
6097 | 7261 | dhd_os_sdunlock(bus->dhd); |
---|
6098 | 7262 | return 0; |
---|
6099 | 7263 | } |
---|
6100 | 7264 | |
---|
6101 | | - bus->dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_DPC; |
---|
6102 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 7265 | + DHD_BUS_BUSY_SET_IN_DPC(bus->dhd); |
---|
| 7266 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
6103 | 7267 | |
---|
6104 | 7268 | /* Start with leftover status bits */ |
---|
6105 | 7269 | intstatus = bus->intstatus; |
---|
.. | .. |
---|
6119 | 7283 | devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); |
---|
6120 | 7284 | if (err) { |
---|
6121 | 7285 | DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err)); |
---|
| 7286 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
6122 | 7287 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
6123 | 7288 | } else { |
---|
6124 | 7289 | ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY); |
---|
.. | .. |
---|
6129 | 7294 | clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
6130 | 7295 | if (err) { |
---|
6131 | 7296 | DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err)); |
---|
| 7297 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
6132 | 7298 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
6133 | 7299 | } |
---|
6134 | 7300 | |
---|
.. | .. |
---|
6139 | 7305 | if (err) { |
---|
6140 | 7306 | DHD_ERROR(("%s: error reading DEVCTL: %d\n", |
---|
6141 | 7307 | __FUNCTION__, err)); |
---|
| 7308 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
6142 | 7309 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
6143 | 7310 | } |
---|
6144 | 7311 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
---|
.. | .. |
---|
6146 | 7313 | if (err) { |
---|
6147 | 7314 | DHD_ERROR(("%s: error writing DEVCTL: %d\n", |
---|
6148 | 7315 | __FUNCTION__, err)); |
---|
| 7316 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
6149 | 7317 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
6150 | 7318 | } |
---|
6151 | 7319 | bus->clkstate = CLK_AVAIL; |
---|
.. | .. |
---|
6164 | 7332 | /* Pending interrupt indicates new device status */ |
---|
6165 | 7333 | if (bus->ipend) { |
---|
6166 | 7334 | bus->ipend = FALSE; |
---|
| 7335 | +#if defined(BT_OVER_SDIO) |
---|
| 7336 | + bcmsdh_btsdio_process_f3_intr(); |
---|
| 7337 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 7338 | + |
---|
6167 | 7339 | R_SDREG(newstatus, ®s->intstatus, retries); |
---|
6168 | 7340 | bus->f1regdata++; |
---|
6169 | 7341 | if (bcmsdh_regfail(bus->sdh)) |
---|
.. | .. |
---|
6172 | 7344 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); |
---|
6173 | 7345 | if (newstatus) { |
---|
6174 | 7346 | bus->f1regdata++; |
---|
| 7347 | +#ifndef BCMSPI |
---|
6175 | 7348 | if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) && |
---|
6176 | 7349 | (newstatus == I_XMTDATA_AVAIL)) { |
---|
6177 | | - } |
---|
6178 | | - else |
---|
| 7350 | + } else |
---|
| 7351 | +#endif /* BCMSPI */ |
---|
6179 | 7352 | W_SDREG(newstatus, ®s->intstatus, retries); |
---|
6180 | 7353 | } |
---|
6181 | 7354 | } |
---|
.. | .. |
---|
6200 | 7373 | /* Handle host mailbox indication */ |
---|
6201 | 7374 | if (intstatus & I_HMB_HOST_INT) { |
---|
6202 | 7375 | uint32 hmbdata = 0; |
---|
| 7376 | + |
---|
6203 | 7377 | intstatus &= ~I_HMB_HOST_INT; |
---|
6204 | 7378 | intstatus |= dhdsdio_hostmail(bus, &hmbdata); |
---|
6205 | | - /* ULP prototyping. Redowload fw on oob interupt */ |
---|
| 7379 | + |
---|
6206 | 7380 | #ifdef DHD_ULP |
---|
| 7381 | + /* ULP prototyping. Redowload fw on oob interupt */ |
---|
| 7382 | + |
---|
6207 | 7383 | /* all the writes after this point CAN use cached sbwad value */ |
---|
6208 | 7384 | bcmsdh_force_sbwad_calc(bus->sdh, FALSE); |
---|
6209 | 7385 | |
---|
6210 | | - if (dhd_ulp_pre_redownload_check(bus->dhd, bus->sdh, (void*)bus->sih, hmbdata)) { |
---|
| 7386 | + if (dhd_ulp_pre_redownload_check(bus->dhd, bus->sdh, hmbdata)) { |
---|
6211 | 7387 | if (dhd_bus_ulp_reinit_fw(bus) < 0) { |
---|
6212 | 7388 | DHD_ERROR(("%s:%d FW redownload failed\n", |
---|
6213 | 7389 | __FUNCTION__, __LINE__)); |
---|
6214 | 7390 | goto exit; |
---|
6215 | 7391 | } |
---|
6216 | 7392 | } |
---|
6217 | | -#endif |
---|
| 7393 | +#endif // endif |
---|
6218 | 7394 | |
---|
6219 | 7395 | } |
---|
| 7396 | + |
---|
| 7397 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 7398 | +exit_ucode: |
---|
| 7399 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
6220 | 7400 | |
---|
6221 | 7401 | /* Just being here means nothing more to do for chipactive */ |
---|
6222 | 7402 | if (intstatus & I_CHIPACTIVE) { |
---|
.. | .. |
---|
6287 | 7467 | bcmsdh_oob_intr_set(bus->sdh, TRUE); |
---|
6288 | 7468 | #endif /* defined(OOB_INTR_ONLY) */ |
---|
6289 | 7469 | bcmsdh_intr_enable(sdh); |
---|
| 7470 | +#ifdef BCMSPI_ANDROID |
---|
| 7471 | + if (*dhd_spi_lockcount == 0) |
---|
| 7472 | + bcmsdh_oob_intr_set(bus->sdh, TRUE); |
---|
| 7473 | +#endif /* BCMSPI_ANDROID */ |
---|
6290 | 7474 | } |
---|
6291 | 7475 | |
---|
6292 | 7476 | #if defined(OOB_INTR_ONLY) && !defined(HW_OOB) |
---|
.. | .. |
---|
6307 | 7491 | |
---|
6308 | 7492 | #ifdef PROP_TXSTATUS |
---|
6309 | 7493 | dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE); |
---|
6310 | | -#endif |
---|
| 7494 | +#endif // endif |
---|
6311 | 7495 | |
---|
6312 | 7496 | if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) |
---|
6313 | 7497 | dhdsdio_sendpendctl(bus); |
---|
.. | .. |
---|
6347 | 7531 | } else { |
---|
6348 | 7532 | DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n", |
---|
6349 | 7533 | __FUNCTION__)); |
---|
| 7534 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
6350 | 7535 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
6351 | 7536 | bus->intstatus = 0; |
---|
6352 | 7537 | } |
---|
.. | .. |
---|
6361 | 7546 | bus->dpc_sched = resched; |
---|
6362 | 7547 | |
---|
6363 | 7548 | /* If we're done for now, turn off clock request. */ |
---|
6364 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING)) { |
---|
| 7549 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING) && |
---|
| 7550 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
6365 | 7551 | bus->activity = FALSE; |
---|
6366 | 7552 | dhdsdio_bussleep(bus, TRUE); |
---|
6367 | 7553 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
6372 | 7558 | if (!resched && dhd_dpcpoll) { |
---|
6373 | 7559 | if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) { |
---|
6374 | 7560 | resched = TRUE; |
---|
| 7561 | +#ifdef DEBUG_DPC_THREAD_WATCHDOG |
---|
| 7562 | + is_resched_by_readframe = TRUE; |
---|
| 7563 | +#endif /* DEBUG_DPC_THREAD_WATCHDOG */ |
---|
6375 | 7564 | } |
---|
6376 | 7565 | } |
---|
6377 | 7566 | |
---|
6378 | 7567 | dhd_os_sdunlock(bus->dhd); |
---|
| 7568 | +#ifdef DEBUG_DPC_THREAD_WATCHDOG |
---|
| 7569 | + if (bus->dhd->dhd_bug_on) { |
---|
| 7570 | + DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x" |
---|
| 7571 | + " ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n", |
---|
| 7572 | + __FUNCTION__, resched, bus->ctrl_frame_stat, |
---|
| 7573 | + bus->intstatus, bus->ipend, |
---|
| 7574 | + pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe)); |
---|
6379 | 7575 | |
---|
6380 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
6381 | | - bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_DPC; |
---|
| 7576 | + bus->dhd->dhd_bug_on = FALSE; |
---|
| 7577 | + } |
---|
| 7578 | +#endif /* DEBUG_DPC_THREAD_WATCHDOG */ |
---|
| 7579 | + |
---|
| 7580 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 7581 | + DHD_BUS_BUSY_CLEAR_IN_DPC(bus->dhd); |
---|
6382 | 7582 | dhd_os_busbusy_wake(bus->dhd); |
---|
6383 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 7583 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
6384 | 7584 | |
---|
6385 | 7585 | return resched; |
---|
6386 | 7586 | } |
---|
.. | .. |
---|
6395 | 7595 | resched = dhdsdio_dpc(bus); |
---|
6396 | 7596 | |
---|
6397 | 7597 | return resched; |
---|
| 7598 | +} |
---|
| 7599 | + |
---|
| 7600 | +void |
---|
| 7601 | +dhdsdio_isr(void *arg) |
---|
| 7602 | +{ |
---|
| 7603 | + dhd_bus_t *bus = (dhd_bus_t*)arg; |
---|
| 7604 | + bcmsdh_info_t *sdh; |
---|
| 7605 | + |
---|
| 7606 | + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
| 7607 | + |
---|
| 7608 | + if (!bus) { |
---|
| 7609 | + DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__)); |
---|
| 7610 | + return; |
---|
| 7611 | + } |
---|
| 7612 | + sdh = bus->sdh; |
---|
| 7613 | + |
---|
| 7614 | + if (bus->dhd->busstate == DHD_BUS_DOWN) { |
---|
| 7615 | + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); |
---|
| 7616 | + return; |
---|
| 7617 | + } |
---|
| 7618 | + |
---|
| 7619 | + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
| 7620 | + |
---|
| 7621 | + /* Count the interrupt call */ |
---|
| 7622 | + bus->intrcount++; |
---|
| 7623 | + bus->ipend = TRUE; |
---|
| 7624 | + |
---|
| 7625 | + /* Shouldn't get this interrupt if we're sleeping? */ |
---|
| 7626 | + if (!SLPAUTO_ENAB(bus)) { |
---|
| 7627 | + if (bus->sleeping) { |
---|
| 7628 | + DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n")); |
---|
| 7629 | + return; |
---|
| 7630 | + } else if (!KSO_ENAB(bus)) { |
---|
| 7631 | + DHD_ERROR(("ISR in devsleep 1\n")); |
---|
| 7632 | + } |
---|
| 7633 | + } |
---|
| 7634 | + |
---|
| 7635 | + /* Disable additional interrupts (is this needed now)? */ |
---|
| 7636 | + if (bus->intr) { |
---|
| 7637 | + DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); |
---|
| 7638 | + } else { |
---|
| 7639 | + DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n")); |
---|
| 7640 | + } |
---|
| 7641 | + |
---|
| 7642 | +#ifdef BCMSPI_ANDROID |
---|
| 7643 | + bcmsdh_oob_intr_set(bus->sdh, FALSE); |
---|
| 7644 | +#endif /* BCMSPI_ANDROID */ |
---|
| 7645 | + bcmsdh_intr_disable(sdh); |
---|
| 7646 | + bus->intdis = TRUE; |
---|
| 7647 | + |
---|
| 7648 | +#if defined(SDIO_ISR_THREAD) |
---|
| 7649 | + DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); |
---|
| 7650 | + DHD_OS_WAKE_LOCK(bus->dhd); |
---|
| 7651 | + dhdsdio_dpc(bus); |
---|
| 7652 | + DHD_OS_WAKE_UNLOCK(bus->dhd); |
---|
| 7653 | +#else |
---|
| 7654 | + bus->dpc_sched = TRUE; |
---|
| 7655 | + dhd_sched_dpc(bus->dhd); |
---|
| 7656 | +#endif /* defined(SDIO_ISR_THREAD) */ |
---|
| 7657 | + |
---|
6398 | 7658 | } |
---|
6399 | 7659 | |
---|
6400 | 7660 | #ifdef SDTEST |
---|
.. | .. |
---|
6535 | 7795 | data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; |
---|
6536 | 7796 | prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN); |
---|
6537 | 7797 | } |
---|
6538 | | -#endif |
---|
| 7798 | +#endif // endif |
---|
6539 | 7799 | |
---|
6540 | 7800 | /* Send it */ |
---|
6541 | 7801 | if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) { |
---|
.. | .. |
---|
6586 | 7846 | if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) |
---|
6587 | 7847 | bus->pktgen_fail++; |
---|
6588 | 7848 | } |
---|
6589 | | - |
---|
6590 | 7849 | |
---|
6591 | 7850 | static void |
---|
6592 | 7851 | dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) |
---|
.. | .. |
---|
6704 | 7963 | { |
---|
6705 | 7964 | int err = 0; |
---|
6706 | 7965 | |
---|
6707 | | -#if defined(OOB_INTR_ONLY) |
---|
| 7966 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
6708 | 7967 | err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus); |
---|
6709 | | -#endif |
---|
| 7968 | +#endif // endif |
---|
6710 | 7969 | return err; |
---|
6711 | 7970 | } |
---|
6712 | 7971 | |
---|
6713 | 7972 | void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp) |
---|
6714 | 7973 | { |
---|
6715 | | -#if defined(OOB_INTR_ONLY) |
---|
| 7974 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
6716 | 7975 | bcmsdh_oob_intr_unregister(dhdp->bus->sdh); |
---|
6717 | | -#endif |
---|
| 7976 | +#endif // endif |
---|
6718 | 7977 | } |
---|
6719 | 7978 | |
---|
6720 | 7979 | void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable) |
---|
6721 | 7980 | { |
---|
6722 | | -#if defined(OOB_INTR_ONLY) |
---|
| 7981 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
6723 | 7982 | bcmsdh_oob_intr_set(dhdp->bus->sdh, enable); |
---|
6724 | | -#endif |
---|
| 7983 | +#endif // endif |
---|
6725 | 7984 | } |
---|
6726 | 7985 | |
---|
6727 | 7986 | void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub) |
---|
.. | .. |
---|
6764 | 8023 | if (!SLPAUTO_ENAB(bus) && bus->sleeping) |
---|
6765 | 8024 | return FALSE; |
---|
6766 | 8025 | |
---|
6767 | | - DHD_GENERAL_LOCK(dhdp, flags); |
---|
6768 | | - if (dhdp->busstate == DHD_BUS_DOWN || |
---|
6769 | | - dhdp->busstate == DHD_BUS_DOWN_IN_PROGRESS) { |
---|
6770 | | - DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 8026 | + DHD_LINUX_GENERAL_LOCK(dhdp, flags); |
---|
| 8027 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp) || |
---|
| 8028 | + DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) { |
---|
| 8029 | + DHD_LINUX_GENERAL_UNLOCK(dhdp, flags); |
---|
6771 | 8030 | return FALSE; |
---|
6772 | 8031 | } |
---|
6773 | | - dhdp->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_WD; |
---|
6774 | | - DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 8032 | + DHD_BUS_BUSY_SET_IN_WD(dhdp); |
---|
| 8033 | + DHD_LINUX_GENERAL_UNLOCK(dhdp, flags); |
---|
6775 | 8034 | |
---|
6776 | 8035 | dhd_os_sdlock(bus->dhd); |
---|
6777 | 8036 | |
---|
.. | .. |
---|
6785 | 8044 | /* Check device if no interrupts */ |
---|
6786 | 8045 | if (!bus->intr || (bus->intrcount == bus->lastintrs)) { |
---|
6787 | 8046 | |
---|
| 8047 | +#ifndef BCMSPI |
---|
6788 | 8048 | if (!bus->dpc_sched) { |
---|
6789 | 8049 | uint8 devpend; |
---|
6790 | 8050 | devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, |
---|
6791 | 8051 | SDIOD_CCCR_INTPEND, NULL); |
---|
6792 | 8052 | intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); |
---|
6793 | 8053 | } |
---|
| 8054 | +#else |
---|
| 8055 | + if (!bus->dpc_sched) { |
---|
| 8056 | + uint32 devpend; |
---|
| 8057 | + devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, |
---|
| 8058 | + SPID_STATUS_REG, NULL); |
---|
| 8059 | + intstatus = devpend & STATUS_F2_PKT_AVAILABLE; |
---|
| 8060 | + } |
---|
| 8061 | +#endif /* !BCMSPI */ |
---|
6794 | 8062 | |
---|
6795 | 8063 | /* If there is something, make like the ISR and schedule the DPC */ |
---|
6796 | 8064 | if (intstatus) { |
---|
.. | .. |
---|
6810 | 8078 | |
---|
6811 | 8079 | #ifdef DHD_DEBUG |
---|
6812 | 8080 | /* Poll for console output periodically */ |
---|
6813 | | - if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) { |
---|
| 8081 | + if (dhdp->busstate == DHD_BUS_DATA && dhdp->dhd_console_ms != 0) { |
---|
6814 | 8082 | bus->console.count += dhd_watchdog_ms; |
---|
6815 | | - if (bus->console.count >= dhd_console_ms) { |
---|
6816 | | - bus->console.count -= dhd_console_ms; |
---|
| 8083 | + if (bus->console.count >= dhdp->dhd_console_ms) { |
---|
| 8084 | + bus->console.count -= dhdp->dhd_console_ms; |
---|
6817 | 8085 | /* Make sure backplane clock is on */ |
---|
6818 | 8086 | if (SLPAUTO_ENAB(bus)) |
---|
6819 | 8087 | dhdsdio_bussleep(bus, FALSE); |
---|
6820 | 8088 | else |
---|
6821 | 8089 | dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); |
---|
6822 | | - if (dhdsdio_readconsole(bus) < 0) |
---|
6823 | | - dhd_console_ms = 0; /* On error, stop trying */ |
---|
| 8090 | + if (dhdsdio_readconsole(bus) < 0) |
---|
| 8091 | + dhdp->dhd_console_ms = 0; /* On error, stop trying */ |
---|
6824 | 8092 | } |
---|
6825 | 8093 | } |
---|
6826 | 8094 | #endif /* DHD_DEBUG */ |
---|
.. | .. |
---|
6836 | 8104 | bus->pktgen_tick = 0; |
---|
6837 | 8105 | dhdsdio_pktgen(bus); |
---|
6838 | 8106 | } |
---|
6839 | | -#endif |
---|
| 8107 | +#endif // endif |
---|
6840 | 8108 | |
---|
6841 | 8109 | /* On idle timeout clear activity flag and/or turn off clock */ |
---|
6842 | 8110 | #ifdef DHD_USE_IDLECOUNT |
---|
.. | .. |
---|
6845 | 8113 | else { |
---|
6846 | 8114 | bus->idlecount++; |
---|
6847 | 8115 | |
---|
6848 | | - if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) { |
---|
6849 | | - |
---|
| 8116 | + /* |
---|
| 8117 | + * If the condition to switch off the clock is reached And if |
---|
| 8118 | + * BT is inactive (in case of BT_OVER_SDIO build) turn off clk. |
---|
| 8119 | + * |
---|
| 8120 | + * Consider the following case, DHD is configured with |
---|
| 8121 | + * 1) idletime == DHD_IDLE_IMMEDIATE |
---|
| 8122 | + * 2) BT is the last user of the clock |
---|
| 8123 | + * We cannot disable the clock from __dhdsdio_clk_disable |
---|
| 8124 | + * since WLAN might be using it. If WLAN is active then |
---|
| 8125 | + * from the respective function/context after doing the job |
---|
| 8126 | + * the clk is turned off. |
---|
| 8127 | + * But if WLAN is actually inactive then the watchdog should |
---|
| 8128 | + * disable the clock. So the condition check below should be |
---|
| 8129 | + * bus->idletime != 0 instead of idletime == 0 |
---|
| 8130 | + */ |
---|
| 8131 | + if ((bus->idletime != 0) && (bus->idlecount >= bus->idletime) && |
---|
| 8132 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
6850 | 8133 | DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__)); |
---|
6851 | 8134 | if (SLPAUTO_ENAB(bus)) { |
---|
6852 | 8135 | if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY) |
---|
.. | .. |
---|
6858 | 8141 | } |
---|
6859 | 8142 | } |
---|
6860 | 8143 | #else |
---|
6861 | | - if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { |
---|
| 8144 | + if ((bus->idletime != 0) && (bus->clkstate == CLK_AVAIL) && |
---|
| 8145 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
6862 | 8146 | if (++bus->idlecount >= bus->idletime) { |
---|
6863 | 8147 | bus->idlecount = 0; |
---|
6864 | 8148 | if (bus->activity) { |
---|
6865 | 8149 | bus->activity = FALSE; |
---|
| 8150 | +#if !defined(OEM_ANDROID) |
---|
| 8151 | + } else { |
---|
| 8152 | +#endif // endif |
---|
6866 | 8153 | if (SLPAUTO_ENAB(bus)) { |
---|
6867 | 8154 | if (!bus->readframes) |
---|
6868 | 8155 | dhdsdio_bussleep(bus, TRUE); |
---|
6869 | 8156 | else |
---|
6870 | 8157 | bus->reqbussleep = TRUE; |
---|
6871 | | - } |
---|
6872 | | - else |
---|
| 8158 | + } else { |
---|
6873 | 8159 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
| 8160 | + } |
---|
6874 | 8161 | } |
---|
6875 | 8162 | } |
---|
6876 | 8163 | } |
---|
.. | .. |
---|
6878 | 8165 | |
---|
6879 | 8166 | dhd_os_sdunlock(bus->dhd); |
---|
6880 | 8167 | |
---|
6881 | | - DHD_GENERAL_LOCK(dhdp, flags); |
---|
6882 | | - dhdp->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_WD; |
---|
6883 | | - DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 8168 | + DHD_LINUX_GENERAL_LOCK(dhdp, flags); |
---|
| 8169 | + DHD_BUS_BUSY_CLEAR_IN_WD(dhdp); |
---|
| 8170 | + dhd_os_busbusy_wake(dhdp); |
---|
| 8171 | + DHD_LINUX_GENERAL_UNLOCK(dhdp, flags); |
---|
6884 | 8172 | |
---|
6885 | 8173 | return bus->ipend; |
---|
6886 | 8174 | } |
---|
6887 | 8175 | |
---|
6888 | | -#ifdef DHD_DEBUG |
---|
6889 | 8176 | extern int |
---|
6890 | 8177 | dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) |
---|
6891 | 8178 | { |
---|
.. | .. |
---|
6936 | 8223 | rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE); |
---|
6937 | 8224 | |
---|
6938 | 8225 | done: |
---|
6939 | | - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { |
---|
| 8226 | + if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && |
---|
| 8227 | + NO_OTHER_ACTIVE_BUS_USER(bus)) { |
---|
6940 | 8228 | bus->activity = FALSE; |
---|
6941 | 8229 | dhdsdio_bussleep(bus, TRUE); |
---|
6942 | 8230 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
6946 | 8234 | |
---|
6947 | 8235 | return rv; |
---|
6948 | 8236 | } |
---|
6949 | | -#endif /* DHD_DEBUG */ |
---|
6950 | 8237 | |
---|
6951 | | -#ifdef DHD_DEBUG |
---|
| 8238 | +#if defined(DHD_DEBUG) && !defined(BCMSDIOLITE) && !defined(BCMSPI) |
---|
6952 | 8239 | static void |
---|
6953 | 8240 | dhd_dump_cis(uint fn, uint8 *cis) |
---|
6954 | 8241 | { |
---|
.. | .. |
---|
6981 | 8268 | static bool |
---|
6982 | 8269 | dhdsdio_chipmatch(uint16 chipid) |
---|
6983 | 8270 | { |
---|
6984 | | - if (chipid == BCM4325_CHIP_ID) |
---|
6985 | | - return TRUE; |
---|
6986 | | - if (chipid == BCM4329_CHIP_ID) |
---|
6987 | | - return TRUE; |
---|
6988 | | - if (chipid == BCM4315_CHIP_ID) |
---|
6989 | | - return TRUE; |
---|
6990 | | - if (chipid == BCM4319_CHIP_ID) |
---|
6991 | | - return TRUE; |
---|
6992 | | - if (chipid == BCM4336_CHIP_ID) |
---|
6993 | | - return TRUE; |
---|
6994 | | - if (chipid == BCM4330_CHIP_ID) |
---|
6995 | | - return TRUE; |
---|
6996 | | - if (chipid == BCM43237_CHIP_ID) |
---|
6997 | | - return TRUE; |
---|
6998 | | - if (chipid == BCM43362_CHIP_ID) |
---|
6999 | | - return TRUE; |
---|
7000 | | - if (chipid == BCM4314_CHIP_ID) |
---|
7001 | | - return TRUE; |
---|
7002 | | - if (chipid == BCM43242_CHIP_ID) |
---|
7003 | | - return TRUE; |
---|
7004 | | - if (chipid == BCM43340_CHIP_ID) |
---|
7005 | | - return TRUE; |
---|
7006 | | - if (chipid == BCM43341_CHIP_ID) |
---|
7007 | | - return TRUE; |
---|
7008 | | - if (chipid == BCM43143_CHIP_ID) |
---|
7009 | | - return TRUE; |
---|
7010 | | - if (chipid == BCM43342_CHIP_ID) |
---|
7011 | | - return TRUE; |
---|
7012 | | - if (chipid == BCM4334_CHIP_ID) |
---|
7013 | | - return TRUE; |
---|
7014 | | - if (chipid == BCM43239_CHIP_ID) |
---|
7015 | | - return TRUE; |
---|
7016 | | - if (chipid == BCM4324_CHIP_ID) |
---|
7017 | | - return TRUE; |
---|
7018 | 8271 | if (chipid == BCM4335_CHIP_ID) |
---|
7019 | 8272 | return TRUE; |
---|
7020 | 8273 | if (chipid == BCM4339_CHIP_ID) |
---|
7021 | 8274 | return TRUE; |
---|
7022 | | - if (chipid == BCM43349_CHIP_ID) |
---|
7023 | | - return TRUE; |
---|
7024 | | - if (chipid == BCM4345_CHIP_ID || chipid == BCM43454_CHIP_ID) |
---|
| 8275 | + if (BCM4345_CHIP(chipid)) |
---|
7025 | 8276 | return TRUE; |
---|
7026 | 8277 | if (chipid == BCM4350_CHIP_ID) |
---|
7027 | 8278 | return TRUE; |
---|
7028 | 8279 | if (chipid == BCM4354_CHIP_ID) |
---|
7029 | | - return TRUE; |
---|
7030 | | - if (chipid == BCM4356_CHIP_ID) |
---|
7031 | 8280 | return TRUE; |
---|
7032 | 8281 | if (chipid == BCM4358_CHIP_ID) |
---|
7033 | 8282 | return TRUE; |
---|
.. | .. |
---|
7037 | 8286 | return TRUE; |
---|
7038 | 8287 | if (BCM4349_CHIP(chipid)) |
---|
7039 | 8288 | return TRUE; |
---|
| 8289 | + if (chipid == BCM4373_CHIP_ID) |
---|
| 8290 | + return TRUE; |
---|
| 8291 | + if (chipid == BCM4364_CHIP_ID) |
---|
| 8292 | + return TRUE; |
---|
| 8293 | + |
---|
7040 | 8294 | if (chipid == BCM43012_CHIP_ID) |
---|
7041 | 8295 | return TRUE; |
---|
7042 | | - if (chipid == BCM4373_CHIP_ID) |
---|
| 8296 | + |
---|
| 8297 | + if (chipid == BCM43014_CHIP_ID) |
---|
| 8298 | + return TRUE; |
---|
| 8299 | + |
---|
| 8300 | + if (chipid == BCM4369_CHIP_ID) |
---|
| 8301 | + return TRUE; |
---|
| 8302 | +#ifdef CHIPS_CUSTOMER_HW6 |
---|
| 8303 | + if (BCM4378_CHIP(chipid)) { |
---|
| 8304 | + return TRUE; |
---|
| 8305 | + } |
---|
| 8306 | +#endif /* CHIPS_CUSTOMER_HW6 */ |
---|
| 8307 | + if (chipid == BCM4362_CHIP_ID) |
---|
| 8308 | + return TRUE; |
---|
| 8309 | + if (chipid == BCM43751_CHIP_ID) |
---|
| 8310 | + return TRUE; |
---|
| 8311 | + if (chipid == CYW55500_CHIP_ID) |
---|
| 8312 | + return TRUE; |
---|
| 8313 | + if (chipid == CYW55560_CHIP_ID) |
---|
7043 | 8314 | return TRUE; |
---|
7044 | 8315 | return FALSE; |
---|
7045 | 8316 | } |
---|
7046 | | - |
---|
7047 | | -#ifdef GET_OTP_MAC_ENABLE |
---|
7048 | | -static int |
---|
7049 | | -dhd_get_otp_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac) |
---|
7050 | | -{ |
---|
7051 | | - int i, err = -1; |
---|
7052 | | - uint8 *ptr = 0; |
---|
7053 | | - unsigned char tpl_code, tpl_link='\0'; |
---|
7054 | | - uint8 header[3] = {0x80, 0x07, 0x19}; |
---|
7055 | | - uint8 *cis; |
---|
7056 | | - |
---|
7057 | | - if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) { |
---|
7058 | | - DHD_ERROR(("%s: cis malloc failed\n", __FUNCTION__)); |
---|
7059 | | - return err; |
---|
7060 | | - } |
---|
7061 | | - bzero(cis, SBSDIO_CIS_SIZE_LIMIT); |
---|
7062 | | - |
---|
7063 | | - if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) { |
---|
7064 | | - DHD_ERROR(("%s: cis read err %d\n", __FUNCTION__, err)); |
---|
7065 | | - MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT); |
---|
7066 | | - return err; |
---|
7067 | | - } |
---|
7068 | | - err = -1; // reset err; |
---|
7069 | | - ptr = cis; |
---|
7070 | | - do { |
---|
7071 | | - /* 0xff means we're done */ |
---|
7072 | | - tpl_code = *ptr; |
---|
7073 | | - ptr++; |
---|
7074 | | - if (tpl_code == 0xff) |
---|
7075 | | - break; |
---|
7076 | | - |
---|
7077 | | - /* null entries have no link field or data */ |
---|
7078 | | - if (tpl_code == 0x00) |
---|
7079 | | - continue; |
---|
7080 | | - |
---|
7081 | | - tpl_link = *ptr; |
---|
7082 | | - ptr++; |
---|
7083 | | - /* a size of 0xff also means we're done */ |
---|
7084 | | - if (tpl_link == 0xff) |
---|
7085 | | - break; |
---|
7086 | | - |
---|
7087 | | - if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) |
---|
7088 | | - break; |
---|
7089 | | - |
---|
7090 | | - ptr += tpl_link; |
---|
7091 | | - } while (1); |
---|
7092 | | - |
---|
7093 | | - if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) { |
---|
7094 | | - /* Normal OTP */ |
---|
7095 | | - memcpy(mac, ptr+1, 6); |
---|
7096 | | - err = 0; |
---|
7097 | | - } else { |
---|
7098 | | - ptr = cis; |
---|
7099 | | - /* Special OTP */ |
---|
7100 | | - if (bcmsdh_reg_read(sdh, SI_ENUM_BASE, 4) == 0x16044330) { |
---|
7101 | | - for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) { |
---|
7102 | | - if (!memcmp(header, ptr, 3)) { |
---|
7103 | | - memcpy(mac, ptr+3, 6); |
---|
7104 | | - err = 0; |
---|
7105 | | - break; |
---|
7106 | | - } |
---|
7107 | | - ptr++; |
---|
7108 | | - } |
---|
7109 | | - } |
---|
7110 | | - } |
---|
7111 | | - |
---|
7112 | | - ASSERT(cis); |
---|
7113 | | - MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT); |
---|
7114 | | - |
---|
7115 | | - return err; |
---|
7116 | | -} |
---|
7117 | | -#endif /* GET_OTP_MAC_ENABLE */ |
---|
7118 | 8317 | |
---|
7119 | 8318 | static void * |
---|
7120 | 8319 | dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, |
---|
.. | .. |
---|
7122 | 8321 | { |
---|
7123 | 8322 | int ret; |
---|
7124 | 8323 | dhd_bus_t *bus; |
---|
7125 | | -#ifdef GET_OTP_MAC_ENABLE |
---|
7126 | | - struct ether_addr ea_addr; |
---|
7127 | | -#endif |
---|
7128 | 8324 | |
---|
| 8325 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 8326 | + if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { |
---|
| 8327 | + DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__)); |
---|
| 8328 | + } else { |
---|
| 8329 | + DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__)); |
---|
| 8330 | + } |
---|
| 8331 | + mutex_lock(&_dhd_sdio_mutex_lock_); |
---|
| 8332 | +#endif // endif |
---|
7129 | 8333 | |
---|
7130 | 8334 | /* Init global variables at run-time, not as part of the declaration. |
---|
7131 | 8335 | * This is required to support init/de-init of the driver. Initialization |
---|
.. | .. |
---|
7135 | 8339 | */ |
---|
7136 | 8340 | dhd_txbound = DHD_TXBOUND; |
---|
7137 | 8341 | dhd_rxbound = DHD_RXBOUND; |
---|
| 8342 | +#ifdef BCMSPI |
---|
| 8343 | + dhd_alignctl = FALSE; |
---|
| 8344 | +#else |
---|
7138 | 8345 | dhd_alignctl = TRUE; |
---|
| 8346 | +#endif /* BCMSPI */ |
---|
7139 | 8347 | sd1idle = TRUE; |
---|
7140 | 8348 | dhd_readahead = TRUE; |
---|
7141 | 8349 | retrydata = FALSE; |
---|
7142 | 8350 | |
---|
| 8351 | +#ifdef DISABLE_FLOW_CONTROL |
---|
7143 | 8352 | dhd_doflow = FALSE; |
---|
| 8353 | +#endif /* DISABLE_FLOW_CONTROL */ |
---|
7144 | 8354 | dhd_dongle_ramsize = 0; |
---|
7145 | 8355 | dhd_txminmax = DHD_TXMINMAX; |
---|
7146 | 8356 | |
---|
| 8357 | +#ifdef BCMSPI |
---|
| 8358 | + forcealign = FALSE; |
---|
| 8359 | +#else |
---|
7147 | 8360 | forcealign = TRUE; |
---|
| 8361 | +#endif /* !BCMSPI */ |
---|
7148 | 8362 | |
---|
7149 | 8363 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
7150 | 8364 | DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid)); |
---|
7151 | 8365 | |
---|
7152 | 8366 | /* We make assumptions about address window mappings */ |
---|
7153 | | - ASSERT((uintptr)regsva == SI_ENUM_BASE); |
---|
| 8367 | + ASSERT((uintptr)regsva == si_enum_base(devid)); |
---|
7154 | 8368 | |
---|
7155 | 8369 | /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start |
---|
7156 | 8370 | * means early parse could fail, so here we should get either an ID |
---|
.. | .. |
---|
7169 | 8383 | |
---|
7170 | 8384 | /* Check the Device ID and make sure it's one that we support */ |
---|
7171 | 8385 | switch (devid) { |
---|
7172 | | - case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */ |
---|
7173 | | - case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */ |
---|
7174 | | - case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */ |
---|
7175 | | - DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__)); |
---|
7176 | | - break; |
---|
7177 | | - case BCM4329_D11N_ID: /* 4329 802.11n dualband device */ |
---|
7178 | | - case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */ |
---|
7179 | | - case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */ |
---|
7180 | | - case 0x4329: |
---|
7181 | | - DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__)); |
---|
7182 | | - break; |
---|
7183 | | - case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */ |
---|
7184 | | - case BCM4315_D11G_ID: /* 4315 802.11g id */ |
---|
7185 | | - case BCM4315_D11A_ID: /* 4315 802.11a id */ |
---|
7186 | | - DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__)); |
---|
7187 | | - break; |
---|
7188 | | - case BCM4319_D11N_ID: /* 4319 802.11n id */ |
---|
7189 | | - case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */ |
---|
7190 | | - case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */ |
---|
7191 | | - DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__)); |
---|
7192 | | - break; |
---|
7193 | 8386 | case 0: |
---|
7194 | 8387 | DHD_INFO(("%s: allow device id 0, will check chip internals\n", |
---|
7195 | 8388 | __FUNCTION__)); |
---|
.. | .. |
---|
7202 | 8395 | } |
---|
7203 | 8396 | |
---|
7204 | 8397 | if (osh == NULL) { |
---|
| 8398 | +#if defined(BCMSPI) && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI)) |
---|
| 8399 | + /* bcmsdh_probe() calls drvinfo.probe() that is this function with osh as NULL */ |
---|
| 8400 | + if (!(osh = osl_attach(sdh, DHD_BUS, TRUE))) { |
---|
| 8401 | + DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__)); |
---|
| 8402 | + goto forcereturn; |
---|
| 8403 | + } |
---|
| 8404 | +#else |
---|
7205 | 8405 | DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__)); |
---|
7206 | 8406 | goto forcereturn; |
---|
| 8407 | +#endif /* BCMSPI && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI)) */ |
---|
7207 | 8408 | } |
---|
7208 | 8409 | |
---|
7209 | 8410 | /* Allocate private bus interface state */ |
---|
.. | .. |
---|
7219 | 8420 | bus->slot_num = slot; |
---|
7220 | 8421 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; |
---|
7221 | 8422 | bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */ |
---|
| 8423 | +#ifdef BT_OVER_SDIO |
---|
| 8424 | + bus->bt_use_count = 0; |
---|
| 8425 | +#endif // endif |
---|
7222 | 8426 | |
---|
7223 | | -#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16) |
---|
| 8427 | +#if defined(SUPPORT_P2P_GO_PS) |
---|
7224 | 8428 | init_waitqueue_head(&bus->bus_sleep); |
---|
7225 | 8429 | #endif /* LINUX && SUPPORT_P2P_GO_PS */ |
---|
7226 | 8430 | |
---|
.. | .. |
---|
7269 | 8473 | if (dhd_download_fw_on_driverload) { |
---|
7270 | 8474 | if ((ret = dhd_bus_start(bus->dhd)) != 0) { |
---|
7271 | 8475 | DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); |
---|
| 8476 | +#if !defined(OEM_ANDROID) || defined(BCMQT) |
---|
| 8477 | + if (ret == BCME_NOTUP) |
---|
| 8478 | +#endif /* !OEM_ANDROID || defined(BCMQT) */ |
---|
7272 | 8479 | goto fail; |
---|
7273 | 8480 | } |
---|
7274 | 8481 | } |
---|
7275 | | - |
---|
7276 | | -#ifdef GET_OTP_MAC_ENABLE |
---|
7277 | | - if (dhd_get_otp_mac(bus->dhd, sdh, ea_addr.octet)) { |
---|
7278 | | - DHD_TRACE(("%s: Can not read MAC address\n", __FUNCTION__)); |
---|
7279 | | - } else |
---|
7280 | | - memcpy(bus->dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN); |
---|
7281 | | -#endif |
---|
| 8482 | + else { |
---|
| 8483 | + /* Set random MAC address during boot time */ |
---|
| 8484 | + get_random_bytes(&bus->dhd->mac.octet[3], 3); |
---|
| 8485 | + /* Adding BRCM OUI */ |
---|
| 8486 | + bus->dhd->mac.octet[0] = 0; |
---|
| 8487 | + bus->dhd->mac.octet[1] = 0x90; |
---|
| 8488 | + bus->dhd->mac.octet[2] = 0x4C; |
---|
| 8489 | + } |
---|
| 8490 | +#if defined(BT_OVER_SDIO) |
---|
| 8491 | + /* At this point Regulators are turned on and iconditionaly sdio bus is started |
---|
| 8492 | + * based upon dhd_download_fw_on_driverload check, so |
---|
| 8493 | + * increase the bus user count, this count will only be disabled inside |
---|
| 8494 | + * dhd_register_if() function if flag dhd_download_fw_on_driverload is set to false, |
---|
| 8495 | + * i.e FW download during insmod is not needed, otherwise it will not be decremented |
---|
| 8496 | + * so that WALN will always hold the bus untill rmmod is done. |
---|
| 8497 | + */ |
---|
| 8498 | + dhdsdio_bus_usr_cnt_inc(bus->dhd); |
---|
| 8499 | +#endif /* BT_OVER_SDIO */ |
---|
7282 | 8500 | |
---|
7283 | 8501 | /* Ok, have the per-port tell the stack we're open for business */ |
---|
7284 | | - if (dhd_register_if(bus->dhd, 0, TRUE) != 0) { |
---|
| 8502 | + if (dhd_attach_net(bus->dhd, TRUE) != 0) |
---|
| 8503 | + { |
---|
7285 | 8504 | DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); |
---|
7286 | 8505 | goto fail; |
---|
7287 | 8506 | } |
---|
7288 | 8507 | |
---|
| 8508 | +#ifdef BCMHOST_XTAL_PU_TIME_MOD |
---|
| 8509 | + bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11); |
---|
| 8510 | + bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001); |
---|
| 8511 | +#endif /* BCMHOST_XTAL_PU_TIME_MOD */ |
---|
7289 | 8512 | |
---|
| 8513 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 8514 | + mutex_unlock(&_dhd_sdio_mutex_lock_); |
---|
| 8515 | + DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); |
---|
| 8516 | +#endif // endif |
---|
7290 | 8517 | |
---|
7291 | 8518 | return bus; |
---|
7292 | 8519 | |
---|
.. | .. |
---|
7294 | 8521 | dhdsdio_release(bus, osh); |
---|
7295 | 8522 | |
---|
7296 | 8523 | forcereturn: |
---|
| 8524 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 8525 | + mutex_unlock(&_dhd_sdio_mutex_lock_); |
---|
| 8526 | + DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); |
---|
| 8527 | +#endif // endif |
---|
7297 | 8528 | |
---|
7298 | 8529 | return NULL; |
---|
7299 | 8530 | } |
---|
.. | .. |
---|
7302 | 8533 | dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, |
---|
7303 | 8534 | uint16 devid) |
---|
7304 | 8535 | { |
---|
7305 | | - int err = 0; |
---|
| 8536 | +#ifdef BCMSPI |
---|
| 8537 | + uint32 spidreg = 0; |
---|
| 8538 | +#else |
---|
7306 | 8539 | uint8 clkctl = 0; |
---|
| 8540 | + uint8 cardcap = 0; |
---|
| 8541 | +#endif /* BCMSPI */ |
---|
| 8542 | + uint fn, numfn; |
---|
| 8543 | + uint8 *cis[SDIOD_MAX_IOFUNCS]; |
---|
| 8544 | + int32 value; |
---|
| 8545 | + int32 size; |
---|
| 8546 | + int err = 0; |
---|
| 8547 | + hs_addrs_t bl_hs_addrs = {NULL, NULL}; |
---|
7307 | 8548 | |
---|
| 8549 | + BCM_REFERENCE(value); |
---|
7308 | 8550 | bus->alp_only = TRUE; |
---|
7309 | 8551 | bus->sih = NULL; |
---|
7310 | 8552 | |
---|
| 8553 | +#ifdef BCMSPI |
---|
| 8554 | + spidreg = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_RESET_BP, NULL); |
---|
| 8555 | + if (spidreg & SPID_SECURE_MODE) { |
---|
| 8556 | + DHD_INFO(("Security related features are present\n")); |
---|
| 8557 | + bus->secureboot = TRUE; |
---|
| 8558 | + } |
---|
| 8559 | + if (spidreg & SPID_CHIPID_PRESENT) { |
---|
| 8560 | + DHD_INFO(("Chip ID is present in SPI core\n")); |
---|
| 8561 | + bus->chipidpresent = true; |
---|
| 8562 | + } |
---|
| 8563 | +#else |
---|
| 8564 | + cardcap = dhdsdio_devcap_get(bus); |
---|
| 8565 | + if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_SECURE_MODE) { |
---|
| 8566 | + DHD_INFO(("Security related features are present\n")); |
---|
| 8567 | + bus->secureboot = TRUE; |
---|
| 8568 | + } |
---|
| 8569 | + if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) { |
---|
| 8570 | + DHD_INFO(("Chip ID is present in SDIO core\n")); |
---|
| 8571 | + bus->chipidpresent = true; |
---|
| 8572 | + } |
---|
| 8573 | +#endif /* BCMSPI */ |
---|
| 8574 | + |
---|
| 8575 | + if (bus->secureboot) { |
---|
| 8576 | + /* Should not do any backplane access before bootloader is ready */ |
---|
| 8577 | + dhdsdio_dongle_host_get_handshake_address(bus, &bl_hs_addrs); |
---|
| 8578 | + err = dhdsdio_wait_bootloader_ready(bus, &bl_hs_addrs); |
---|
| 8579 | + if (err) { |
---|
| 8580 | + DHD_ERROR(("Bootloader ready timeout\n")); |
---|
| 8581 | + goto fail; |
---|
| 8582 | + } |
---|
| 8583 | + } |
---|
| 8584 | + |
---|
| 8585 | + if (bus->chipidpresent) { |
---|
| 8586 | + /* Get SDIO core base address */ |
---|
| 8587 | + bus->regs = si_get_sdio_addrbase(sdh); |
---|
| 8588 | + } |
---|
| 8589 | + |
---|
7311 | 8590 | /* Return the window to backplane enumeration space for core access */ |
---|
7312 | | - if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) { |
---|
| 8591 | + if (dhdsdio_set_siaddr_window(bus, si_enum_base(devid))) { |
---|
7313 | 8592 | DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__)); |
---|
7314 | 8593 | } |
---|
7315 | 8594 | |
---|
7316 | | -#if defined(DHD_DEBUG) |
---|
7317 | | - DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n", |
---|
7318 | | - bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4))); |
---|
7319 | | -#endif |
---|
| 8595 | +#if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG) |
---|
| 8596 | + if (bus->chipidpresent) { |
---|
| 8597 | + DHD_ERROR(("F1 signature read @0x%lx=0x%4x\n", |
---|
| 8598 | + (unsigned long)&bus->regs->chipid, R_REG(osh, &bus->regs->chipid))); |
---|
| 8599 | + } else { |
---|
| 8600 | + DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n", |
---|
| 8601 | + bcmsdh_reg_read(bus->sdh, si_enum_base(devid), 4))); |
---|
| 8602 | + } |
---|
| 8603 | +#endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */ |
---|
7320 | 8604 | |
---|
| 8605 | +#ifndef BCMSPI /* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */ |
---|
7321 | 8606 | |
---|
7322 | 8607 | /* Force PLL off until si_attach() programs PLL control regs */ |
---|
7323 | 8608 | |
---|
| 8609 | + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); |
---|
| 8610 | + if (!err) |
---|
| 8611 | + clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
7324 | 8612 | |
---|
7325 | | - |
---|
7326 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
7327 | | - if(alive != FW_ALIVE_MAGIC) |
---|
7328 | | -#endif |
---|
7329 | | - { |
---|
7330 | | - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); |
---|
7331 | | - if (!err) |
---|
7332 | | - clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); |
---|
7333 | | - |
---|
7334 | | - if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) { |
---|
7335 | | - DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", |
---|
7336 | | - err, DHD_INIT_CLKCTL1, clkctl)); |
---|
7337 | | - goto fail; |
---|
7338 | | - } |
---|
| 8613 | + if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) { |
---|
| 8614 | + DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", |
---|
| 8615 | + err, DHD_INIT_CLKCTL1, clkctl)); |
---|
| 8616 | + goto fail; |
---|
7339 | 8617 | } |
---|
| 8618 | + |
---|
| 8619 | +#endif /* !BCMSPI */ |
---|
| 8620 | +#ifdef BCMSPI |
---|
| 8621 | + /* internally func is hardcoded to 1 as gSPI has cis on F1 only */ |
---|
| 8622 | + fn = 0; |
---|
| 8623 | + value = F0_BLOCK_SIZE; |
---|
| 8624 | + /* Get block size from sd */ |
---|
| 8625 | + if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32), |
---|
| 8626 | + &size, sizeof(int32), FALSE) != BCME_OK) { |
---|
| 8627 | + size = 0; |
---|
| 8628 | + DHD_ERROR(("%s: fail on fn %d %s get\n", |
---|
| 8629 | + __FUNCTION__, fn, "sd_blocksize")); |
---|
| 8630 | + } else { |
---|
| 8631 | + DHD_INFO(("%s: Initial value for fn %d %s is %d\n", |
---|
| 8632 | + __FUNCTION__, fn, "sd_blocksize", size)); |
---|
| 8633 | + } |
---|
| 8634 | + if (size != 0 && size < value) { |
---|
| 8635 | + value = size; |
---|
| 8636 | + } |
---|
| 8637 | + value = fn << 16 | value; |
---|
| 8638 | + if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &value, |
---|
| 8639 | + sizeof(value), TRUE) != BCME_OK) { |
---|
| 8640 | + bus->blocksize = 0; |
---|
| 8641 | + DHD_ERROR(("%s: fail on fn %d %s set\n", __FUNCTION__, |
---|
| 8642 | + fn, "sd_blocksize")); |
---|
| 8643 | + } |
---|
| 8644 | + BCM_REFERENCE(cis); |
---|
| 8645 | + BCM_REFERENCE(numfn); |
---|
| 8646 | +#else |
---|
| 8647 | + numfn = bcmsdh_query_iofnum(sdh); |
---|
| 8648 | + ASSERT(numfn <= SDIOD_MAX_IOFUNCS); |
---|
| 8649 | + |
---|
| 8650 | + /* Make sure ALP is available before trying to read CIS */ |
---|
| 8651 | + SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, |
---|
| 8652 | + SBSDIO_FUNC1_CHIPCLKCSR, NULL)), |
---|
| 8653 | + !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY); |
---|
| 8654 | + |
---|
| 8655 | + /* Now request ALP be put on the bus */ |
---|
| 8656 | + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, |
---|
| 8657 | + DHD_INIT_CLKCTL2, &err); |
---|
| 8658 | + OSL_DELAY(65); |
---|
| 8659 | +#ifndef BCMSDIOLITE |
---|
| 8660 | + for (fn = 0; fn <= numfn; fn++) { |
---|
| 8661 | + if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { |
---|
| 8662 | + DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); |
---|
| 8663 | + break; |
---|
| 8664 | + } |
---|
| 8665 | + bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
| 8666 | + |
---|
| 8667 | + if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], |
---|
| 8668 | + SBSDIO_CIS_SIZE_LIMIT))) { |
---|
| 8669 | + DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); |
---|
| 8670 | + MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
| 8671 | + break; |
---|
| 8672 | + } |
---|
| 8673 | + |
---|
| 8674 | + /* Reading the F1, F2 and F3 max blocksize values from CIS |
---|
| 8675 | + * and writing into the F1, F2 and F3 block size registers. |
---|
| 8676 | + * There is no max block size register value available for F0 in CIS register. |
---|
| 8677 | + * So, setting default value for F0 block size as 32 (which was set earlier |
---|
| 8678 | + * in iovar). IOVAR takes only one arguement. |
---|
| 8679 | + * So, we are passing the function number alongwith the value (fn<<16) |
---|
| 8680 | + */ |
---|
| 8681 | + if (!fn) |
---|
| 8682 | + value = F0_BLOCK_SIZE; |
---|
| 8683 | + else |
---|
| 8684 | + value = (cis[fn][25]<<8) | cis[fn][24] | (fn<<16); |
---|
| 8685 | + /* Get block size from sd */ |
---|
| 8686 | + if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32), |
---|
| 8687 | + &size, sizeof(int32), FALSE) != BCME_OK) { |
---|
| 8688 | + size = 0; |
---|
| 8689 | + DHD_ERROR(("%s: fail on fn %d %s get\n", |
---|
| 8690 | + __FUNCTION__, fn, "sd_blocksize")); |
---|
| 8691 | + } else { |
---|
| 8692 | + DHD_INFO(("%s: Initial value for fn %d %s is %d\n", |
---|
| 8693 | + __FUNCTION__, fn, "sd_blocksize", size)); |
---|
| 8694 | + } |
---|
| 8695 | + if (size != 0 && size < value) { |
---|
| 8696 | + value = size; |
---|
| 8697 | + } |
---|
| 8698 | + value = fn << 16 | value; |
---|
| 8699 | + if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &value, |
---|
| 8700 | + sizeof(value), TRUE) != BCME_OK) { |
---|
| 8701 | + bus->blocksize = 0; |
---|
| 8702 | + DHD_ERROR(("%s: fail on fn %d %s set\n", __FUNCTION__, |
---|
| 8703 | + fn, "sd_blocksize")); |
---|
| 8704 | + } |
---|
| 8705 | + |
---|
| 8706 | + /* F2 blocksize value can be taken in order of precedence of |
---|
| 8707 | + * insmod argument |
---|
| 8708 | + * build flag variable |
---|
| 8709 | + * CIS tuple |
---|
| 8710 | + * default parameter |
---|
| 8711 | + */ |
---|
| 8712 | + if (fn == F2_BLOCK) { |
---|
| 8713 | + if (!sd_f2_blocksize) { |
---|
| 8714 | +#ifdef CUSTOM_SDIO_F2_BLKSIZE |
---|
| 8715 | + sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; |
---|
| 8716 | +#else |
---|
| 8717 | + sd_f2_blocksize = ((uint16)value ? (uint16)value : |
---|
| 8718 | + DEFAULT_SDIO_F2_BLKSIZE); |
---|
| 8719 | +#endif /* CUSTOM_SDIO_F2_BLKSIZE */ |
---|
| 8720 | + } |
---|
| 8721 | + |
---|
| 8722 | + value = (fn << SDIO_FUNC_BLOCK_SIZE_SHIFT) | sd_f2_blocksize; |
---|
| 8723 | + if (bcmsdh_iovar_op(sdh, "sd_blocksize", |
---|
| 8724 | + NULL, 0, &value, sizeof(fn), TRUE) != BCME_OK) { |
---|
| 8725 | + DHD_ERROR(("%s: Set F2 Block size error\n", |
---|
| 8726 | + __FUNCTION__)); |
---|
| 8727 | + goto fail; |
---|
| 8728 | + } |
---|
| 8729 | + } |
---|
7340 | 8730 | |
---|
7341 | 8731 | #ifdef DHD_DEBUG |
---|
7342 | | - if (DHD_INFO_ON()) { |
---|
7343 | | - uint fn, numfn; |
---|
7344 | | - uint8 *cis[SDIOD_MAX_IOFUNCS]; |
---|
7345 | | - int err = 0; |
---|
7346 | | - |
---|
7347 | | - numfn = bcmsdh_query_iofnum(sdh); |
---|
7348 | | - ASSERT(numfn <= SDIOD_MAX_IOFUNCS); |
---|
7349 | | - |
---|
7350 | | - /* Make sure ALP is available before trying to read CIS */ |
---|
7351 | | - SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, |
---|
7352 | | - SBSDIO_FUNC1_CHIPCLKCSR, NULL)), |
---|
7353 | | - !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY); |
---|
7354 | | - |
---|
7355 | | - /* Now request ALP be put on the bus */ |
---|
7356 | | - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, |
---|
7357 | | - DHD_INIT_CLKCTL2, &err); |
---|
7358 | | - OSL_DELAY(65); |
---|
7359 | | - |
---|
7360 | | - for (fn = 0; fn <= numfn; fn++) { |
---|
7361 | | - if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { |
---|
7362 | | - DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); |
---|
7363 | | - break; |
---|
7364 | | - } |
---|
7365 | | - bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
7366 | | - |
---|
7367 | | - if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) { |
---|
7368 | | - DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); |
---|
7369 | | - MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
7370 | | - break; |
---|
7371 | | - } |
---|
| 8732 | + if (DHD_INFO_ON()) { |
---|
7372 | 8733 | dhd_dump_cis(fn, cis[fn]); |
---|
7373 | 8734 | } |
---|
7374 | | - |
---|
7375 | | - while (fn-- > 0) { |
---|
7376 | | - ASSERT(cis[fn]); |
---|
7377 | | - MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
7378 | | - } |
---|
7379 | | - |
---|
7380 | | - if (err) { |
---|
7381 | | - DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n")); |
---|
7382 | | - goto fail; |
---|
7383 | | - } |
---|
7384 | | - } |
---|
7385 | 8735 | #endif /* DHD_DEBUG */ |
---|
| 8736 | + } |
---|
| 8737 | + while (fn-- > 0) { |
---|
| 8738 | + ASSERT(cis[fn]); |
---|
| 8739 | + MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
---|
| 8740 | + } |
---|
| 8741 | +#else |
---|
| 8742 | + BCM_REFERENCE(cis); |
---|
| 8743 | + BCM_REFERENCE(fn); |
---|
| 8744 | +#endif /* !BCMSDIOLITE */ |
---|
| 8745 | +#endif /* !BCMSPI */ |
---|
| 8746 | + if (err) { |
---|
| 8747 | + DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n")); |
---|
| 8748 | + goto fail; |
---|
| 8749 | + } |
---|
7386 | 8750 | |
---|
7387 | 8751 | /* si_attach() will provide an SI handle and scan the backplane */ |
---|
7388 | 8752 | if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh, |
---|
.. | .. |
---|
7395 | 8759 | DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n", |
---|
7396 | 8760 | bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg)); |
---|
7397 | 8761 | #endif /* DHD_DEBUG */ |
---|
7398 | | - |
---|
7399 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
7400 | | - card_dev = bus->sih->chip; |
---|
7401 | | - card_rev = bus->sih->chiprev; |
---|
7402 | | -#endif |
---|
7403 | | - |
---|
7404 | 8762 | |
---|
7405 | 8763 | bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); |
---|
7406 | 8764 | |
---|
.. | .. |
---|
7415 | 8773 | else |
---|
7416 | 8774 | bus->kso = TRUE; |
---|
7417 | 8775 | |
---|
7418 | | - if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) { |
---|
7419 | | - } |
---|
7420 | | - |
---|
7421 | 8776 | si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength); |
---|
7422 | | - |
---|
7423 | 8777 | |
---|
7424 | 8778 | /* Get info on the ARM and SOCRAM cores... */ |
---|
7425 | 8779 | if (!DHD_NOPMU(bus)) { |
---|
.. | .. |
---|
7447 | 8801 | switch ((uint16)bus->sih->chip) { |
---|
7448 | 8802 | case BCM4335_CHIP_ID: |
---|
7449 | 8803 | case BCM4339_CHIP_ID: |
---|
7450 | | - case BCM43349_CHIP_ID: |
---|
7451 | 8804 | bus->dongle_ram_base = CR4_4335_RAM_BASE; |
---|
7452 | 8805 | break; |
---|
7453 | 8806 | case BCM4350_CHIP_ID: |
---|
7454 | 8807 | case BCM4354_CHIP_ID: |
---|
7455 | | - case BCM4356_CHIP_ID: |
---|
7456 | 8808 | case BCM4358_CHIP_ID: |
---|
7457 | 8809 | bus->dongle_ram_base = CR4_4350_RAM_BASE; |
---|
7458 | 8810 | break; |
---|
7459 | 8811 | case BCM4360_CHIP_ID: |
---|
7460 | 8812 | bus->dongle_ram_base = CR4_4360_RAM_BASE; |
---|
7461 | 8813 | break; |
---|
7462 | | - case BCM4345_CHIP_ID: |
---|
7463 | | - case BCM43454_CHIP_ID: |
---|
| 8814 | + CASE_BCM4345_CHIP: |
---|
7464 | 8815 | bus->dongle_ram_base = (bus->sih->chiprev < 6) /* from 4345C0 */ |
---|
7465 | 8816 | ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE; |
---|
7466 | 8817 | break; |
---|
7467 | 8818 | case BCM4349_CHIP_GRPID: |
---|
7468 | | - /* RAM base changed from 4349c0(revid=9) onwards */ |
---|
| 8819 | + /* RAM based changed from 4349c0(revid=9) onwards */ |
---|
7469 | 8820 | bus->dongle_ram_base = ((bus->sih->chiprev < 9) ? |
---|
7470 | | - CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9); |
---|
| 8821 | + CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9); |
---|
7471 | 8822 | break; |
---|
7472 | 8823 | case BCM4373_CHIP_ID: |
---|
7473 | 8824 | bus->dongle_ram_base = CR4_4373_RAM_BASE; |
---|
7474 | 8825 | /* Updating F2 Block size to 256 for 4373 to fix TX Transmit |
---|
7475 | | - * Underflow issue during Bi-Directional Traffic |
---|
| 8826 | + * Underflow issue during Bi-Directional Traffic |
---|
7476 | 8827 | */ |
---|
7477 | 8828 | { |
---|
7478 | 8829 | uint fn = 2; |
---|
.. | .. |
---|
7480 | 8831 | if (bcmsdh_iovar_op(sdh, "sd_blocksize", |
---|
7481 | 8832 | NULL, 0, &fn, sizeof(fn), TRUE) != BCME_OK) { |
---|
7482 | 8833 | DHD_ERROR(("%s: Set F2 Block size error\n", |
---|
7483 | | - __FUNCTION__)); |
---|
| 8834 | + __FUNCTION__)); |
---|
7484 | 8835 | goto fail; |
---|
7485 | 8836 | } |
---|
7486 | 8837 | } |
---|
7487 | 8838 | break; |
---|
| 8839 | + case BCM4364_CHIP_ID: |
---|
| 8840 | + bus->dongle_ram_base = CR4_4364_RAM_BASE; |
---|
| 8841 | + break; |
---|
| 8842 | + case BCM4362_CHIP_ID: |
---|
| 8843 | + bus->dongle_ram_base = CR4_4362_RAM_BASE; |
---|
| 8844 | + break; |
---|
| 8845 | + case BCM43751_CHIP_ID: |
---|
| 8846 | + bus->dongle_ram_base = CR4_43751_RAM_BASE; |
---|
| 8847 | + break; |
---|
| 8848 | + case BCM4369_CHIP_ID: |
---|
| 8849 | + bus->dongle_ram_base = CR4_4369_RAM_BASE; |
---|
| 8850 | + break; |
---|
| 8851 | + case CYW55500_CHIP_ID: |
---|
| 8852 | + bus->dongle_ram_base = CR4_55500_RAM_BASE; |
---|
| 8853 | + break; |
---|
| 8854 | + case CYW55560_CHIP_ID: |
---|
| 8855 | + bus->dongle_ram_base = CR4_55560_RAM_BASE; |
---|
| 8856 | + break; |
---|
| 8857 | +#ifdef CHIPS_CUSTOMER_HW6 |
---|
| 8858 | + case BCM4378_CHIP_GRPID: |
---|
| 8859 | + bus->dongle_ram_base = CR4_4378_RAM_BASE; |
---|
| 8860 | + break; |
---|
| 8861 | +#endif /* CHIPS_CUSTOMER_HW6 */ |
---|
7488 | 8862 | default: |
---|
7489 | 8863 | bus->dongle_ram_base = 0; |
---|
7490 | 8864 | DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n", |
---|
7491 | 8865 | __FUNCTION__, bus->dongle_ram_base)); |
---|
7492 | 8866 | } |
---|
7493 | 8867 | } |
---|
| 8868 | + |
---|
| 8869 | + /* 55560, Dedicated space for TCAM patching and TRX Hader at RAMBASE */ |
---|
| 8870 | + /* TCAM Patching - 2048[2K], TRX Header - 32Bytes */ |
---|
| 8871 | + if (bus->sih->chip == CYW55500_CHIP_ID) { |
---|
| 8872 | + bus->orig_ramsize -= (CR4_55500_TCAM_SZ + CR4_55500_TRX_HDR_SZ); |
---|
| 8873 | + } else if (bus->sih->chip == CYW55560_CHIP_ID) { |
---|
| 8874 | + bus->orig_ramsize -= (CR4_55560_TCAM_SZ + CR4_55560_TRX_HDR_SZ); |
---|
| 8875 | + } |
---|
| 8876 | + |
---|
7494 | 8877 | bus->ramsize = bus->orig_ramsize; |
---|
7495 | 8878 | if (dhd_dongle_ramsize) |
---|
7496 | 8879 | dhd_dongle_setramsize(bus, dhd_dongle_ramsize); |
---|
.. | .. |
---|
7502 | 8885 | } |
---|
7503 | 8886 | |
---|
7504 | 8887 | /* ...but normally deal with the SDPCMDEV core */ |
---|
| 8888 | +#ifdef BCMSDIOLITE |
---|
| 8889 | + if (!(bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0))) { |
---|
| 8890 | + DHD_ERROR(("%s: failed to find Chip Common core!\n", __FUNCTION__)); |
---|
| 8891 | + goto fail; |
---|
| 8892 | + } |
---|
| 8893 | +#else |
---|
7505 | 8894 | if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) && |
---|
7506 | 8895 | !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) { |
---|
7507 | 8896 | DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__)); |
---|
7508 | 8897 | goto fail; |
---|
7509 | 8898 | } |
---|
| 8899 | +#endif // endif |
---|
7510 | 8900 | bus->sdpcmrev = si_corerev(bus->sih); |
---|
7511 | 8901 | |
---|
7512 | 8902 | /* Set core control so an SDIO reset does a backplane reset */ |
---|
7513 | 8903 | OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN); |
---|
| 8904 | +#ifndef BCMSPI |
---|
7514 | 8905 | bus->rxint_mode = SDIO_DEVICE_HMB_RXINT; |
---|
7515 | 8906 | |
---|
7516 | 8907 | if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) && |
---|
.. | .. |
---|
7523 | 8914 | val |= CC_XMTDATAAVAIL_CTRL; |
---|
7524 | 8915 | W_REG(osh, &bus->regs->corecontrol, val); |
---|
7525 | 8916 | } |
---|
7526 | | - |
---|
| 8917 | +#endif /* BCMSPI */ |
---|
7527 | 8918 | |
---|
7528 | 8919 | pktq_init(&bus->txq, (PRIOMASK + 1), QLEN); |
---|
7529 | 8920 | |
---|
.. | .. |
---|
7571 | 8962 | goto fail; |
---|
7572 | 8963 | } |
---|
7573 | 8964 | |
---|
7574 | | - bus->membuf = MALLOC(osh, MAX_MEM_BUF); |
---|
7575 | | - if (bus->membuf == NULL) { |
---|
7576 | | - DHD_ERROR(("%s: MALLOC of %d-byte membuf failed\n", __FUNCTION__, MAX_MEM_BUF)); |
---|
7577 | | - if (bus->databuf) { |
---|
7578 | | -#ifndef CONFIG_DHD_USE_STATIC_BUF |
---|
7579 | | - MFREE(osh, bus->databuf, MAX_DATA_BUF); |
---|
7580 | | -#endif |
---|
7581 | | - bus->databuf = NULL; |
---|
7582 | | - } |
---|
7583 | | - if (!bus->rxblen) |
---|
7584 | | - DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen); |
---|
7585 | | - goto fail; |
---|
7586 | | - } |
---|
7587 | | - memset(bus->membuf, 0, MAX_MEM_BUF); |
---|
7588 | | - |
---|
7589 | 8965 | /* Align the buffer */ |
---|
7590 | 8966 | if ((uintptr)bus->databuf % DHD_SDALIGN) |
---|
7591 | 8967 | bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN)); |
---|
.. | .. |
---|
7611 | 8987 | dhdsdio_pktgen_init(bus); |
---|
7612 | 8988 | #endif /* SDTEST */ |
---|
7613 | 8989 | |
---|
7614 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
7615 | | - if(alive == FW_ALIVE_MAGIC) { |
---|
7616 | | - bus->txglom_enable = sd_txglom; |
---|
7617 | | - } else |
---|
7618 | | -#endif /* LOAD_DHD_WITH_FW_ALIVE */ |
---|
7619 | | - { |
---|
7620 | | - /* Disable F2 to clear any intermediate frame state on the dongle */ |
---|
7621 | | - bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); |
---|
7622 | | - } |
---|
| 8990 | +#ifndef BCMSPI |
---|
| 8991 | + /* Disable F2 to clear any intermediate frame state on the dongle */ |
---|
| 8992 | + bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); |
---|
| 8993 | +#endif /* !BCMSPI */ |
---|
7623 | 8994 | |
---|
| 8995 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
7624 | 8996 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
7625 | 8997 | bus->sleeping = FALSE; |
---|
7626 | 8998 | bus->rxflow = FALSE; |
---|
7627 | 8999 | bus->prev_rxlim_hit = 0; |
---|
7628 | 9000 | |
---|
| 9001 | +#ifndef BCMSPI |
---|
7629 | 9002 | /* Done with backplane-dependent accesses, can drop clock... */ |
---|
7630 | 9003 | bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); |
---|
| 9004 | +#endif /* !BCMSPI */ |
---|
7631 | 9005 | |
---|
7632 | 9006 | /* ...and initialize clock/power states */ |
---|
7633 | 9007 | bus->clkstate = CLK_SDONLY; |
---|
.. | .. |
---|
7659 | 9033 | if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32), |
---|
7660 | 9034 | &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { |
---|
7661 | 9035 | bus->blocksize = 0; |
---|
7662 | | - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); |
---|
| 9036 | + DHD_ERROR(("%s: fail on fn %d %s get\n", __FUNCTION__, fnum, "sd_blocksize")); |
---|
7663 | 9037 | } else { |
---|
7664 | | - DHD_INFO(("%s: Initial value for %s is %d\n", |
---|
7665 | | - __FUNCTION__, "sd_blocksize", bus->blocksize)); |
---|
| 9038 | + DHD_INFO(("%s: Initial value for fn %d %s is %d\n", |
---|
| 9039 | + __FUNCTION__, fnum, "sd_blocksize", bus->blocksize)); |
---|
7666 | 9040 | |
---|
7667 | 9041 | dhdsdio_tune_fifoparam(bus); |
---|
7668 | 9042 | } |
---|
.. | .. |
---|
7710 | 9084 | |
---|
7711 | 9085 | ret = dhdsdio_download_firmware(bus, osh, bus->sdh); |
---|
7712 | 9086 | |
---|
| 9087 | +#if defined(BCMSPI) && defined(GSPI_DWORD_MODE) |
---|
| 9088 | + /* Enable the dwordmode in gSPI before first F2 transaction */ |
---|
| 9089 | + if (((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev > 1)) || |
---|
| 9090 | + (bus->sih->chip == BCM43430_CHIP_ID)) { |
---|
| 9091 | + bcmsdh_dwordmode(bus->sdh, TRUE); |
---|
| 9092 | + bus->dwordmode = TRUE; |
---|
| 9093 | + DHD_INFO(("DHD:SPI DWORD mode enabled\n")); |
---|
| 9094 | + } |
---|
| 9095 | +#endif /* defined(BCMSPI) && defined(GSPI_DWORD_MODE) */ |
---|
7713 | 9096 | |
---|
7714 | 9097 | return ret; |
---|
7715 | 9098 | } |
---|
.. | .. |
---|
7719 | 9102 | { |
---|
7720 | 9103 | int ret; |
---|
7721 | 9104 | |
---|
| 9105 | +#if defined(SUPPORT_MULTIPLE_REVISION) |
---|
| 9106 | + if (concate_revision(bus, bus->fw_path, bus->nv_path) != 0) { |
---|
| 9107 | + DHD_ERROR(("%s: fail to concatnate revison \n", |
---|
| 9108 | + __FUNCTION__)); |
---|
| 9109 | + return BCME_BADARG; |
---|
| 9110 | + } |
---|
| 9111 | +#endif /* SUPPORT_MULTIPLE_REVISION */ |
---|
| 9112 | + |
---|
| 9113 | +#if defined(DHD_BLOB_EXISTENCE_CHECK) |
---|
| 9114 | + dhd_set_blob_support(bus->dhd, bus->fw_path); |
---|
| 9115 | +#endif /* DHD_BLOB_EXISTENCE_CHECK */ |
---|
7722 | 9116 | |
---|
7723 | 9117 | DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n", |
---|
7724 | 9118 | __FUNCTION__, bus->fw_path, bus->nv_path)); |
---|
.. | .. |
---|
7727 | 9121 | /* Download the firmware */ |
---|
7728 | 9122 | dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); |
---|
7729 | 9123 | |
---|
7730 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
7731 | | - if(alive == FW_ALIVE_MAGIC) { |
---|
7732 | | - ret = 0; |
---|
7733 | | - bus->alp_only = FALSE; |
---|
7734 | | - bus->dhd->busstate = DHD_BUS_LOAD; |
---|
7735 | | - DHD_ERROR(("skip download FW and nv\n")); |
---|
7736 | | - } |
---|
7737 | | - else |
---|
7738 | | -#endif |
---|
7739 | | - ret = _dhdsdio_download_firmware(bus); |
---|
| 9124 | + ret = _dhdsdio_download_firmware(bus); |
---|
7740 | 9125 | |
---|
7741 | 9126 | dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); |
---|
7742 | 9127 | |
---|
.. | .. |
---|
7755 | 9140 | ASSERT(osh); |
---|
7756 | 9141 | |
---|
7757 | 9142 | if (bus->dhd) { |
---|
| 9143 | +#if defined(DEBUGGER) || defined(DHD_DSCOPE) |
---|
| 9144 | + debugger_close(); |
---|
| 9145 | +#endif /* DEBUGGER || DHD_DSCOPE */ |
---|
7758 | 9146 | dongle_isolation = bus->dhd->dongle_isolation; |
---|
7759 | 9147 | dhd_detach(bus->dhd); |
---|
7760 | 9148 | } |
---|
.. | .. |
---|
7774 | 9162 | #ifdef DHD_DEBUG |
---|
7775 | 9163 | if (bus->console.buf != NULL) |
---|
7776 | 9164 | MFREE(osh, bus->console.buf, bus->console.bufsize); |
---|
7777 | | -#endif |
---|
| 9165 | +#endif // endif |
---|
7778 | 9166 | |
---|
7779 | 9167 | #ifdef DHDENABLE_TAILPAD |
---|
7780 | 9168 | if (bus->pad_pkt) |
---|
.. | .. |
---|
7798 | 9186 | if (bus->rxbuf) { |
---|
7799 | 9187 | #ifndef CONFIG_DHD_USE_STATIC_BUF |
---|
7800 | 9188 | MFREE(osh, bus->rxbuf, bus->rxblen); |
---|
7801 | | -#endif |
---|
| 9189 | +#endif // endif |
---|
7802 | 9190 | bus->rxctl = bus->rxbuf = NULL; |
---|
7803 | 9191 | bus->rxlen = 0; |
---|
7804 | 9192 | } |
---|
.. | .. |
---|
7806 | 9194 | if (bus->databuf) { |
---|
7807 | 9195 | #ifndef CONFIG_DHD_USE_STATIC_BUF |
---|
7808 | 9196 | MFREE(osh, bus->databuf, MAX_DATA_BUF); |
---|
7809 | | -#endif |
---|
| 9197 | +#endif // endif |
---|
7810 | 9198 | bus->databuf = NULL; |
---|
7811 | | - } |
---|
7812 | | - |
---|
7813 | | - if (bus->membuf) { |
---|
7814 | | - MFREE(osh, bus->membuf, MAX_DATA_BUF); |
---|
7815 | | - bus->membuf = NULL; |
---|
7816 | 9199 | } |
---|
7817 | 9200 | |
---|
7818 | 9201 | if (bus->vars && bus->varsz) { |
---|
.. | .. |
---|
7822 | 9205 | |
---|
7823 | 9206 | } |
---|
7824 | 9207 | |
---|
7825 | | - |
---|
7826 | 9208 | static void |
---|
7827 | 9209 | dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag) |
---|
7828 | 9210 | { |
---|
| 9211 | +#if !defined(BCMLXSDMMC) |
---|
| 9212 | + int32 bcmerror = BCME_ERROR; |
---|
| 9213 | +#endif // endif |
---|
| 9214 | + |
---|
7829 | 9215 | DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__, |
---|
7830 | 9216 | bus->dhd, bus->dhd->dongle_reset)); |
---|
7831 | 9217 | |
---|
.. | .. |
---|
7833 | 9219 | return; |
---|
7834 | 9220 | |
---|
7835 | 9221 | if (bus->sih) { |
---|
| 9222 | + /* In Win10, system will be BSOD if using "sysprep" to do OS image */ |
---|
| 9223 | + /* Skip this will not cause the BSOD. */ |
---|
7836 | 9224 | #if !defined(BCMLXSDMMC) |
---|
7837 | 9225 | if (bus->dhd) { |
---|
7838 | 9226 | dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); |
---|
7839 | 9227 | } |
---|
7840 | | - if (KSO_ENAB(bus) && (dongle_isolation == FALSE)) |
---|
7841 | | - si_watchdog(bus->sih, 4); |
---|
| 9228 | + if (KSO_ENAB(bus) && (dongle_isolation == FALSE)) { |
---|
| 9229 | + if (bus->secureboot) { |
---|
| 9230 | + /* |
---|
| 9231 | + * CYW555x0 - As part of watchdog reset, ARM gets |
---|
| 9232 | + * reset and bootloader starts from fresh, |
---|
| 9233 | + * So, pre wd reset sequcnce defined to make |
---|
| 9234 | + * sure H2D regs are initialized to zero |
---|
| 9235 | + */ |
---|
| 9236 | + if ((bcmerror = |
---|
| 9237 | + dhdsdio_dongle_host_pre_wd_reset_sequence(bus))) |
---|
| 9238 | + { |
---|
| 9239 | + DHD_ERROR(("%s: error %d pre wd reset seq.\n", |
---|
| 9240 | + __FUNCTION__, bcmerror)); |
---|
| 9241 | + } |
---|
| 9242 | + } |
---|
| 9243 | + |
---|
| 9244 | + if (bus->chipidpresent) { |
---|
| 9245 | + /* |
---|
| 9246 | + * Configure registers to trigger WLAN reset on |
---|
| 9247 | + * "SDIO Soft Reset", and set RES bit to trigger SDIO as |
---|
| 9248 | + * well as WLAN reset (instead of using PMU/CC Watchdog register) |
---|
| 9249 | + */ |
---|
| 9250 | + uint8 cardctl; |
---|
| 9251 | + cardctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, |
---|
| 9252 | + SDIOD_CCCR_BRCM_CARDCTL, &bcmerror); |
---|
| 9253 | + cardctl |= SDIOD_CCCR_BRCM_WLANRST_ONF0ABORT; |
---|
| 9254 | + if (!bcmerror) { |
---|
| 9255 | + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, |
---|
| 9256 | + SDIOD_CCCR_BRCM_CARDCTL, cardctl, |
---|
| 9257 | + &bcmerror); |
---|
| 9258 | + } |
---|
| 9259 | + if (!bcmerror) { |
---|
| 9260 | + bcmerror = bcmsdh_abort(bus->sdh, SDIO_FUNC_0 | 0x8); |
---|
| 9261 | + DHD_ERROR(("%s: Set WLANRST in cardctl error %d\n", |
---|
| 9262 | + __FUNCTION__, bcmerror)); |
---|
| 9263 | + } |
---|
| 9264 | + } else { |
---|
| 9265 | + si_watchdog(bus->sih, 4); |
---|
| 9266 | + } |
---|
| 9267 | + |
---|
| 9268 | + } |
---|
7842 | 9269 | #endif /* !defined(BCMLXSDMMC) */ |
---|
7843 | 9270 | if (bus->dhd) { |
---|
7844 | 9271 | dhdsdio_clkctl(bus, CLK_NONE, FALSE); |
---|
.. | .. |
---|
7860 | 9287 | |
---|
7861 | 9288 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
7862 | 9289 | |
---|
7863 | | - |
---|
| 9290 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 9291 | + if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { |
---|
| 9292 | + DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__)); |
---|
| 9293 | + } else { |
---|
| 9294 | + DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__)); |
---|
| 9295 | + } |
---|
| 9296 | + mutex_lock(&_dhd_sdio_mutex_lock_); |
---|
| 9297 | +#endif // endif |
---|
7864 | 9298 | |
---|
7865 | 9299 | if (bus) { |
---|
7866 | 9300 | ASSERT(bus->dhd); |
---|
| 9301 | + /* Advertise bus cleanup during rmmod */ |
---|
| 9302 | + dhdsdio_advertise_bus_cleanup(bus->dhd); |
---|
7867 | 9303 | dhdsdio_release(bus, bus->dhd->osh); |
---|
7868 | 9304 | } |
---|
7869 | 9305 | |
---|
7870 | | - |
---|
| 9306 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 9307 | + mutex_unlock(&_dhd_sdio_mutex_lock_); |
---|
| 9308 | + DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); |
---|
| 9309 | +#endif /* LINUX */ |
---|
7871 | 9310 | |
---|
7872 | 9311 | DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); |
---|
7873 | 9312 | } |
---|
.. | .. |
---|
7876 | 9315 | dhdsdio_suspend(void *context) |
---|
7877 | 9316 | { |
---|
7878 | 9317 | int ret = 0; |
---|
7879 | | -#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16) |
---|
| 9318 | +#ifdef SUPPORT_P2P_GO_PS |
---|
7880 | 9319 | int wait_time = 0; |
---|
7881 | 9320 | #endif /* SUPPORT_P2P_GO_PS */ |
---|
7882 | 9321 | |
---|
7883 | 9322 | dhd_bus_t *bus = (dhd_bus_t*)context; |
---|
7884 | 9323 | unsigned long flags; |
---|
7885 | 9324 | |
---|
| 9325 | + DHD_ERROR(("%s Enter\n", __FUNCTION__)); |
---|
7886 | 9326 | if (bus->dhd == NULL) { |
---|
7887 | 9327 | DHD_ERROR(("bus not inited\n")); |
---|
7888 | 9328 | return BCME_ERROR; |
---|
.. | .. |
---|
7891 | 9331 | DHD_ERROR(("prot is not inited\n")); |
---|
7892 | 9332 | return BCME_ERROR; |
---|
7893 | 9333 | } |
---|
7894 | | - //added by May 20190628 |
---|
| 9334 | + |
---|
7895 | 9335 | if (bus->dhd->up == FALSE) { |
---|
7896 | 9336 | return BCME_OK; |
---|
7897 | 9337 | } |
---|
7898 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9338 | + |
---|
| 9339 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
7899 | 9340 | if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) { |
---|
7900 | 9341 | DHD_ERROR(("not in a readystate to LPBK is not inited\n")); |
---|
7901 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9342 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7902 | 9343 | return BCME_ERROR; |
---|
7903 | 9344 | } |
---|
7904 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9345 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7905 | 9346 | if (bus->dhd->dongle_reset) { |
---|
7906 | 9347 | DHD_ERROR(("Dongle is in reset state.\n")); |
---|
7907 | 9348 | return -EIO; |
---|
7908 | 9349 | } |
---|
7909 | 9350 | |
---|
7910 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9351 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9352 | + /* stop all interface network queue. */ |
---|
| 9353 | + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); |
---|
7911 | 9354 | bus->dhd->busstate = DHD_BUS_SUSPEND; |
---|
7912 | | - if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_IN_TX) { |
---|
| 9355 | + if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) { |
---|
7913 | 9356 | DHD_ERROR(("Tx Request is not ended\n")); |
---|
7914 | 9357 | bus->dhd->busstate = DHD_BUS_DATA; |
---|
7915 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9358 | + /* resume all interface network queue. */ |
---|
| 9359 | + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); |
---|
| 9360 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7916 | 9361 | return -EBUSY; |
---|
7917 | 9362 | } |
---|
7918 | | - bus->dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_SUSPEND; |
---|
7919 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9363 | + DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd); |
---|
| 9364 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7920 | 9365 | |
---|
7921 | | -#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16) |
---|
| 9366 | +#ifdef SUPPORT_P2P_GO_PS |
---|
7922 | 9367 | if (bus->idletime > 0) { |
---|
7923 | 9368 | wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms); |
---|
7924 | 9369 | } |
---|
7925 | 9370 | #endif /* SUPPORT_P2P_GO_PS */ |
---|
7926 | 9371 | ret = dhd_os_check_wakelock(bus->dhd); |
---|
7927 | | -#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16) |
---|
7928 | | - if ((ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) { |
---|
| 9372 | +#ifdef SUPPORT_P2P_GO_PS |
---|
| 9373 | + if ((!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) { |
---|
7929 | 9374 | if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) { |
---|
7930 | 9375 | if (!bus->sleeping) { |
---|
7931 | | - bus->dhd->busstate = DHD_BUS_DATA; |
---|
7932 | | - return 1; |
---|
| 9376 | + ret = 1; |
---|
7933 | 9377 | } |
---|
7934 | 9378 | } |
---|
7935 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
7936 | | - bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SUSPEND; |
---|
7937 | | - dhd_os_busbusy_wake(bus->dhd); |
---|
7938 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7939 | | - return 0; |
---|
7940 | 9379 | } |
---|
7941 | 9380 | #endif /* SUPPORT_P2P_GO_PS */ |
---|
7942 | 9381 | |
---|
7943 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
7944 | | - bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SUSPEND; |
---|
| 9382 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9383 | + if (ret) { |
---|
| 9384 | + bus->dhd->busstate = DHD_BUS_DATA; |
---|
| 9385 | + /* resume all interface network queue. */ |
---|
| 9386 | + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); |
---|
| 9387 | + } |
---|
| 9388 | + DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd); |
---|
7945 | 9389 | dhd_os_busbusy_wake(bus->dhd); |
---|
7946 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9390 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7947 | 9391 | return ret; |
---|
7948 | 9392 | } |
---|
7949 | 9393 | |
---|
.. | .. |
---|
7951 | 9395 | dhdsdio_resume(void *context) |
---|
7952 | 9396 | { |
---|
7953 | 9397 | dhd_bus_t *bus = (dhd_bus_t*)context; |
---|
7954 | | - unsigned long flags; |
---|
| 9398 | + ulong flags; |
---|
7955 | 9399 | |
---|
7956 | | - //added by May 20190628 |
---|
| 9400 | + DHD_ERROR(("%s Enter\n", __FUNCTION__)); |
---|
| 9401 | + |
---|
7957 | 9402 | if (bus->dhd->up == FALSE) { |
---|
7958 | 9403 | return BCME_OK; |
---|
7959 | 9404 | } |
---|
7960 | 9405 | |
---|
7961 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
7962 | | - bus->dhd->busstate = DHD_BUS_DATA; |
---|
7963 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9406 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9407 | + DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd); |
---|
| 9408 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
7964 | 9409 | |
---|
7965 | | -#if defined(OOB_INTR_ONLY) |
---|
| 9410 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
7966 | 9411 | if (dhd_os_check_if_up(bus->dhd)) |
---|
7967 | 9412 | bcmsdh_oob_intr_set(bus->sdh, TRUE); |
---|
7968 | | -#endif |
---|
| 9413 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
| 9414 | + |
---|
| 9415 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9416 | + DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd); |
---|
| 9417 | + bus->dhd->busstate = DHD_BUS_DATA; |
---|
| 9418 | + dhd_os_busbusy_wake(bus->dhd); |
---|
| 9419 | + /* resume all interface network queue. */ |
---|
| 9420 | + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); |
---|
| 9421 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9422 | + |
---|
7969 | 9423 | return 0; |
---|
7970 | 9424 | } |
---|
7971 | | - |
---|
7972 | 9425 | |
---|
7973 | 9426 | /* Register/Unregister functions are called by the main DHD entry |
---|
7974 | 9427 | * point (e.g. module insertion) to link with the bus driver, in |
---|
.. | .. |
---|
8011 | 9464 | } |
---|
8012 | 9465 | #endif /* defined(BCMLXSDMMC) */ |
---|
8013 | 9466 | |
---|
8014 | | -#ifdef BCMEMBEDIMAGE |
---|
8015 | | -static int |
---|
8016 | | -dhdsdio_download_code_array(struct dhd_bus *bus) |
---|
8017 | | -{ |
---|
8018 | | - int bcmerror = -1; |
---|
8019 | | - int offset = 0; |
---|
8020 | | - unsigned char *ularray = NULL; |
---|
8021 | | - |
---|
8022 | | - DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__)); |
---|
8023 | | - |
---|
8024 | | - /* Download image */ |
---|
8025 | | - while ((offset + MEMBLOCK) < sizeof(dlarray)) { |
---|
8026 | | - /* check if CR4 */ |
---|
8027 | | - if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { |
---|
8028 | | - /* if address is 0, store the reset instruction to be written in 0 */ |
---|
8029 | | - |
---|
8030 | | - if (offset == 0) { |
---|
8031 | | - bus->resetinstr = *(((uint32*)dlarray)); |
---|
8032 | | - /* Add start of RAM address to the address given by user */ |
---|
8033 | | - offset += bus->dongle_ram_base; |
---|
8034 | | - } |
---|
8035 | | - } |
---|
8036 | | - |
---|
8037 | | - bcmerror = dhdsdio_membytes(bus, TRUE, offset, |
---|
8038 | | - (uint8 *) (dlarray + offset), MEMBLOCK); |
---|
8039 | | - if (bcmerror) { |
---|
8040 | | - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
8041 | | - __FUNCTION__, bcmerror, MEMBLOCK, offset)); |
---|
8042 | | - goto err; |
---|
8043 | | - } |
---|
8044 | | - |
---|
8045 | | - offset += MEMBLOCK; |
---|
8046 | | - } |
---|
8047 | | - |
---|
8048 | | - if (offset < sizeof(dlarray)) { |
---|
8049 | | - bcmerror = dhdsdio_membytes(bus, TRUE, offset, |
---|
8050 | | - (uint8 *) (dlarray + offset), sizeof(dlarray) - offset); |
---|
8051 | | - if (bcmerror) { |
---|
8052 | | - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
8053 | | - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); |
---|
8054 | | - goto err; |
---|
8055 | | - } |
---|
8056 | | - } |
---|
8057 | | - |
---|
8058 | | -#ifdef DHD_DEBUG |
---|
8059 | | - /* Upload and compare the downloaded code */ |
---|
8060 | | - { |
---|
8061 | | - ularray = MALLOC(bus->dhd->osh, bus->ramsize); |
---|
8062 | | - /* Upload image to verify downloaded contents. */ |
---|
8063 | | - offset = 0; |
---|
8064 | | - memset(ularray, 0xaa, bus->ramsize); |
---|
8065 | | - while ((offset + MEMBLOCK) < sizeof(dlarray)) { |
---|
8066 | | - bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK); |
---|
8067 | | - if (bcmerror) { |
---|
8068 | | - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", |
---|
8069 | | - __FUNCTION__, bcmerror, MEMBLOCK, offset)); |
---|
8070 | | - goto err; |
---|
8071 | | - } |
---|
8072 | | - |
---|
8073 | | - offset += MEMBLOCK; |
---|
8074 | | - } |
---|
8075 | | - |
---|
8076 | | - if (offset < sizeof(dlarray)) { |
---|
8077 | | - bcmerror = dhdsdio_membytes(bus, FALSE, offset, |
---|
8078 | | - ularray + offset, sizeof(dlarray) - offset); |
---|
8079 | | - if (bcmerror) { |
---|
8080 | | - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", |
---|
8081 | | - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); |
---|
8082 | | - goto err; |
---|
8083 | | - } |
---|
8084 | | - } |
---|
8085 | | - |
---|
8086 | | - if (memcmp(dlarray, ularray, sizeof(dlarray))) { |
---|
8087 | | - DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n", |
---|
8088 | | - __FUNCTION__, dlimagename, dlimagever, dlimagedate)); |
---|
8089 | | - goto err; |
---|
8090 | | - } else |
---|
8091 | | - DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n", |
---|
8092 | | - __FUNCTION__, dlimagename, dlimagever, dlimagedate)); |
---|
8093 | | - |
---|
8094 | | - } |
---|
8095 | | -#endif /* DHD_DEBUG */ |
---|
8096 | | - |
---|
8097 | | -err: |
---|
8098 | | - if (ularray) |
---|
8099 | | - MFREE(bus->dhd->osh, ularray, bus->ramsize); |
---|
8100 | | - return bcmerror; |
---|
8101 | | -} |
---|
8102 | | -#endif /* BCMEMBEDIMAGE */ |
---|
8103 | | - |
---|
8104 | 9467 | static int |
---|
8105 | 9468 | dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) |
---|
8106 | 9469 | { |
---|
.. | .. |
---|
8110 | 9473 | void *image = NULL; |
---|
8111 | 9474 | uint8 *memblock = NULL, *memptr; |
---|
8112 | 9475 | uint memblock_size = MEMBLOCK; |
---|
| 9476 | + struct trx_header *trx_hdr; |
---|
| 9477 | + bool trx_chk = TRUE; |
---|
8113 | 9478 | #ifdef DHD_DEBUG_DOWNLOADTIME |
---|
8114 | 9479 | unsigned long initial_jiffies = 0; |
---|
8115 | 9480 | uint firmware_sz = 0; |
---|
8116 | | -#endif |
---|
| 9481 | +#endif // endif |
---|
8117 | 9482 | |
---|
8118 | 9483 | DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path)); |
---|
8119 | 9484 | |
---|
8120 | | - image = dhd_os_open_image(pfw_path); |
---|
8121 | | - if (image == NULL) |
---|
| 9485 | + image = dhd_os_open_image1(bus->dhd, pfw_path); |
---|
| 9486 | + if (image == NULL) { |
---|
| 9487 | + DHD_ERROR(("%s: Failed to open fw file !\n", __FUNCTION__)); |
---|
8122 | 9488 | goto err; |
---|
| 9489 | + } |
---|
8123 | 9490 | |
---|
8124 | 9491 | /* Update the dongle image download block size depending on the F1 block size */ |
---|
8125 | 9492 | if (sd_f1_blocksize == 512) |
---|
8126 | 9493 | memblock_size = MAX_MEMBLOCK; |
---|
8127 | | - |
---|
8128 | 9494 | memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN); |
---|
8129 | 9495 | if (memblock == NULL) { |
---|
8130 | 9496 | DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, |
---|
.. | .. |
---|
8136 | 9502 | |
---|
8137 | 9503 | #ifdef DHD_DEBUG_DOWNLOADTIME |
---|
8138 | 9504 | initial_jiffies = jiffies; |
---|
8139 | | -#endif |
---|
| 9505 | +#endif // endif |
---|
8140 | 9506 | |
---|
8141 | 9507 | /* Download image */ |
---|
8142 | 9508 | while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) { |
---|
.. | .. |
---|
8156 | 9522 | } |
---|
8157 | 9523 | } |
---|
8158 | 9524 | |
---|
| 9525 | + /* Check for trx file */ |
---|
| 9526 | + if (trx_chk && (len >= sizeof(struct trx_header))) { |
---|
| 9527 | + trx_chk = FALSE; |
---|
| 9528 | + trx_hdr = (struct trx_header *)memptr; |
---|
| 9529 | + if (trx_hdr->magic == TRX_MAGIC) { |
---|
| 9530 | + /* CYW555x0, we need to write TRX header at RAMSTART */ |
---|
| 9531 | + offset -= sizeof(struct trx_header); |
---|
| 9532 | + } |
---|
| 9533 | + } |
---|
| 9534 | + |
---|
8159 | 9535 | bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); |
---|
8160 | 9536 | if (bcmerror) { |
---|
8161 | 9537 | DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
.. | .. |
---|
8166 | 9542 | offset += memblock_size; |
---|
8167 | 9543 | #ifdef DHD_DEBUG_DOWNLOADTIME |
---|
8168 | 9544 | firmware_sz += len; |
---|
8169 | | -#endif |
---|
| 9545 | +#endif // endif |
---|
8170 | 9546 | } |
---|
8171 | 9547 | |
---|
8172 | 9548 | #ifdef DHD_DEBUG_DOWNLOADTIME |
---|
8173 | 9549 | DHD_ERROR(("Firmware download time for %u bytes: %u ms\n", |
---|
8174 | 9550 | firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies))); |
---|
8175 | | -#endif |
---|
| 9551 | +#endif // endif |
---|
8176 | 9552 | |
---|
8177 | 9553 | err: |
---|
8178 | 9554 | if (memblock) |
---|
8179 | 9555 | MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN); |
---|
8180 | 9556 | |
---|
8181 | 9557 | if (image) |
---|
8182 | | - dhd_os_close_image(image); |
---|
| 9558 | + dhd_os_close_image1(bus->dhd, image); |
---|
8183 | 9559 | |
---|
8184 | 9560 | return bcmerror; |
---|
8185 | 9561 | } |
---|
8186 | 9562 | |
---|
| 9563 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 9564 | +/* Currently supported only for the chips in which ucode RAM is AXI addressable */ |
---|
| 9565 | +static uint32 |
---|
| 9566 | +dhdsdio_ucode_base(struct dhd_bus *bus) |
---|
| 9567 | +{ |
---|
| 9568 | + uint32 ucode_base = 0; |
---|
| 9569 | + |
---|
| 9570 | + switch ((uint16)bus->sih->chip) { |
---|
| 9571 | + case BCM43012_CHIP_ID: |
---|
| 9572 | + ucode_base = 0xE8020000; |
---|
| 9573 | + break; |
---|
| 9574 | + default: |
---|
| 9575 | + DHD_ERROR(("%s: Unsupported!\n", __func__)); |
---|
| 9576 | + break; |
---|
| 9577 | + } |
---|
| 9578 | + |
---|
| 9579 | + return ucode_base; |
---|
| 9580 | +} |
---|
| 9581 | + |
---|
| 9582 | +static int |
---|
| 9583 | +dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path) |
---|
| 9584 | +{ |
---|
| 9585 | + int bcmerror = -1; |
---|
| 9586 | + int offset = 0; |
---|
| 9587 | + int len; |
---|
| 9588 | + uint32 ucode_base; |
---|
| 9589 | + void *image = NULL; |
---|
| 9590 | + uint8 *memblock = NULL, *memptr; |
---|
| 9591 | + uint memblock_size = MEMBLOCK; |
---|
| 9592 | +#ifdef DHD_DEBUG_DOWNLOADTIME |
---|
| 9593 | + unsigned long initial_jiffies = 0; |
---|
| 9594 | + uint firmware_sz = 0; |
---|
| 9595 | +#endif // endif |
---|
| 9596 | + |
---|
| 9597 | + DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, ucode_path)); |
---|
| 9598 | + |
---|
| 9599 | + ucode_base = dhdsdio_ucode_base(bus); |
---|
| 9600 | + |
---|
| 9601 | + image = dhd_os_open_image1(bus->dhd, ucode_path); |
---|
| 9602 | + if (image == NULL) |
---|
| 9603 | + goto err; |
---|
| 9604 | + |
---|
| 9605 | + /* Update the dongle image download block size depending on the F1 block size */ |
---|
| 9606 | + if (sd_f1_blocksize == 512) |
---|
| 9607 | + memblock_size = MAX_MEMBLOCK; |
---|
| 9608 | + |
---|
| 9609 | + memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN); |
---|
| 9610 | + if (memblock == NULL) { |
---|
| 9611 | + DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, |
---|
| 9612 | + memblock_size)); |
---|
| 9613 | + goto err; |
---|
| 9614 | + } |
---|
| 9615 | + if ((uint32)(uintptr)memblock % DHD_SDALIGN) |
---|
| 9616 | + memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); |
---|
| 9617 | + |
---|
| 9618 | +#ifdef DHD_DEBUG_DOWNLOADTIME |
---|
| 9619 | + initial_jiffies = jiffies; |
---|
| 9620 | +#endif // endif |
---|
| 9621 | + |
---|
| 9622 | + /* Download image */ |
---|
| 9623 | + while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) { |
---|
| 9624 | + if (len < 0) { |
---|
| 9625 | + DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len)); |
---|
| 9626 | + bcmerror = BCME_ERROR; |
---|
| 9627 | + goto err; |
---|
| 9628 | + } |
---|
| 9629 | + |
---|
| 9630 | + bcmerror = dhdsdio_membytes(bus, TRUE, (ucode_base + offset), memptr, len); |
---|
| 9631 | + if (bcmerror) { |
---|
| 9632 | + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
| 9633 | + __FUNCTION__, bcmerror, memblock_size, offset)); |
---|
| 9634 | + goto err; |
---|
| 9635 | + } |
---|
| 9636 | + |
---|
| 9637 | + offset += memblock_size; |
---|
| 9638 | +#ifdef DHD_DEBUG_DOWNLOADTIME |
---|
| 9639 | + firmware_sz += len; |
---|
| 9640 | +#endif // endif |
---|
| 9641 | + } |
---|
| 9642 | + |
---|
| 9643 | +#ifdef DHD_DEBUG_DOWNLOADTIME |
---|
| 9644 | + DHD_ERROR(("ucode download time for %u bytes: %u ms\n", |
---|
| 9645 | + firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies))); |
---|
| 9646 | +#endif // endif |
---|
| 9647 | + |
---|
| 9648 | +err: |
---|
| 9649 | + if (memblock) |
---|
| 9650 | + MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN); |
---|
| 9651 | + |
---|
| 9652 | + if (image) |
---|
| 9653 | + dhd_os_close_image1(bus->dhd, image); |
---|
| 9654 | + |
---|
| 9655 | + return bcmerror; |
---|
| 9656 | +} /* dhdsdio_download_ucode_file */ |
---|
| 9657 | + |
---|
| 9658 | +void |
---|
| 9659 | +dhd_bus_ucode_download(struct dhd_bus *bus) |
---|
| 9660 | +{ |
---|
| 9661 | + uint32 shaddr = 0, shdata = 0; |
---|
| 9662 | + |
---|
| 9663 | + shaddr = bus->dongle_ram_base + bus->ramsize - 4; |
---|
| 9664 | + dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&shdata, 4); |
---|
| 9665 | + |
---|
| 9666 | + DHD_TRACE(("%s: shdata:[0x%08x :0x%08x]\n", __func__, shaddr, shdata)); |
---|
| 9667 | + |
---|
| 9668 | + if (shdata == UCODE_DOWNLOAD_REQUEST) |
---|
| 9669 | + { |
---|
| 9670 | + DHD_ERROR(("%s: Received ucode download request!\n", __func__)); |
---|
| 9671 | + |
---|
| 9672 | + /* Download the ucode */ |
---|
| 9673 | + if (!dhd_get_ucode_path(bus->dhd)) { |
---|
| 9674 | + DHD_ERROR(("%s: bus->uc_path not set!\n", __func__)); |
---|
| 9675 | + return; |
---|
| 9676 | + } |
---|
| 9677 | + dhdsdio_download_ucode_file(bus, dhd_get_ucode_path(bus->dhd)); |
---|
| 9678 | + |
---|
| 9679 | + DHD_ERROR(("%s: Ucode downloaded successfully!\n", __func__)); |
---|
| 9680 | + |
---|
| 9681 | + shdata = UCODE_DOWNLOAD_COMPLETE; |
---|
| 9682 | + dhdsdio_membytes(bus, TRUE, shaddr, (uint8 *)&shdata, 4); |
---|
| 9683 | + } |
---|
| 9684 | +} |
---|
| 9685 | + |
---|
| 9686 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
8187 | 9687 | |
---|
8188 | 9688 | static int |
---|
8189 | 9689 | dhdsdio_download_nvram(struct dhd_bus *bus) |
---|
.. | .. |
---|
8202 | 9702 | |
---|
8203 | 9703 | /* For Get nvram from UEFI */ |
---|
8204 | 9704 | if (nvram_file_exists) |
---|
8205 | | - image = dhd_os_open_image(pnv_path); |
---|
| 9705 | + image = dhd_os_open_image1(bus->dhd, pnv_path); |
---|
8206 | 9706 | |
---|
8207 | 9707 | memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE); |
---|
8208 | 9708 | if (memblock == NULL) { |
---|
.. | .. |
---|
8229 | 9729 | DHD_ERROR(("%s: error downloading vars: %d\n", |
---|
8230 | 9730 | __FUNCTION__, bcmerror)); |
---|
8231 | 9731 | } |
---|
8232 | | - } |
---|
8233 | | - else { |
---|
| 9732 | + } else { |
---|
8234 | 9733 | DHD_ERROR(("%s: error reading nvram file: %d\n", |
---|
8235 | 9734 | __FUNCTION__, len)); |
---|
8236 | 9735 | bcmerror = BCME_SDIO_ERROR; |
---|
.. | .. |
---|
8241 | 9740 | MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE); |
---|
8242 | 9741 | |
---|
8243 | 9742 | if (image) |
---|
8244 | | - dhd_os_close_image(image); |
---|
| 9743 | + dhd_os_close_image1(bus->dhd, image); |
---|
8245 | 9744 | |
---|
8246 | 9745 | return bcmerror; |
---|
8247 | 9746 | } |
---|
.. | .. |
---|
8256 | 9755 | |
---|
8257 | 9756 | /* Out immediately if no image to download */ |
---|
8258 | 9757 | if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { |
---|
8259 | | -#ifdef BCMEMBEDIMAGE |
---|
8260 | | - embed = TRUE; |
---|
8261 | | -#else |
---|
8262 | | - return 0; |
---|
8263 | | -#endif |
---|
| 9758 | + return bcmerror; |
---|
8264 | 9759 | } |
---|
8265 | 9760 | |
---|
8266 | 9761 | /* Keep arm in reset */ |
---|
.. | .. |
---|
8273 | 9768 | if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { |
---|
8274 | 9769 | if (dhdsdio_download_code_file(bus, bus->fw_path)) { |
---|
8275 | 9770 | DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__)); |
---|
8276 | | -#ifdef BCMEMBEDIMAGE |
---|
8277 | | - embed = TRUE; |
---|
8278 | | -#else |
---|
8279 | 9771 | goto err; |
---|
8280 | | -#endif |
---|
8281 | | - } |
---|
8282 | | - else { |
---|
| 9772 | + } else { |
---|
8283 | 9773 | embed = FALSE; |
---|
8284 | 9774 | dlok = TRUE; |
---|
8285 | 9775 | } |
---|
8286 | 9776 | } |
---|
8287 | 9777 | |
---|
8288 | | -#ifdef BCMEMBEDIMAGE |
---|
8289 | | - if (embed) { |
---|
8290 | | - if (dhdsdio_download_code_array(bus)) { |
---|
8291 | | - DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__)); |
---|
8292 | | - goto err; |
---|
8293 | | - } |
---|
8294 | | - else { |
---|
8295 | | - dlok = TRUE; |
---|
8296 | | - } |
---|
8297 | | - } |
---|
8298 | | -#else |
---|
8299 | 9778 | BCM_REFERENCE(embed); |
---|
8300 | | -#endif |
---|
8301 | 9779 | if (!dlok) { |
---|
8302 | 9780 | DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__)); |
---|
8303 | 9781 | goto err; |
---|
.. | .. |
---|
8323 | 9801 | |
---|
8324 | 9802 | static int |
---|
8325 | 9803 | dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, |
---|
8326 | | - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) |
---|
| 9804 | + void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle) |
---|
8327 | 9805 | { |
---|
8328 | 9806 | int status; |
---|
8329 | 9807 | |
---|
.. | .. |
---|
8332 | 9810 | return BCME_NODEVICE; |
---|
8333 | 9811 | } |
---|
8334 | 9812 | |
---|
8335 | | - status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle); |
---|
| 9813 | + status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete_fn, handle); |
---|
8336 | 9814 | |
---|
8337 | 9815 | return status; |
---|
8338 | 9816 | } |
---|
8339 | 9817 | |
---|
8340 | 9818 | static int |
---|
8341 | 9819 | dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, |
---|
8342 | | - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry) |
---|
| 9820 | + void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle, int max_retry) |
---|
8343 | 9821 | { |
---|
8344 | 9822 | int ret; |
---|
8345 | 9823 | int i = 0; |
---|
.. | .. |
---|
8353 | 9831 | |
---|
8354 | 9832 | sdh = bus->sdh; |
---|
8355 | 9833 | do { |
---|
| 9834 | + if (fn == 2) |
---|
| 9835 | + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_CHIP_CTRL_DATA, 0x80, NULL); |
---|
| 9836 | + |
---|
8356 | 9837 | ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes, |
---|
8357 | | - pkt, complete, handle); |
---|
| 9838 | + pkt, complete_fn, handle); |
---|
8358 | 9839 | |
---|
8359 | 9840 | bus->f2txdata++; |
---|
8360 | 9841 | ASSERT(ret != BCME_PENDING); |
---|
.. | .. |
---|
8457 | 9938 | unsigned long flags; |
---|
8458 | 9939 | int timeleft; |
---|
8459 | 9940 | |
---|
8460 | | - DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 9941 | + DHD_LINUX_GENERAL_LOCK(dhdp, flags); |
---|
8461 | 9942 | dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS; |
---|
8462 | | - DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 9943 | + DHD_LINUX_GENERAL_UNLOCK(dhdp, flags); |
---|
8463 | 9944 | |
---|
8464 | 9945 | timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state); |
---|
8465 | | - if (timeleft == 0) { |
---|
| 9946 | + if ((timeleft == 0) || (timeleft == 1)) { |
---|
8466 | 9947 | DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n", |
---|
8467 | 9948 | __FUNCTION__, dhdp->dhd_bus_busy_state)); |
---|
8468 | | - BUG_ON(1); |
---|
| 9949 | + ASSERT(0); |
---|
8469 | 9950 | } |
---|
8470 | 9951 | |
---|
8471 | 9952 | return; |
---|
.. | .. |
---|
8486 | 9967 | dhdsdio_advertise_bus_cleanup(bus->dhd); |
---|
8487 | 9968 | dhd_os_sdlock(dhdp); |
---|
8488 | 9969 | dhd_os_wd_timer(dhdp, 0); |
---|
| 9970 | +#if defined(OEM_ANDROID) |
---|
8489 | 9971 | #if !defined(IGNORE_ETH0_DOWN) |
---|
8490 | 9972 | /* Force flow control as protection when stop come before ifconfig_down */ |
---|
8491 | 9973 | dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); |
---|
8492 | 9974 | #endif /* !defined(IGNORE_ETH0_DOWN) */ |
---|
| 9975 | +#endif /* OEM_ANDROID */ |
---|
8493 | 9976 | /* Expect app to have torn down any connection before calling */ |
---|
8494 | 9977 | /* Stop the bus, disable F2 */ |
---|
8495 | 9978 | dhd_bus_stop(bus, FALSE); |
---|
8496 | | - |
---|
8497 | | -#if defined(OOB_INTR_ONLY) |
---|
| 9979 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
8498 | 9980 | /* Clean up any pending IRQ */ |
---|
8499 | 9981 | dhd_enable_oob_intr(bus, FALSE); |
---|
8500 | 9982 | bcmsdh_oob_intr_set(bus->sdh, FALSE); |
---|
8501 | 9983 | bcmsdh_oob_intr_unregister(bus->sdh); |
---|
8502 | | -#endif |
---|
| 9984 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
8503 | 9985 | |
---|
8504 | 9986 | /* Clean tx/rx buffer pointers, detach from the dongle */ |
---|
8505 | 9987 | dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE); |
---|
8506 | 9988 | |
---|
8507 | 9989 | bus->dhd->dongle_reset = TRUE; |
---|
| 9990 | + DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__)); |
---|
8508 | 9991 | bus->dhd->up = FALSE; |
---|
8509 | 9992 | dhd_txglom_enable(dhdp, FALSE); |
---|
8510 | 9993 | dhd_os_sdunlock(dhdp); |
---|
8511 | 9994 | |
---|
8512 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9995 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 9996 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
8513 | 9997 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
8514 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 9998 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
8515 | 9999 | |
---|
8516 | | - DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); |
---|
| 10000 | + DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); |
---|
8517 | 10001 | /* App can now remove power from device */ |
---|
8518 | 10002 | } else |
---|
8519 | 10003 | bcmerror = BCME_SDIO_ERROR; |
---|
8520 | 10004 | } else { |
---|
8521 | 10005 | /* App must have restored power to device before calling */ |
---|
8522 | 10006 | |
---|
8523 | | - DHD_ERROR(("\n\n%s: == WLAN ON ==\n", __FUNCTION__)); |
---|
| 10007 | + DHD_ERROR(("\n\n%s: == Power ON ==\n", __FUNCTION__)); |
---|
8524 | 10008 | |
---|
8525 | 10009 | if (bus->dhd->dongle_reset) { |
---|
8526 | 10010 | /* Turn on WLAN */ |
---|
8527 | 10011 | dhd_os_sdlock(dhdp); |
---|
8528 | | - /* Reset SD client */ |
---|
| 10012 | + /* Reset SD client -- required if devreset is called |
---|
| 10013 | + * via 'dhd devreset' iovar |
---|
| 10014 | + */ |
---|
8529 | 10015 | bcmsdh_reset(bus->sdh); |
---|
8530 | | - |
---|
8531 | 10016 | /* Attempt to re-attach & download */ |
---|
8532 | 10017 | if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh, |
---|
8533 | | - (uint32 *)SI_ENUM_BASE, |
---|
| 10018 | + (uint32 *)(uintptr)si_enum_base(bus->cl_devid), |
---|
8534 | 10019 | bus->cl_devid)) { |
---|
8535 | 10020 | |
---|
8536 | | - DHD_GENERAL_LOCK(bus->dhd, flags); |
---|
| 10021 | + DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); |
---|
| 10022 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
8537 | 10023 | bus->dhd->busstate = DHD_BUS_DOWN; |
---|
8538 | | - DHD_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 10024 | + DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags); |
---|
| 10025 | + |
---|
8539 | 10026 | /* Attempt to download binary to the dongle */ |
---|
8540 | 10027 | if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) && |
---|
8541 | 10028 | dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) { |
---|
.. | .. |
---|
8543 | 10030 | /* Re-init bus, enable F2 transfer */ |
---|
8544 | 10031 | bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); |
---|
8545 | 10032 | if (bcmerror == BCME_OK) { |
---|
8546 | | -#if defined(OOB_INTR_ONLY) |
---|
| 10033 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
8547 | 10034 | dhd_enable_oob_intr(bus, TRUE); |
---|
8548 | 10035 | bcmsdh_oob_intr_register(bus->sdh, |
---|
8549 | 10036 | dhdsdio_isr, bus); |
---|
8550 | 10037 | bcmsdh_oob_intr_set(bus->sdh, TRUE); |
---|
8551 | | -#endif |
---|
| 10038 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
8552 | 10039 | |
---|
8553 | 10040 | bus->dhd->dongle_reset = FALSE; |
---|
8554 | 10041 | bus->dhd->up = TRUE; |
---|
8555 | 10042 | |
---|
8556 | | -#if !defined(IGNORE_ETH0_DOWN) |
---|
| 10043 | +#if defined(OEM_ANDROID) && !defined(IGNORE_ETH0_DOWN) |
---|
8557 | 10044 | /* Restore flow control */ |
---|
8558 | 10045 | dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); |
---|
8559 | | -#endif |
---|
| 10046 | +#endif /* defined(OEM_ANDROID) && (!defined(IGNORE_ETH0_DOWN)) */ |
---|
8560 | 10047 | dhd_os_wd_timer(dhdp, dhd_watchdog_ms); |
---|
8561 | 10048 | |
---|
8562 | 10049 | DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); |
---|
.. | .. |
---|
8578 | 10065 | bcmerror = BCME_SDIO_ERROR; |
---|
8579 | 10066 | } |
---|
8580 | 10067 | |
---|
8581 | | - dhd_os_sdunlock(dhdp); |
---|
| 10068 | + dhd_os_sdunlock(dhdp); |
---|
8582 | 10069 | } else { |
---|
8583 | | - bcmerror = BCME_SDIO_ERROR; |
---|
8584 | 10070 | DHD_INFO(("%s called when dongle is not in reset\n", |
---|
8585 | 10071 | __FUNCTION__)); |
---|
| 10072 | +#if defined(OEM_ANDROID) |
---|
8586 | 10073 | DHD_INFO(("Will call dhd_bus_start instead\n")); |
---|
8587 | 10074 | dhd_bus_resume(dhdp, 1); |
---|
8588 | 10075 | if ((bcmerror = dhd_bus_start(dhdp)) != 0) |
---|
8589 | 10076 | DHD_ERROR(("%s: dhd_bus_start fail with %d\n", |
---|
8590 | 10077 | __FUNCTION__, bcmerror)); |
---|
| 10078 | +#endif /* defined(OEM_ANDROID) */ |
---|
8591 | 10079 | } |
---|
8592 | 10080 | } |
---|
8593 | 10081 | return bcmerror; |
---|
.. | .. |
---|
8644 | 10132 | return dhdsdio_membytes(bus, set, address, data, size); |
---|
8645 | 10133 | } |
---|
8646 | 10134 | |
---|
| 10135 | +#if defined(SUPPORT_MULTIPLE_REVISION) |
---|
| 10136 | +static int |
---|
| 10137 | +concate_revision_bcm4335(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10138 | +{ |
---|
| 10139 | + |
---|
| 10140 | + uint chipver; |
---|
| 10141 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10142 | + char chipver_tag[10] = "_4335"; |
---|
| 10143 | +#else |
---|
| 10144 | + char chipver_tag[4] = {0, }; |
---|
| 10145 | +#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ |
---|
| 10146 | + |
---|
| 10147 | + DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); |
---|
| 10148 | + if (bus->sih->chip != BCM4335_CHIP_ID) { |
---|
| 10149 | + DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__)); |
---|
| 10150 | + return -1; |
---|
| 10151 | + } |
---|
| 10152 | + chipver = bus->sih->chiprev; |
---|
| 10153 | + DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); |
---|
| 10154 | + if (chipver == 0x0) { |
---|
| 10155 | + DHD_ERROR(("----- CHIP bcm4335_A0 -----\n")); |
---|
| 10156 | + strcat(chipver_tag, "_a0"); |
---|
| 10157 | + } else if (chipver == 0x1) { |
---|
| 10158 | + DHD_ERROR(("----- CHIP bcm4335_B0 -----\n")); |
---|
| 10159 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10160 | + strcat(chipver_tag, "_b0"); |
---|
| 10161 | +#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ |
---|
| 10162 | + } |
---|
| 10163 | + |
---|
| 10164 | + strcat(fw_path, chipver_tag); |
---|
| 10165 | + strcat(nv_path, chipver_tag); |
---|
| 10166 | + return 0; |
---|
| 10167 | +} |
---|
| 10168 | + |
---|
| 10169 | +static int |
---|
| 10170 | +concate_revision_bcm4339(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10171 | +{ |
---|
| 10172 | + |
---|
| 10173 | + uint chipver; |
---|
| 10174 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10175 | + char chipver_tag[10] = "_4339"; |
---|
| 10176 | +#else |
---|
| 10177 | + char chipver_tag[4] = {0, }; |
---|
| 10178 | +#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ |
---|
| 10179 | + |
---|
| 10180 | + DHD_TRACE(("%s: BCM4339 Multiple Revision Check\n", __FUNCTION__)); |
---|
| 10181 | + if (bus->sih->chip != BCM4339_CHIP_ID) { |
---|
| 10182 | + DHD_ERROR(("%s:Chip is not BCM4339\n", __FUNCTION__)); |
---|
| 10183 | + return -1; |
---|
| 10184 | + } |
---|
| 10185 | + chipver = bus->sih->chiprev; |
---|
| 10186 | + DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); |
---|
| 10187 | + if (chipver == 0x1) { |
---|
| 10188 | + DHD_ERROR(("----- CHIP bcm4339_A0 -----\n")); |
---|
| 10189 | + strcat(chipver_tag, "_a0"); |
---|
| 10190 | + } else { |
---|
| 10191 | + DHD_ERROR(("----- CHIP bcm4339 unknown revision %d -----\n", |
---|
| 10192 | + chipver)); |
---|
| 10193 | + } |
---|
| 10194 | + |
---|
| 10195 | + strcat(fw_path, chipver_tag); |
---|
| 10196 | + strcat(nv_path, chipver_tag); |
---|
| 10197 | + return 0; |
---|
| 10198 | +} |
---|
| 10199 | + |
---|
| 10200 | +static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10201 | +{ |
---|
| 10202 | + uint32 chip_ver; |
---|
| 10203 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10204 | + char chipver_tag[10] = {0, }; |
---|
| 10205 | +#else |
---|
| 10206 | + char chipver_tag[4] = {0, }; |
---|
| 10207 | +#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ |
---|
| 10208 | + chip_ver = bus->sih->chiprev; |
---|
| 10209 | + |
---|
| 10210 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10211 | + if (chip_ver == 3) |
---|
| 10212 | + strcat(chipver_tag, "_4354"); |
---|
| 10213 | + else |
---|
| 10214 | + strcat(chipver_tag, "_4350"); |
---|
| 10215 | +#endif // endif |
---|
| 10216 | + |
---|
| 10217 | + if (chip_ver == 3) { |
---|
| 10218 | + DHD_ERROR(("----- CHIP 4354 A0 -----\n")); |
---|
| 10219 | + strcat(chipver_tag, "_a0"); |
---|
| 10220 | + } else { |
---|
| 10221 | + DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver)); |
---|
| 10222 | + } |
---|
| 10223 | + |
---|
| 10224 | + strcat(fw_path, chipver_tag); |
---|
| 10225 | + strcat(nv_path, chipver_tag); |
---|
| 10226 | + return 0; |
---|
| 10227 | +} |
---|
| 10228 | + |
---|
| 10229 | +static int concate_revision_bcm4354(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10230 | +{ |
---|
| 10231 | + uint32 chip_ver; |
---|
| 10232 | +#if defined(SUPPORT_MULTIPLE_CHIPS) |
---|
| 10233 | + char chipver_tag[10] = "_4354"; |
---|
| 10234 | +#else |
---|
| 10235 | + char chipver_tag[4] = {0, }; |
---|
| 10236 | +#endif /* SUPPORT_MULTIPLE_CHIPS */ |
---|
| 10237 | + |
---|
| 10238 | + chip_ver = bus->sih->chiprev; |
---|
| 10239 | + if (chip_ver == 1) { |
---|
| 10240 | + DHD_ERROR(("----- CHIP 4354 A1 -----\n")); |
---|
| 10241 | + strcat(chipver_tag, "_a1"); |
---|
| 10242 | + } else { |
---|
| 10243 | + DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver)); |
---|
| 10244 | + } |
---|
| 10245 | + |
---|
| 10246 | + strcat(fw_path, chipver_tag); |
---|
| 10247 | + strcat(nv_path, chipver_tag); |
---|
| 10248 | + |
---|
| 10249 | + return 0; |
---|
| 10250 | +} |
---|
| 10251 | + |
---|
| 10252 | +static int |
---|
| 10253 | +concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10254 | +{ |
---|
| 10255 | + char chipver_tag[10] = {0, }; |
---|
| 10256 | +#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT |
---|
| 10257 | + int base_system_rev_for_nv = 0; |
---|
| 10258 | +#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ |
---|
| 10259 | + |
---|
| 10260 | + DHD_TRACE(("%s: BCM43454 Multiple Revision Check\n", __FUNCTION__)); |
---|
| 10261 | + if (bus->sih->chip != BCM43454_CHIP_ID) { |
---|
| 10262 | + DHD_ERROR(("%s:Chip is not BCM43454!\n", __FUNCTION__)); |
---|
| 10263 | + return -1; |
---|
| 10264 | + } |
---|
| 10265 | +#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT |
---|
| 10266 | + base_system_rev_for_nv = dhd_get_system_rev(); |
---|
| 10267 | + if (base_system_rev_for_nv > 0) { |
---|
| 10268 | + DHD_ERROR(("----- Board Rev [%d] -----\n", base_system_rev_for_nv)); |
---|
| 10269 | + sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv); |
---|
| 10270 | + } |
---|
| 10271 | +#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ |
---|
| 10272 | +#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW |
---|
| 10273 | + DHD_ERROR(("----- Rev [%d] Fot MULTIPLE Board. -----\n", system_hw_rev)); |
---|
| 10274 | + if ((system_hw_rev >= 8) && (system_hw_rev <= 11)) { |
---|
| 10275 | + DHD_ERROR(("This HW is Rev 08 ~ 11. this is For FD-HW\n")); |
---|
| 10276 | + strcat(chipver_tag, "_FD"); |
---|
| 10277 | + } |
---|
| 10278 | +#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */ |
---|
| 10279 | + |
---|
| 10280 | + strcat(nv_path, chipver_tag); |
---|
| 10281 | + return 0; |
---|
| 10282 | +} |
---|
| 10283 | + |
---|
| 10284 | +int |
---|
| 10285 | +concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path) |
---|
| 10286 | +{ |
---|
| 10287 | + int res = 0; |
---|
| 10288 | + |
---|
| 10289 | + if (!bus || !bus->sih) { |
---|
| 10290 | + DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__)); |
---|
| 10291 | + return -1; |
---|
| 10292 | + } |
---|
| 10293 | + |
---|
| 10294 | + switch (bus->sih->chip) { |
---|
| 10295 | + case BCM4335_CHIP_ID: |
---|
| 10296 | + res = concate_revision_bcm4335(bus, fw_path, nv_path); |
---|
| 10297 | + |
---|
| 10298 | + break; |
---|
| 10299 | + case BCM4339_CHIP_ID: |
---|
| 10300 | + res = concate_revision_bcm4339(bus, fw_path, nv_path); |
---|
| 10301 | + break; |
---|
| 10302 | + case BCM4350_CHIP_ID: |
---|
| 10303 | + res = concate_revision_bcm4350(bus, fw_path, nv_path); |
---|
| 10304 | + break; |
---|
| 10305 | + case BCM4354_CHIP_ID: |
---|
| 10306 | + res = concate_revision_bcm4354(bus, fw_path, nv_path); |
---|
| 10307 | + break; |
---|
| 10308 | + case BCM43454_CHIP_ID: |
---|
| 10309 | + res = concate_revision_bcm43454(bus, fw_path, nv_path); |
---|
| 10310 | + break; |
---|
| 10311 | + |
---|
| 10312 | + default: |
---|
| 10313 | + DHD_ERROR(("REVISION SPECIFIC feature is not required\n")); |
---|
| 10314 | + return res; |
---|
| 10315 | + } |
---|
| 10316 | + |
---|
| 10317 | + if (res == 0) { |
---|
| 10318 | + } |
---|
| 10319 | + return res; |
---|
| 10320 | +} |
---|
| 10321 | +#endif /* SUPPORT_MULTIPLE_REVISION */ |
---|
8647 | 10322 | |
---|
8648 | 10323 | void |
---|
8649 | 10324 | dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path) |
---|
.. | .. |
---|
8695 | 10370 | |
---|
8696 | 10371 | #ifdef PROP_TXSTATUS |
---|
8697 | 10372 | wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED); |
---|
8698 | | -#endif |
---|
| 10373 | +#endif // endif |
---|
8699 | 10374 | if (!wlfc_enabled) { |
---|
8700 | 10375 | #ifdef DHDTCPACK_SUPPRESS |
---|
8701 | 10376 | /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt, |
---|
.. | .. |
---|
8704 | 10379 | dhd_tcpack_info_tbl_clean(bus->dhd); |
---|
8705 | 10380 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
8706 | 10381 | /* Clear the data packet queues */ |
---|
8707 | | - pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0); |
---|
| 10382 | + pktq_flush(dhdp->osh, &bus->txq, TRUE); |
---|
8708 | 10383 | } |
---|
8709 | 10384 | } |
---|
8710 | 10385 | |
---|
.. | .. |
---|
8733 | 10408 | #endif /* BCMSDIO */ |
---|
8734 | 10409 | |
---|
8735 | 10410 | #ifdef DEBUGGER |
---|
8736 | | -uint32 dhd_sdio_reg_read(void *h, uint32 addr) |
---|
| 10411 | +static uint32 |
---|
| 10412 | +dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr) |
---|
8737 | 10413 | { |
---|
8738 | 10414 | uint32 rval; |
---|
8739 | | - struct dhd_bus *bus = (struct dhd_bus *) h; |
---|
8740 | 10415 | |
---|
8741 | 10416 | dhd_os_sdlock(bus->dhd); |
---|
8742 | 10417 | |
---|
.. | .. |
---|
8751 | 10426 | return rval; |
---|
8752 | 10427 | } |
---|
8753 | 10428 | |
---|
8754 | | -void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val) |
---|
| 10429 | +static void |
---|
| 10430 | +dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val) |
---|
8755 | 10431 | { |
---|
8756 | | - struct dhd_bus *bus = (struct dhd_bus *) h; |
---|
8757 | | - |
---|
8758 | 10432 | dhd_os_sdlock(bus->dhd); |
---|
8759 | 10433 | |
---|
8760 | 10434 | BUS_WAKE(bus); |
---|
.. | .. |
---|
8765 | 10439 | |
---|
8766 | 10440 | dhd_os_sdunlock(bus->dhd); |
---|
8767 | 10441 | } |
---|
| 10442 | + |
---|
8768 | 10443 | #endif /* DEBUGGER */ |
---|
8769 | 10444 | |
---|
| 10445 | +#if defined(BT_OVER_SDIO) |
---|
| 10446 | +uint8 dhd_bus_cfg_read(void *h, uint fun_num, uint32 addr, int *err) |
---|
| 10447 | +{ |
---|
| 10448 | + uint8 intrd; |
---|
| 10449 | + dhd_pub_t *dhdp = (dhd_pub_t *)h; |
---|
| 10450 | + dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; |
---|
| 10451 | + |
---|
| 10452 | + dhd_os_sdlock(bus->dhd); |
---|
| 10453 | + |
---|
| 10454 | + intrd = bcmsdh_cfg_read(bus->sdh, fun_num, addr, err); |
---|
| 10455 | + |
---|
| 10456 | + dhd_os_sdunlock(bus->dhd); |
---|
| 10457 | + |
---|
| 10458 | + return intrd; |
---|
| 10459 | +} EXPORT_SYMBOL(dhd_bus_cfg_read); |
---|
| 10460 | + |
---|
| 10461 | +void dhd_bus_cfg_write(void *h, uint fun_num, uint32 addr, uint8 val, int *err) |
---|
| 10462 | +{ |
---|
| 10463 | + dhd_pub_t *dhdp = (dhd_pub_t *)h; |
---|
| 10464 | + dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; |
---|
| 10465 | + |
---|
| 10466 | + dhd_os_sdlock(bus->dhd); |
---|
| 10467 | + |
---|
| 10468 | + bcmsdh_cfg_write(bus->sdh, fun_num, addr, val, err); |
---|
| 10469 | + |
---|
| 10470 | + dhd_os_sdunlock(bus->dhd); |
---|
| 10471 | + |
---|
| 10472 | +} EXPORT_SYMBOL(dhd_bus_cfg_write); |
---|
| 10473 | + |
---|
| 10474 | +int dhd_bus_recv_buf(void *h, uint32 addr, uint fn, uint8 *buf, uint nbytes) |
---|
| 10475 | +{ |
---|
| 10476 | + int ret; |
---|
| 10477 | + dhd_pub_t *dhdp = (dhd_pub_t *)h; |
---|
| 10478 | + dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; |
---|
| 10479 | + dhd_os_sdlock(bus->dhd); |
---|
| 10480 | + |
---|
| 10481 | + ret = dhd_bcmsdh_recv_buf(bus, 0, fn, |
---|
| 10482 | + F2SYNC, buf, nbytes, NULL, NULL, NULL); |
---|
| 10483 | + |
---|
| 10484 | + dhd_os_sdunlock(bus->dhd); |
---|
| 10485 | + DHD_ERROR(("\nEntering %s function is %d and no of bytes received %d\n", |
---|
| 10486 | + __func__, fn, nbytes)); |
---|
| 10487 | + |
---|
| 10488 | + return ret; |
---|
| 10489 | +} EXPORT_SYMBOL(dhd_bus_recv_buf); |
---|
| 10490 | + |
---|
| 10491 | +int dhd_bus_send_buf(void *h, uint32 addr, uint fn, uint8 *buf, uint nbytes) |
---|
| 10492 | +{ |
---|
| 10493 | + int ret; |
---|
| 10494 | + dhd_pub_t *dhdp = (dhd_pub_t *)h; |
---|
| 10495 | + dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; |
---|
| 10496 | + DHD_ERROR(("\nEntering %s function is %d and no of bytes sent is %d\n", |
---|
| 10497 | + __func__, fn, nbytes)); |
---|
| 10498 | + |
---|
| 10499 | + dhd_os_sdlock(bus->dhd); |
---|
| 10500 | + |
---|
| 10501 | + ret = dhd_bcmsdh_send_buf(bus, 0, fn, |
---|
| 10502 | + F2SYNC, buf, nbytes, NULL, NULL, NULL, 1); |
---|
| 10503 | + |
---|
| 10504 | + dhd_os_sdunlock(bus->dhd); |
---|
| 10505 | + |
---|
| 10506 | + return ret; |
---|
| 10507 | +} EXPORT_SYMBOL(dhd_bus_send_buf); |
---|
| 10508 | + |
---|
| 10509 | +int dhd_bus_set_blocksize(void *h, unsigned int fun_num, unsigned int block_size) |
---|
| 10510 | +{ |
---|
| 10511 | + int bcmerr; |
---|
| 10512 | + int func_blk_size = fun_num; |
---|
| 10513 | + dhd_pub_t *dhd = (dhd_pub_t *)h; |
---|
| 10514 | + dhd_bus_t *bus = (dhd_bus_t *)dhd->bus; |
---|
| 10515 | + |
---|
| 10516 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 10517 | + func_blk_size = fun_num << 16 | block_size; |
---|
| 10518 | + bcmerr = bcmsdh_iovar_op(bus->sdh, "sd_blocksize", NULL, 0, &func_blk_size, |
---|
| 10519 | + sizeof(func_blk_size), TRUE); |
---|
| 10520 | + if (bcmerr != BCME_OK) { |
---|
| 10521 | + DHD_ERROR(("%s: Set F%d Block size error\n", __FUNCTION__, fun_num)); |
---|
| 10522 | + return BCME_ERROR; |
---|
| 10523 | + } |
---|
| 10524 | +#endif // endif |
---|
| 10525 | + return bcmerr; |
---|
| 10526 | +} EXPORT_SYMBOL(dhd_bus_set_blocksize); |
---|
| 10527 | + |
---|
| 10528 | +static int |
---|
| 10529 | +extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value) |
---|
| 10530 | +{ |
---|
| 10531 | + char field [8]; |
---|
| 10532 | + |
---|
| 10533 | + strncpy(field, line + start_pos, num_chars); |
---|
| 10534 | + field [num_chars] = '\0'; |
---|
| 10535 | + |
---|
| 10536 | + return (sscanf (field, "%hX", value) == 1); |
---|
| 10537 | +} |
---|
| 10538 | + |
---|
| 10539 | +static int |
---|
| 10540 | +read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode, uint16 * hi_addr, |
---|
| 10541 | + uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes) |
---|
| 10542 | +{ |
---|
| 10543 | + int str_len; |
---|
| 10544 | + uint16 num_data_bytes, addr, data_pos, type, w, i; |
---|
| 10545 | + uint32 abs_base_addr32 = 0; |
---|
| 10546 | + *num_bytes = 0; |
---|
| 10547 | + |
---|
| 10548 | + while (!*num_bytes) |
---|
| 10549 | + { |
---|
| 10550 | + str_len = dhd_os_gets_image(bus->dhd, line, BTFW_MAX_STR_LEN, file); |
---|
| 10551 | + |
---|
| 10552 | + DHD_TRACE(("%s: Len :0x%x %s\n", __FUNCTION__, str_len, line)); |
---|
| 10553 | + |
---|
| 10554 | + if (str_len == 0) { |
---|
| 10555 | + break; |
---|
| 10556 | + } else if (str_len > 9) { |
---|
| 10557 | + extract_hex_field(line, 1, 2, &num_data_bytes); |
---|
| 10558 | + extract_hex_field(line, 3, 4, &addr); |
---|
| 10559 | + extract_hex_field(line, 7, 2, &type); |
---|
| 10560 | + |
---|
| 10561 | + data_pos = 9; |
---|
| 10562 | + for (i = 0; i < num_data_bytes; i++) { |
---|
| 10563 | + extract_hex_field(line, data_pos, 2, &w); |
---|
| 10564 | + data_bytes [i] = (uint8)(w & 0x00FF); |
---|
| 10565 | + data_pos += 2; |
---|
| 10566 | + } |
---|
| 10567 | + |
---|
| 10568 | + if (type == BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS) { |
---|
| 10569 | + *hi_addr = (data_bytes [0] << 8) | data_bytes [1]; |
---|
| 10570 | + *addr_mode = BTFW_ADDR_MODE_EXTENDED; |
---|
| 10571 | + } else if (type == BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS) { |
---|
| 10572 | + *hi_addr = (data_bytes [0] << 8) | data_bytes [1]; |
---|
| 10573 | + *addr_mode = BTFW_ADDR_MODE_SEGMENT; |
---|
| 10574 | + } else if (type == BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS) { |
---|
| 10575 | + abs_base_addr32 = (data_bytes [0] << 24) | (data_bytes [1] << 16) | |
---|
| 10576 | + (data_bytes [2] << 8) | data_bytes [3]; |
---|
| 10577 | + *addr_mode = BTFW_ADDR_MODE_LINEAR32; |
---|
| 10578 | + } else if (type == BTFW_HEX_LINE_TYPE_DATA) { |
---|
| 10579 | + *dest_addr = addr; |
---|
| 10580 | + if (*addr_mode == BTFW_ADDR_MODE_EXTENDED) |
---|
| 10581 | + *dest_addr += (*hi_addr << 16); |
---|
| 10582 | + else if (*addr_mode == BTFW_ADDR_MODE_SEGMENT) |
---|
| 10583 | + *dest_addr += (*hi_addr << 4); |
---|
| 10584 | + else if (*addr_mode == BTFW_ADDR_MODE_LINEAR32) |
---|
| 10585 | + *dest_addr += abs_base_addr32; |
---|
| 10586 | + *num_bytes = num_data_bytes; |
---|
| 10587 | + } |
---|
| 10588 | + } |
---|
| 10589 | + } |
---|
| 10590 | + return (*num_bytes > 0); |
---|
| 10591 | +} |
---|
| 10592 | + |
---|
| 10593 | +static int |
---|
| 10594 | +_dhdsdio_download_btfw(struct dhd_bus *bus) |
---|
| 10595 | +{ |
---|
| 10596 | + int bcm_error = -1; |
---|
| 10597 | + void *image = NULL; |
---|
| 10598 | + uint8 *mem_blk = NULL, *mem_ptr = NULL, *data_ptr = NULL; |
---|
| 10599 | + |
---|
| 10600 | + uint32 offset_addr = 0, offset_len = 0, bytes_to_write = 0; |
---|
| 10601 | + |
---|
| 10602 | + char *line = NULL; |
---|
| 10603 | + uint32 dest_addr = 0, num_bytes; |
---|
| 10604 | + uint16 hiAddress = 0; |
---|
| 10605 | + uint32 start_addr, start_data, end_addr, end_data, i, index, pad, |
---|
| 10606 | + bt2wlan_pwrup_adr; |
---|
| 10607 | + |
---|
| 10608 | + int addr_mode = BTFW_ADDR_MODE_EXTENDED; |
---|
| 10609 | + |
---|
| 10610 | + /* Out immediately if no image to download */ |
---|
| 10611 | + if ((bus->btfw_path == NULL) || (bus->btfw_path[0] == '\0')) { |
---|
| 10612 | + return 0; |
---|
| 10613 | + } |
---|
| 10614 | + |
---|
| 10615 | + image = dhd_os_open_image1(bus->dhd, bus->btfw_path); |
---|
| 10616 | + if (image == NULL) |
---|
| 10617 | + goto err; |
---|
| 10618 | + |
---|
| 10619 | + mem_ptr = mem_blk = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN); |
---|
| 10620 | + if (mem_blk == NULL) { |
---|
| 10621 | + DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, |
---|
| 10622 | + BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN)); |
---|
| 10623 | + goto err; |
---|
| 10624 | + } |
---|
| 10625 | + if ((uint32)(uintptr)mem_blk % DHD_SDALIGN) |
---|
| 10626 | + mem_ptr += (DHD_SDALIGN - ((uint32)(uintptr)mem_blk % DHD_SDALIGN)); |
---|
| 10627 | + |
---|
| 10628 | + data_ptr = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE - 8); |
---|
| 10629 | + if (data_ptr == NULL) { |
---|
| 10630 | + DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, |
---|
| 10631 | + BTFW_DOWNLOAD_BLK_SIZE - 8)); |
---|
| 10632 | + goto err; |
---|
| 10633 | + } |
---|
| 10634 | + /* Write to BT register to hold WLAN wake high during BT FW download */ |
---|
| 10635 | + bt2wlan_pwrup_adr = BTMEM_OFFSET + BT2WLAN_PWRUP_ADDR; |
---|
| 10636 | + bcmsdh_reg_write(bus->sdh, bt2wlan_pwrup_adr, 4, BT2WLAN_PWRUP_WAKE); |
---|
| 10637 | + /* |
---|
| 10638 | + * Wait for at least 2msec for the clock to be ready/Available. |
---|
| 10639 | + */ |
---|
| 10640 | + OSL_DELAY(2000); |
---|
| 10641 | + |
---|
| 10642 | + line = MALLOC(bus->dhd->osh, BTFW_MAX_STR_LEN); |
---|
| 10643 | + if (line == NULL) { |
---|
| 10644 | + DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", |
---|
| 10645 | + __FUNCTION__, BTFW_MAX_STR_LEN)); |
---|
| 10646 | + goto err; |
---|
| 10647 | + } |
---|
| 10648 | + memset(line, 0, BTFW_MAX_STR_LEN); |
---|
| 10649 | + |
---|
| 10650 | + while (read_more_btbytes (bus, image, line, &addr_mode, &hiAddress, &dest_addr, |
---|
| 10651 | + data_ptr, &num_bytes)) { |
---|
| 10652 | + |
---|
| 10653 | + DHD_TRACE(("read %d bytes at address %08X\n", num_bytes, dest_addr)); |
---|
| 10654 | + |
---|
| 10655 | + start_addr = BTMEM_OFFSET + dest_addr; |
---|
| 10656 | + index = 0; |
---|
| 10657 | + |
---|
| 10658 | + /* Make sure the start address is 4 byte aligned to avoid alignment issues |
---|
| 10659 | + * with SD host controllers |
---|
| 10660 | + */ |
---|
| 10661 | + if (!ISALIGNED(start_addr, 4)) { |
---|
| 10662 | + pad = start_addr % 4; |
---|
| 10663 | + start_addr = ROUNDDN(start_addr, 4); |
---|
| 10664 | + start_data = bcmsdh_reg_read(bus->sdh, start_addr, 4); |
---|
| 10665 | + for (i = 0; i < pad; i++, index++) { |
---|
| 10666 | + mem_ptr[index] = (uint8)((uint8 *)&start_data)[i]; |
---|
| 10667 | + } |
---|
| 10668 | + } |
---|
| 10669 | + bcopy(data_ptr, &(mem_ptr[index]), num_bytes); |
---|
| 10670 | + index += num_bytes; |
---|
| 10671 | + |
---|
| 10672 | + /* Make sure the length is multiple of 4bytes to avoid alignment issues |
---|
| 10673 | + * with SD host controllers |
---|
| 10674 | + */ |
---|
| 10675 | + end_addr = start_addr + index; |
---|
| 10676 | + if (!ISALIGNED(end_addr, 4)) { |
---|
| 10677 | + end_addr = ROUNDDN(end_addr, 4); |
---|
| 10678 | + end_data = bcmsdh_reg_read(bus->sdh, end_addr, 4); |
---|
| 10679 | + for (i = (index % 4); i < 4; i++, index++) { |
---|
| 10680 | + mem_ptr[index] = (uint8)((uint8 *)&end_data)[i]; |
---|
| 10681 | + } |
---|
| 10682 | + } |
---|
| 10683 | + |
---|
| 10684 | + offset_addr = start_addr & 0xFFF; |
---|
| 10685 | + offset_len = offset_addr + index; |
---|
| 10686 | + if (offset_len <= 0x1000) { |
---|
| 10687 | + bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr, index); |
---|
| 10688 | + if (bcm_error) { |
---|
| 10689 | + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
| 10690 | + __FUNCTION__, bcm_error, num_bytes, start_addr)); |
---|
| 10691 | + goto err; |
---|
| 10692 | + } |
---|
| 10693 | + } |
---|
| 10694 | + else { |
---|
| 10695 | + bytes_to_write = 0x1000 - offset_addr; |
---|
| 10696 | + bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr, |
---|
| 10697 | + bytes_to_write); |
---|
| 10698 | + if (bcm_error) { |
---|
| 10699 | + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
| 10700 | + __FUNCTION__, bcm_error, num_bytes, start_addr)); |
---|
| 10701 | + goto err; |
---|
| 10702 | + } |
---|
| 10703 | + |
---|
| 10704 | + OSL_DELAY(10000); |
---|
| 10705 | + |
---|
| 10706 | + bcm_error = dhdsdio_membytes(bus, TRUE, (start_addr + bytes_to_write), |
---|
| 10707 | + (mem_ptr + bytes_to_write), (index - bytes_to_write)); |
---|
| 10708 | + if (bcm_error) { |
---|
| 10709 | + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", |
---|
| 10710 | + __FUNCTION__, bcm_error, num_bytes, start_addr)); |
---|
| 10711 | + goto err; |
---|
| 10712 | + } |
---|
| 10713 | + } |
---|
| 10714 | + memset(line, 0, BTFW_MAX_STR_LEN); |
---|
| 10715 | + } |
---|
| 10716 | + |
---|
| 10717 | + bcm_error = 0; |
---|
| 10718 | +err: |
---|
| 10719 | + if (mem_blk) |
---|
| 10720 | + MFREE(bus->dhd->osh, mem_blk, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN); |
---|
| 10721 | + |
---|
| 10722 | + if (data_ptr) |
---|
| 10723 | + MFREE(bus->dhd->osh, data_ptr, BTFW_DOWNLOAD_BLK_SIZE - 8); |
---|
| 10724 | + |
---|
| 10725 | + if (line) |
---|
| 10726 | + MFREE(bus->dhd->osh, line, BTFW_MAX_STR_LEN); |
---|
| 10727 | + |
---|
| 10728 | + if (image) |
---|
| 10729 | + dhd_os_close_image1(bus->dhd, image); |
---|
| 10730 | + |
---|
| 10731 | + return bcm_error; |
---|
| 10732 | +} |
---|
| 10733 | + |
---|
| 10734 | +static int |
---|
| 10735 | +dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh) |
---|
| 10736 | +{ |
---|
| 10737 | + int ret; |
---|
| 10738 | + |
---|
| 10739 | + DHD_TRACE(("%s: btfw path=%s\n", |
---|
| 10740 | + __FUNCTION__, bus->btfw_path)); |
---|
| 10741 | + DHD_OS_WAKE_LOCK(bus->dhd); |
---|
| 10742 | + dhd_os_sdlock(bus->dhd); |
---|
| 10743 | + |
---|
| 10744 | + /* Download the firmware */ |
---|
| 10745 | + ret = _dhdsdio_download_btfw(bus); |
---|
| 10746 | + |
---|
| 10747 | + dhd_os_sdunlock(bus->dhd); |
---|
| 10748 | + DHD_OS_WAKE_UNLOCK(bus->dhd); |
---|
| 10749 | + |
---|
| 10750 | + return ret; |
---|
| 10751 | +} |
---|
8770 | 10752 | |
---|
8771 | 10753 | int |
---|
| 10754 | +dhd_bus_download_btfw(struct dhd_bus *bus, osl_t *osh, |
---|
| 10755 | + char *pbtfw_path) |
---|
| 10756 | +{ |
---|
| 10757 | + int ret; |
---|
| 10758 | + |
---|
| 10759 | + bus->btfw_path = pbtfw_path; |
---|
| 10760 | + |
---|
| 10761 | + ret = dhdsdio_download_btfw(bus, osh, bus->sdh); |
---|
| 10762 | + |
---|
| 10763 | + return ret; |
---|
| 10764 | +} |
---|
| 10765 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 10766 | + |
---|
| 10767 | +void |
---|
| 10768 | +dhd_bus_dump_trap_info(dhd_bus_t *bus, struct bcmstrbuf *strbuf) |
---|
| 10769 | +{ |
---|
| 10770 | + trap_t *tr = &bus->dhd->last_trap_info; |
---|
| 10771 | + |
---|
| 10772 | + bcm_bprintf(strbuf, |
---|
| 10773 | + "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x," |
---|
| 10774 | + "lp 0x%x, rpc 0x%x Trap offset 0x%x, " |
---|
| 10775 | + "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, " |
---|
| 10776 | + "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n", |
---|
| 10777 | + ltoh32(tr->type), ltoh32(tr->epc), ltoh32(tr->cpsr), ltoh32(tr->spsr), |
---|
| 10778 | + ltoh32(tr->r13), ltoh32(tr->r14), ltoh32(tr->pc), |
---|
| 10779 | + ltoh32(bus->dongle_trap_addr), |
---|
| 10780 | + ltoh32(tr->r0), ltoh32(tr->r1), ltoh32(tr->r2), ltoh32(tr->r3), |
---|
| 10781 | + ltoh32(tr->r4), ltoh32(tr->r5), ltoh32(tr->r6), ltoh32(tr->r7)); |
---|
| 10782 | + |
---|
| 10783 | +} |
---|
| 10784 | + |
---|
| 10785 | +static int |
---|
8772 | 10786 | dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len) |
---|
8773 | 10787 | { |
---|
8774 | 10788 | int ret = -1; |
---|
.. | .. |
---|
8782 | 10796 | return ret; |
---|
8783 | 10797 | } |
---|
8784 | 10798 | |
---|
| 10799 | +/* Function to set the min res mask depending on the chip ID used */ |
---|
| 10800 | +bool |
---|
| 10801 | +dhd_bus_set_default_min_res_mask(struct dhd_bus *bus) |
---|
| 10802 | +{ |
---|
| 10803 | + if ((bus == NULL) || (bus->sih == NULL)) { |
---|
| 10804 | + DHD_ERROR(("%s(): Invalid Arguments \r\n", __FUNCTION__)); |
---|
| 10805 | + return FALSE; |
---|
| 10806 | + } |
---|
| 10807 | + |
---|
| 10808 | + switch (bus->sih->chip) { |
---|
| 10809 | + case BCM4339_CHIP_ID: |
---|
| 10810 | + bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE(bus->sih) + 0x618, 4, 0x3fcaf377); |
---|
| 10811 | + if (bcmsdh_regfail(bus->sdh)) { |
---|
| 10812 | + DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
| 10813 | + return FALSE; |
---|
| 10814 | + } |
---|
| 10815 | + break; |
---|
| 10816 | + |
---|
| 10817 | + case BCM43012_CHIP_ID: |
---|
| 10818 | + bcmsdh_reg_write(bus->sdh, |
---|
| 10819 | + si_get_pmu_reg_addr(bus->sih, OFFSETOF(pmuregs_t, min_res_mask)), |
---|
| 10820 | + 4, DEFAULT_43012_MIN_RES_MASK); |
---|
| 10821 | + if (bcmsdh_regfail(bus->sdh)) { |
---|
| 10822 | + DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
| 10823 | + return FALSE; |
---|
| 10824 | + } |
---|
| 10825 | + break; |
---|
| 10826 | + |
---|
| 10827 | + default: |
---|
| 10828 | + DHD_ERROR(("%s: Unhandled chip id\n", __FUNCTION__)); |
---|
| 10829 | + return FALSE; |
---|
| 10830 | + } |
---|
| 10831 | + |
---|
| 10832 | + return TRUE; |
---|
| 10833 | +} |
---|
| 10834 | + |
---|
| 10835 | +/* Function to reset PMU registers */ |
---|
| 10836 | +void |
---|
| 10837 | +dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp) |
---|
| 10838 | +{ |
---|
| 10839 | + struct dhd_bus *bus = dhdp->bus; |
---|
| 10840 | + bcmsdh_reg_write(bus->sdh, si_get_pmu_reg_addr(bus->sih, |
---|
| 10841 | + OFFSETOF(pmuregs_t, swscratch)), 4, 0x0); |
---|
| 10842 | + if (bcmsdh_regfail(bus->sdh)) { |
---|
| 10843 | + DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
| 10844 | + } |
---|
| 10845 | +} |
---|
| 10846 | + |
---|
8785 | 10847 | #ifdef DHD_ULP |
---|
| 10848 | + |
---|
8786 | 10849 | /* Function to disable console messages on entering ULP mode */ |
---|
8787 | 10850 | void |
---|
8788 | 10851 | dhd_bus_ulp_disable_console(dhd_pub_t *dhdp) |
---|
.. | .. |
---|
8795 | 10858 | |
---|
8796 | 10859 | /* Flush the console buffer before disabling */ |
---|
8797 | 10860 | dhdsdio_readconsole(dhdp->bus); |
---|
8798 | | - dhd_console_ms = 0; |
---|
| 10861 | + dhdp->dhd_console_ms = 0; |
---|
8799 | 10862 | #endif /* DHD_DEBUG */ |
---|
8800 | 10863 | } |
---|
8801 | 10864 | |
---|
.. | .. |
---|
8821 | 10884 | dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); |
---|
8822 | 10885 | |
---|
8823 | 10886 | dhd_ulp_set_ulp_state(bus->dhd, DHD_ULP_READY); |
---|
8824 | | -#if defined(OOB_INTR_ONLY) |
---|
| 10887 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
8825 | 10888 | dhd_enable_oob_intr(bus, TRUE); |
---|
8826 | 10889 | bcmsdh_oob_intr_set(bus->sdh, TRUE); |
---|
8827 | | -#endif |
---|
| 10890 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
8828 | 10891 | #ifdef DHD_DEBUG |
---|
8829 | 10892 | /* Re-enable the console messages on FW redownload to default value */ |
---|
8830 | 10893 | dhd_ulp_restore_console_interval(bus->dhd); |
---|
.. | .. |
---|
8840 | 10903 | |
---|
8841 | 10904 | return bcmerror; |
---|
8842 | 10905 | } |
---|
8843 | | - |
---|
8844 | | -/* Utility function for bus wake */ |
---|
8845 | | -void |
---|
8846 | | -dhd_bus_ulp_bus_wake(void *bus) |
---|
8847 | | -{ |
---|
8848 | | - dhd_bus_t *ptrbus = (dhd_bus_t *)bus; |
---|
8849 | | - BUS_WAKE(ptrbus); |
---|
8850 | | -} |
---|
8851 | | - |
---|
8852 | | -/* Utility function to read the SDIO configuration space */ |
---|
8853 | | -int |
---|
8854 | | -dhd_bus_read_sdh_config(void *bus) |
---|
8855 | | -{ |
---|
8856 | | - int ret = 0; |
---|
8857 | | - dhd_bus_t *ptrbus = (dhd_bus_t *)bus; |
---|
8858 | | - ret = bcmsdh_cfg_read(ptrbus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); |
---|
8859 | | - |
---|
8860 | | - return ret; |
---|
8861 | | -} |
---|
8862 | | - |
---|
8863 | | -void |
---|
8864 | | -dhd_bus_schedule_dpc(void *bus) |
---|
8865 | | -{ dhd_bus_t *ptrbus = (dhd_bus_t *)bus; |
---|
8866 | | - |
---|
8867 | | - ptrbus->dpc_sched = TRUE; |
---|
8868 | | - dhd_sched_dpc(ptrbus->dhd); |
---|
8869 | | -} |
---|
8870 | | - |
---|
8871 | | -/* Function to set the min res mask depending on the chip ID used */ |
---|
8872 | | -bool |
---|
8873 | | -dhd_bus_set_default_min_res_mask(struct dhd_bus *bus) |
---|
8874 | | -{ |
---|
8875 | | - switch (bus->sih->chip) { |
---|
8876 | | - case BCM4339_CHIP_ID: |
---|
8877 | | - bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE + 0x618, 4, 0x3fcaf377); |
---|
8878 | | - if (bcmsdh_regfail(bus->sdh)) { |
---|
8879 | | - DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
8880 | | - return FALSE; |
---|
8881 | | - } |
---|
8882 | | - break; |
---|
8883 | | - |
---|
8884 | | - case BCM43012_CHIP_ID: |
---|
8885 | | - bcmsdh_reg_write(bus->sdh, |
---|
8886 | | - si_get_pmu_reg_addr(bus->sih, OFFSETOF(pmuregs_t, min_res_mask)), |
---|
8887 | | - 4, DEFAULT_43012_MIN_RES_MASK); |
---|
8888 | | - if (bcmsdh_regfail(bus->sdh)) { |
---|
8889 | | - DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
8890 | | - return FALSE; |
---|
8891 | | - } |
---|
8892 | | - break; |
---|
8893 | | - |
---|
8894 | | - default: |
---|
8895 | | - DHD_ERROR(("%s: Unhandled chip id\n", __FUNCTION__)); |
---|
8896 | | - return FALSE; |
---|
8897 | | - } |
---|
8898 | | - |
---|
8899 | | - return TRUE; |
---|
8900 | | -} |
---|
8901 | | - |
---|
8902 | | -void |
---|
8903 | | -dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp) |
---|
8904 | | -{ |
---|
8905 | | - struct dhd_bus *bus = dhdp->bus; |
---|
8906 | | - bcmsdh_reg_write(bus->sdh, si_get_pmu_reg_addr(bus->sih, |
---|
8907 | | - OFFSETOF(pmuregs_t, swscratch)), 4, 0x0); |
---|
8908 | | - if (bcmsdh_regfail(bus->sdh)) { |
---|
8909 | | - DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); |
---|
8910 | | - } |
---|
8911 | | -} |
---|
8912 | 10906 | #endif /* DHD_ULP */ |
---|
| 10907 | + |
---|
| 10908 | +int |
---|
| 10909 | +dhd_bus_readwrite_bp_addr(dhd_pub_t *dhdp, uint addr, uint size, uint* data, bool read) |
---|
| 10910 | +{ |
---|
| 10911 | + int bcmerror = 0; |
---|
| 10912 | + struct dhd_bus *bus = dhdp->bus; |
---|
| 10913 | + |
---|
| 10914 | + if (read) { |
---|
| 10915 | + *data = (int32)bcmsdh_reg_read(bus->sdh, addr, size); |
---|
| 10916 | + } else { |
---|
| 10917 | + bcmsdh_reg_write(bus->sdh, addr, size, *data); |
---|
| 10918 | + } |
---|
| 10919 | + |
---|
| 10920 | + if (bcmsdh_regfail(bus->sdh)) |
---|
| 10921 | + bcmerror = BCME_SDIO_ERROR; |
---|
| 10922 | + |
---|
| 10923 | + return bcmerror; |
---|
| 10924 | +} |
---|
| 10925 | + |
---|
| 10926 | +int dhd_get_idletime(dhd_pub_t *dhd) |
---|
| 10927 | +{ |
---|
| 10928 | + return dhd->bus->idletime; |
---|
| 10929 | +} |
---|
| 10930 | + |
---|
| 10931 | +#ifdef DHD_WAKE_STATUS |
---|
| 10932 | +wake_counts_t* |
---|
| 10933 | +dhd_bus_get_wakecount(dhd_pub_t *dhd) |
---|
| 10934 | +{ |
---|
| 10935 | + return &dhd->bus->wake_counts; |
---|
| 10936 | +} |
---|
| 10937 | +int |
---|
| 10938 | +dhd_bus_get_bus_wake(dhd_pub_t *dhd) |
---|
| 10939 | +{ |
---|
| 10940 | + return bcmsdh_set_get_wake(dhd->bus->sdh, 0); |
---|
| 10941 | +} |
---|
| 10942 | +#endif /* DHD_WAKE_STATUS */ |
---|