forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_sdio.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * DHD Bus Module for SDIO
43 *
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
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,16 +26,12 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: dhd_sdio.c 722050 2019-08-21 02:24:57Z $
29
+ * $Id: dhd_sdio.c 701844 2017-05-26 18:56:40Z $
2930 */
3031
3132 #include <typedefs.h>
3233 #include <osl.h>
3334 #include <bcmsdh.h>
34
-
35
-#ifdef BCMEMBEDIMAGE
36
-#include BCMEMBEDIMAGE
37
-#endif /* BCMEMBEDIMAGE */
3835
3936 #include <bcmdefs.h>
4037 #include <bcmutils.h>
....@@ -51,14 +48,18 @@
5148 #include <sbhnddma.h>
5249
5350 #include <sdio.h>
51
+#ifdef BCMSPI
52
+#include <spid.h>
53
+#endif /* BCMSPI */
5454 #include <sbsdio.h>
5555 #include <sbsdpcmdev.h>
5656 #include <bcmsdpcm.h>
5757 #include <bcmsdbus.h>
58
+#include <trxhdr.h>
5859
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>
6263
6364 #include <dngl_stats.h>
6465 #include <dhd.h>
....@@ -68,57 +69,61 @@
6869 #include <dhdioctl.h>
6970 #include <sdiovar.h>
7071
71
-#ifdef LOAD_DHD_WITH_FW_ALIVE
72
-#include <dhd_chip_info.h>
73
-#endif
74
-
7572 #ifdef PROP_TXSTATUS
7673 #include <dhd_wlfc.h>
77
-#endif
74
+#endif // endif
7875 #ifdef DHDTCPACK_SUPPRESS
7976 #include <dhd_ip.h>
8077 #endif /* DHDTCPACK_SUPPRESS */
8178
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
+
8287 bool dhd_mp_halting(dhd_pub_t *dhdp);
8388 extern void bcmsdh_waitfor_iodrain(void *sdh);
8489 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);
8693
8794 #ifndef DHDSDIO_MEM_DUMP_FNAME
8895 #define DHDSDIO_MEM_DUMP_FNAME "mem_dump"
89
-#endif
96
+#endif // endif
9097
9198 #define QLEN (1024) /* bulk rx and tx queue lengths */
9299 #define FCHI (QLEN - 10)
93100 #define FCLOW (FCHI / 2)
94101 #define PRIOMASK 7
95102
103
+#define F0_BLOCK_SIZE 32
96104 #define TXRETRIES 2 /* # of retries for tx frames */
97105 #define READ_FRM_CNT_RETRIES 3
98106 #ifndef DHD_RXBOUND
99107 #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
100
-#endif
108
+#endif // endif
101109
102110 #ifndef DHD_TXBOUND
103111 #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
104
-#endif
112
+#endif // endif
105113
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 */
107115
108116 #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
109117 #define MAX_MEMBLOCK (32 * 1024) /* Block size used for downloading of dongle image */
110118
111119 #define MAX_DATA_BUF (64 * 1024) /* Must be large enough to hold biggest possible glom */
112120
113
-//added 20190626 for fixed that download fw failed in new kernel version
114
-#define MAX_MEM_BUF 4096
115
-
116121 #ifndef DHD_FIRSTREAD
117122 #define DHD_FIRSTREAD 32
118
-#endif
123
+#endif // endif
119124 #if !ISPOWEROF2(DHD_FIRSTREAD)
120125 #error DHD_FIRSTREAD is not a power of 2!
121
-#endif
126
+#endif // endif
122127
123128 /* Total length of frame header for dongle protocol */
124129 #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
....@@ -129,20 +134,34 @@
129134 #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
130135 #else
131136 #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
132
-#endif
137
+#endif // endif
133138
134139 /* Space for header read, limit for data packets */
135140 #ifndef MAX_HDR_READ
136141 #define MAX_HDR_READ 32
137
-#endif
142
+#endif // endif
138143 #if !ISPOWEROF2(MAX_HDR_READ)
139144 #error MAX_HDR_READ is not a power of 2!
140
-#endif
145
+#endif // endif
141146
142147 #define MAX_RX_DATASZ 2048
143148
149
+#define SDIO_FUNC_BLOCK_SIZE_SHIFT 16
150
+#define F2_BLOCK_SIZE_256 256
151
+
144152 /* Maximum milliseconds to wait for F2 to come up */
153
+#ifdef BCMQT
154
+#define DHD_WAIT_F2RDY 30000
155
+#else
145156 #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 */
146165
147166 /* Bump up limit on waiting for HT to account for first startup;
148167 * if the image is doing a CRC calculation before programming the PMU
....@@ -152,13 +171,13 @@
152171 #if (PMU_MAX_TRANSITION_DLY <= 1000000)
153172 #undef PMU_MAX_TRANSITION_DLY
154173 #define PMU_MAX_TRANSITION_DLY 1000000
155
-#endif
174
+#endif // endif
156175
157176 /* hooks for limiting threshold custom tx num in rx processing */
158177 #define DEFAULT_TXINRX_THRES 0
159178 #ifndef CUSTOM_TXINRX_THRES
160179 #define CUSTOM_TXINRX_THRES DEFAULT_TXINRX_THRES
161
-#endif
180
+#endif // endif
162181
163182 /* Value for ChipClockCSR during initial setup */
164183 #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
....@@ -174,6 +193,13 @@
174193 PKTFREE(bus->dhd->osh, pkt, FALSE);
175194 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
176195
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 */
177203
178204 /* Device console log buffer state */
179205 #define CONSOLE_LINE_MAX 192
....@@ -209,6 +235,36 @@
209235 #define OVERFLOW_BLKSZ512_MES 80
210236
211237 #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
+
212268 /* Private data for SDIO bus interaction */
213269 typedef struct dhd_bus {
214270 dhd_pub_t *dhd;
....@@ -277,10 +333,8 @@
277333 uint polltick; /* Tick counter */
278334 uint pollcnt; /* Count of active polls */
279335
280
-#ifdef DHD_DEBUG
281336 dhd_console_t console; /* Console output polling support */
282337 uint console_addr; /* Console address from shared struct */
283
-#endif /* DHD_DEBUG */
284338
285339 uint regfails; /* Count of R_REG/W_REG failures */
286340
....@@ -294,7 +348,7 @@
294348 int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
295349 bool use_rxchain; /* If dhd should use PKT chains */
296350 bool sleeping; /* Is SDIO bus sleeping? */
297
-#if (defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16))
351
+#if defined(SUPPORT_P2P_GO_PS)
298352 wait_queue_head_t bus_sleep;
299353 #endif /* LINUX && SUPPORT_P2P_GO_PS */
300354 uint rxflow_mode; /* Rx flow control mode */
....@@ -359,6 +413,10 @@
359413 uint f2rxdata; /* Number of frame data reads */
360414 uint f2txdata; /* Number of f2 frame writes */
361415 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 */
362420 #ifdef DHDENABLE_TAILPAD
363421 uint tx_tailpad_chain; /* Number of tail padding by chaining pad_pkt */
364422 uint tx_tailpad_pktget; /* Number of tail padding by new PKTGET */
....@@ -366,7 +424,9 @@
366424 uint8 *ctrl_frame_buf;
367425 uint32 ctrl_frame_len;
368426 bool ctrl_frame_stat;
427
+#ifndef BCMSPI
369428 uint32 rxint_mode; /* rx interrupt mode */
429
+#endif /* BCMSPI */
370430 bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram
371431 * Available with socram rev 16
372432 * Remap region not DMA-able
....@@ -385,11 +445,34 @@
385445 uint32 txglom_total_len; /* Total length of pkts in glom array */
386446 bool txglom_enable; /* Flag to indicate whether tx glom is enabled/disabled */
387447 uint32 txglomsize; /* Glom size limitation */
388
- uint8 *membuf;
389448 #ifdef DHDENABLE_TAILPAD
390449 void *pad_pkt;
391450 #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 */
392458 } 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 */
393476
394477 /* clkstate */
395478 #define CLK_NONE 0
....@@ -414,9 +497,21 @@
414497 extern uint dhd_watchdog_ms;
415498 extern uint sd_f1_blocksize;
416499
500
+#ifdef BCMSPI_ANDROID
501
+extern uint *dhd_spi_lockcount;
502
+#endif /* BCMSPI_ANDROID */
417503
418504 extern void dhd_os_wd_timer(void *bus, uint wdtick);
419505 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 */
420515
421516 /* Tx/Rx bounds */
422517 uint dhd_txbound;
....@@ -440,8 +535,14 @@
440535 static bool retrydata;
441536 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
442537
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
443543 static uint watermark = 8;
444544 static uint mesbusyctrl = 0;
545
+#endif /* BCMSPI */
445546 static const uint firstread = DHD_FIRSTREAD;
446547
447548 /* Retry count for register access failures */
....@@ -450,14 +551,23 @@
450551 /* Force even SD lengths (some host controllers mess up on odd bytes) */
451552 static bool forcealign;
452553
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);
454557
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
457567
458568 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
459569 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
460
-#endif
570
+#endif // endif
461571
462572 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
463573 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
....@@ -480,9 +590,11 @@
480590 /* Try doing readahead */
481591 static bool dhd_readahead;
482592
593
+#define TXCTL_CREDITS 2
594
+
483595 /* To check if there's window offered */
484596 #define DATAOK(bus) \
485
- (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
597
+ (((uint8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS) && \
486598 (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
487599
488600 /* To check if there's window offered for ctrl frame */
....@@ -554,6 +666,37 @@
554666 #define SDIO_DEVICE_RXDATAINT_MODE_0 1 /* from sdiod rev 4 */
555667 #define SDIO_DEVICE_RXDATAINT_MODE_1 2 /* from sdiod rev 4 */
556668
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 */
557700
558701 #define FRAME_AVAIL_MASK(bus) \
559702 ((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
....@@ -566,10 +709,14 @@
566709
567710 #define GSPI_PR55150_BAILOUT
568711
712
+#endif /* BCMSPI */
713
+
714
+extern uint sd_f2_blocksize;
715
+
569716 #ifdef SDTEST
570717 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
571718 static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
572
-#endif
719
+#endif // endif
573720
574721 static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
575722 #ifdef DHD_DEBUG
....@@ -578,9 +725,27 @@
578725
579726 #if defined(DHD_FW_COREDUMP)
580727 static int dhdsdio_mem_dump(dhd_bus_t *bus);
728
+static int dhdsdio_get_mem_dump(dhd_bus_t *bus);
581729 #endif /* DHD_FW_COREDUMP */
582730 static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
731
+static int dhdsdio_readshared_console(dhd_bus_t *bus);
583732 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);
584749
585750 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
586751 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
....@@ -609,22 +774,28 @@
609774 static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
610775 static int _dhdsdio_download_firmware(dhd_bus_t *bus);
611776
777
+#ifdef DHD_UCODE_DOWNLOAD
778
+static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path);
779
+#endif /* DHD_UCODE_DOWNLOAD */
612780 static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
613781 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
617782 static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
618783 static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
619784 static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
620785 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);
621790
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) */
626798
627
-int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len);
628799 #ifdef DHD_ULP
629800 #include <dhd_ulp.h>
630801 static int dhd_bus_ulp_reinit_fw(dhd_bus_t *bus);
....@@ -702,6 +873,28 @@
702873 return err;
703874 }
704875
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 */
705898
706899 #ifdef USE_OOB_GPIO1
707900 static int
....@@ -711,8 +904,8 @@
711904
712905 bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
713906
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);
716909
717910 /* Set device for gpio1 wakeup */
718911 bcmsdh_reg_write(bus->sdh, addr, 4, 2);
....@@ -735,67 +928,66 @@
735928 bool cap = FALSE;
736929 uint32 core_capext, addr, data;
737930
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
+
738939 if (bus->sih->chip == BCM43430_CHIP_ID ||
739940 bus->sih->chip == BCM43018_CHIP_ID) {
740941 /* 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);
742943 if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
743944 cap = TRUE;
744945
745946 return cap;
746947 }
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) {
753950 core_capext = FALSE;
754951 } else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
755952 (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) ||
759954 (bus->sih->chip == BCM4354_CHIP_ID) ||
760
- (bus->sih->chip == BCM4356_CHIP_ID) ||
761955 (bus->sih->chip == BCM4358_CHIP_ID) ||
762956 (BCM4349_CHIP(bus->sih->chip)) ||
763957 (bus->sih->chip == BCM4350_CHIP_ID) ||
958
+#ifdef UNRELEASEDCHIP_FOR_ANDROID
959
+ (bus->sih->chip == BCM4362_CHIP_ID) ||
960
+#endif /* UNRELEASEDCHIP_FOR_ANDROID */
764961 (bus->sih->chip == BCM43012_CHIP_ID) ||
962
+ (bus->sih->chip == BCM43014_CHIP_ID) ||
963
+ (bus->sih->chip == BCM43751_CHIP_ID) ||
765964 (bus->sih->chip == BCM4373_CHIP_ID)) {
766965 core_capext = TRUE;
767966 } else {
768967 core_capext = bcmsdh_reg_read(bus->sdh,
769968 si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
770969 4);
970
+
771971 core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
772972 }
773973 if (!(core_capext))
774974 return FALSE;
775975
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) ||
780977 (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) ||
784979 (bus->sih->chip == BCM4354_CHIP_ID) ||
785
- (bus->sih->chip == BCM4356_CHIP_ID) ||
786980 (bus->sih->chip == BCM4358_CHIP_ID) ||
787981 (bus->sih->chip == BCM4350_CHIP_ID)) {
788982 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);
791985 bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
792986 enabval = bcmsdh_reg_read(bus->sdh, data, 4);
793987
794988 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) ||
797990 (bus->sih->chip == BCM4354_CHIP_ID) ||
798
- (bus->sih->chip == BCM4356_CHIP_ID) ||
799991 (bus->sih->chip == BCM4358_CHIP_ID))
800992 enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
801993
....@@ -813,29 +1005,14 @@
8131005 }
8141006
8151007 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
8291008 dhdsdio_sr_init(dhd_bus_t *bus)
8301009 {
8311010 uint8 val;
8321011 int err = 0;
8331012
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) {
8391016 val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
8401017 val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
8411018 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
....@@ -855,9 +1032,27 @@
8551032 (SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
8561033 #endif /* USE_CMD14 */
8571034
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 */
8591052
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) {
8611056 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
8621057 SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
8631058 } else {
....@@ -906,23 +1101,17 @@
9061101 #define KSO_WAKE_RETRY_COUNT 100
9071102 #define ERROR_BCME_NODEVICE_MAX 1
9081103
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
9121108
913
-#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
9141109 static int
9151110 dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
9161111 {
9171112 uint8 wr_val = 0, rd_val, cmp_val, bmask;
9181113 int err = 0;
9191114 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);
9261115
9271116 KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
9281117
....@@ -930,13 +1119,13 @@
9301119
9311120 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
9321121
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.
9371125 */
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)) {
9401129 return err;
9411130 }
9421131
....@@ -965,19 +1154,16 @@
9651154 OSL_DELAY(KSO_WAIT_US);
9661155
9671156 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);
9701158
9711159 if (try_cnt > 2)
9721160 KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
9731161 __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
9741162
975
- if (try_cnt > MAX_KSO_ATTEMPTS) {
1163
+ if (try_cnt > CUSTOM_MAX_KSO_ATTEMPTS) {
9761164 DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
9771165 __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
9781166 }
979
-
980
- mmc_retune_enable(host);
9811167
9821168 return err;
9831169 }
....@@ -1085,7 +1271,12 @@
10851271 #ifdef USE_CMD14
10861272 err = bcmsdh_sleep(bus->sdh, TRUE);
10871273 #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
+ }
10891280
10901281 err = dhdsdio_clk_kso_enab(bus, FALSE);
10911282 if (OOB_WAKEUP_ENAB(bus))
....@@ -1096,7 +1287,8 @@
10961287
10971288 if ((SLPAUTO_ENAB(bus)) && (bus->idleclock != DHD_IDLE_ACTIVE)) {
10981289 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);
11001292 }
11011293 } else {
11021294 /* Exit Sleep */
....@@ -1104,16 +1296,6 @@
11041296 if (bus->clkstate == CLK_NONE) {
11051297 DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
11061298 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
- }
11171299 }
11181300 #ifdef USE_CMD14
11191301 err = bcmsdh_sleep(bus->sdh, FALSE);
....@@ -1155,10 +1337,14 @@
11551337
11561338 if (err != 0) {
11571339 DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
1340
+#ifndef BT_OVER_SDIO
11581341 err = 0; /* continue anyway */
1342
+#endif /* BT_OVER_SDIO */
11591343 }
11601344
1161
-
1345
+ if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1346
+ dhdsdio_set_sdmode(bus, bus->sd_mode);
1347
+ }
11621348 #endif /* !USE_CMD14 */
11631349
11641350 if (err == 0) {
....@@ -1181,7 +1367,7 @@
11811367 SPINWAIT_SLEEP(sdioh_spinwait_sleep,
11821368 (((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
11831369 SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
1184
- (SBSDIO_HT_AVAIL)), (10000));
1370
+ (SBSDIO_HT_AVAIL)), (DHD_WAIT_HTAVAIL));
11851371
11861372 DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
11871373 if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
....@@ -1220,7 +1406,6 @@
12201406 clkctl = 0;
12211407 sdh = bus->sdh;
12221408
1223
-
12241409 if (!KSO_ENAB(bus))
12251410 return BCME_OK;
12261411
....@@ -1233,7 +1418,9 @@
12331418 /* Request HT Avail */
12341419 clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
12351420
1236
-
1421
+#ifdef BCMSPI
1422
+ dhdsdio_wkwlan(bus, TRUE);
1423
+#endif /* BCMSPI */
12371424
12381425 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
12391426 if (err) {
....@@ -1242,16 +1429,16 @@
12421429 DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
12431430 }
12441431
1245
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
1432
+#ifdef OEM_ANDROID
12461433 else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
1434
+ bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
12471435 dhd_os_send_hang_message(bus->dhd);
12481436 }
1249
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
1437
+#endif /* OEM_ANDROID */
12501438 return BCME_ERROR;
12511439 } else {
12521440 ht_avail_error = 0;
12531441 }
1254
-
12551442
12561443 /* Check current status */
12571444 clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
....@@ -1286,7 +1473,7 @@
12861473 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
12871474 }
12881475 }
1289
-
1476
+#ifndef BCMSDIOLITE
12901477 /* Otherwise, wait here (polling) for HT Avail */
12911478 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
12921479 SPINWAIT_SLEEP(sdioh_spinwait_sleep,
....@@ -1303,7 +1490,7 @@
13031490 __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
13041491 return BCME_ERROR;
13051492 }
1306
-
1493
+#endif /* BCMSDIOLITE */
13071494 /* Mark clock available */
13081495 bus->clkstate = CLK_AVAIL;
13091496 DHD_INFO(("CLKCTL: turned ON\n"));
....@@ -1346,6 +1533,25 @@
13461533 return BCME_ERROR;
13471534 }
13481535 }
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;
13491555 }
13501556 return BCME_OK;
13511557 }
....@@ -1354,6 +1560,7 @@
13541560 static int
13551561 dhdsdio_sdclk(dhd_bus_t *bus, bool on)
13561562 {
1563
+#ifndef BCMSPI
13571564 int err;
13581565 int32 iovalue;
13591566
....@@ -1371,14 +1578,6 @@
13711578 return BCME_ERROR;
13721579 }
13731580
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
- }
13821581 } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
13831582 /* Restore clock speed */
13841583 iovalue = bus->sd_divisor;
....@@ -1399,18 +1598,6 @@
13991598 return BCME_ERROR;
14001599 }
14011600 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
-
14141601 iovalue = 0;
14151602 err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
14161603 &iovalue, sizeof(iovalue), TRUE);
....@@ -1432,6 +1619,8 @@
14321619 }
14331620 bus->clkstate = CLK_NONE;
14341621 }
1622
+#else /* BCMSPI */
1623
+#endif /* !BCMSPI */
14351624
14361625 return BCME_OK;
14371626 }
....@@ -1476,6 +1665,27 @@
14761665 break;
14771666
14781667 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
+
14791689 /* Remove HT request, or bring up SD clock */
14801690 if (bus->clkstate == CLK_NONE)
14811691 ret = dhdsdio_sdclk(bus, TRUE);
....@@ -1490,13 +1700,33 @@
14901700 break;
14911701
14921702 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
+
14931723 /* Make sure to remove HT request */
14941724 if (bus->clkstate == CLK_AVAIL)
14951725 ret = dhdsdio_htclk(bus, FALSE, FALSE);
14961726 /* Now remove the SD clock */
14971727 ret = dhdsdio_sdclk(bus, FALSE);
14981728 #ifdef DHD_DEBUG
1499
- if (dhd_console_ms == 0)
1729
+ if (bus->dhd->dhd_console_ms == 0)
15001730 #endif /* DHD_DEBUG */
15011731 if (bus->poll == 0)
15021732 dhd_os_wd_timer(bus->dhd, 0);
....@@ -1516,6 +1746,9 @@
15161746 bcmsdh_info_t *sdh = bus->sdh;
15171747 sdpcmd_regs_t *regs = bus->regs;
15181748 uint retries = 0;
1749
+#if defined(BCMSDIOH_STD)
1750
+ uint32 sd3_tuning_disable = FALSE;
1751
+#endif /* BCMSDIOH_STD */
15191752
15201753 DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
15211754 (sleep ? "SLEEP" : "WAKE"),
....@@ -1531,9 +1764,33 @@
15311764 /* Going to sleep: set the alarm and turn off the lights... */
15321765 if (sleep) {
15331766 /* 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 */
15351773 return BCME_BUSY;
15361774
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 */
15371794
15381795 if (!SLPAUTO_ENAB(bus)) {
15391796 /* Disable SDIO interrupts (no longer interested) */
....@@ -1554,11 +1811,8 @@
15541811 SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
15551812
15561813 /* 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,
15601815 SBSDIO_DEVCTL_PADS_ISO, NULL);
1561
- }
15621816 } else {
15631817 /* Leave interrupts enabled since device can exit sleep and
15641818 * interrupt host
....@@ -1568,7 +1822,12 @@
15681822
15691823 /* Change state */
15701824 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)
15721831 wake_up(&bus->bus_sleep);
15731832 #endif /* LINUX && SUPPORT_P2P_GO_PS */
15741833 } else {
....@@ -1579,7 +1838,6 @@
15791838
15801839 /* Force pad isolation off if possible (in case power never toggled) */
15811840 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
1582
-
15831841
15841842 /* Make sure the controller has the bus up */
15851843 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
....@@ -1602,23 +1860,154 @@
16021860 }
16031861 } else {
16041862 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 */
16051878 }
16061879
16071880 if (err == 0) {
16081881 /* Change state */
16091882 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 */
16101888 }
16111889 }
16121890
16131891 return err;
16141892 }
16151893
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;
16161905
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)
16182005 void
16192006 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
16202007 {
1621
-#if defined(HW_OOB)
2008
+#if defined(BCMSPI_ANDROID)
2009
+ bcmsdh_intr_enable(bus->sdh);
2010
+#elif defined(HW_OOB)
16222011 bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
16232012 #else
16242013 sdpcmd_regs_t *regs = bus->regs;
....@@ -1643,7 +2032,7 @@
16432032 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
16442033 #endif /* !defined(HW_OOB) */
16452034 }
1646
-#endif
2035
+#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
16472036
16482037 int
16492038 dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
....@@ -1651,9 +2040,11 @@
16512040 int ret = BCME_ERROR;
16522041 osl_t *osh;
16532042 uint datalen, prec;
2043
+#ifdef REVERSE_AIFSN
2044
+ uint prio;
2045
+#endif /* REVERSE_AIFSN */
16542046 #if defined(DHD_TX_DUMP)
16552047 uint8 *dump_data;
1656
- uint16 protocol;
16572048 #endif /* DHD_TX_DUMP */
16582049
16592050 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
....@@ -1681,18 +2072,9 @@
16812072 dhd_ulp_set_path(bus->dhd, DHD_ULP_TX_DATA);
16822073 #endif /* DHD_ULP */
16832074
1684
-#if defined(DHD_TX_DUMP)
2075
+#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
16852076 dump_data = PKTDATA(osh, pkt);
16862077 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)
16962078 {
16972079 int i;
16982080 DHD_ERROR(("TX DUMP\n"));
....@@ -1707,15 +2089,27 @@
17072089 #endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
17082090
17092091 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 */
17102103
17112104 /* 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 ||
17132106 (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
17142107 (bus->clkstate != CLK_AVAIL)) {
17152108 bool deq_ret;
17162109 int pkq_len;
17172110
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)));
17192113 bus->fcqueued++;
17202114
17212115 /* Priority based enq */
....@@ -1743,14 +2137,14 @@
17432137 ret = BCME_OK;
17442138
17452139 dhd_os_sdlock_txq(bus->dhd);
1746
- pkq_len = pktq_len(&bus->txq);
2140
+ pkq_len = pktq_n_pkts_tot(&bus->txq);
17472141 dhd_os_sdunlock_txq(bus->dhd);
17482142 if (pkq_len >= FCHI) {
17492143 bool wlfc_enabled = FALSE;
17502144 #ifdef PROP_TXSTATUS
17512145 wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
17522146 WLFC_UNSUPPORTED);
1753
-#endif
2147
+#endif // endif
17542148 if (!wlfc_enabled && dhd_doflow) {
17552149 dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
17562150 }
....@@ -1758,10 +2152,10 @@
17582152
17592153 #ifdef DHD_DEBUG
17602154 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);
17632157 dhd_os_sdunlock_txq(bus->dhd);
1764
-#endif
2158
+#endif // endif
17652159
17662160 /* Schedule DPC if needed to send queued packet(s) */
17672161 if (dhd_deferred_tx && !bus->dpc_sched) {
....@@ -1773,7 +2167,7 @@
17732167
17742168 #ifdef SDTEST
17752169 chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
1776
-#endif
2170
+#endif // endif
17772171 /* Lock: we're about to use shared data/code (and SDIO) */
17782172 dhd_os_sdlock(bus->dhd);
17792173
....@@ -1789,7 +2183,8 @@
17892183 else
17902184 bus->dhd->dstats.tx_bytes += datalen;
17912185
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)) {
17932188 bus->activity = FALSE;
17942189 dhdsdio_bussleep(bus, TRUE);
17952190 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -1848,16 +2243,6 @@
18482243 frame = (uint8*)PKTDATA(osh, pkt);
18492244 pkt_len = (uint16)PKTLEN(osh, pkt);
18502245
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 */
18612246 #ifdef DHD_DEBUG
18622247 if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
18632248 tx_packets[PKTPRIO(pkt)]++;
....@@ -1866,11 +2251,13 @@
18662251 /* align the data pointer, allocate a new packet if there is not enough space (new
18672252 * packet data pointer will be aligned thus no padding will be needed)
18682253 */
1869
- head_padding = (ulong)frame % DHD_SDALIGN;
2254
+ head_padding = (uintptr)frame % DHD_SDALIGN;
18702255 if (PKTHEADROOM(osh, pkt) < head_padding) {
18712256 head_padding = 0;
18722257 alloc_new_pkt = TRUE;
18732258 } else {
2259
+ /* gSPI expects that hw-header-len is equal to spi-command-len */
2260
+#ifndef BCMSPI
18742261 uint cur_chain_total_len;
18752262 int chain_tail_padding = 0;
18762263
....@@ -1919,6 +2306,7 @@
19192306 */
19202307 #endif /* DHDENABLE_TAILPAD */
19212308 tail_padding += chain_tail_padding;
2309
+#endif /* !BCMSPI */
19222310 }
19232311
19242312 DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
....@@ -1945,8 +2333,7 @@
19452333 (cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
19462334 modulo = cur_total_len % bus->blocksize;
19472335 tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
1948
- }
1949
- else {
2336
+ } else {
19502337 modulo = pkt_len % DHD_SDALIGN;
19512338 tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
19522339 }
....@@ -2092,6 +2479,9 @@
20922479 if (bus->dhd->dongle_reset)
20932480 return BCME_NOTREADY;
20942481
2482
+ if (num_pkt <= 0)
2483
+ return BCME_BADARG;
2484
+
20952485 sdh = bus->sdh;
20962486 osh = bus->dhd->osh;
20972487 /* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
....@@ -2202,6 +2592,14 @@
22022592 uint datalen = 0;
22032593 dhd_pub_t *dhd = bus->dhd;
22042594 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 */
22052603
22062604 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
22072605
....@@ -2214,7 +2612,7 @@
22142612 tx_prec_map = ~bus->flowcontrol;
22152613 #ifdef DHD_LOSSLESS_ROAMING
22162614 tx_prec_map &= dhd->dequeue_prec_map;
2217
-#endif
2615
+#endif /* DHD_LOSSLESS_ROAMING */
22182616 for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
22192617 int i;
22202618 int num_pkt = 1;
....@@ -2241,6 +2639,29 @@
22412639 ASSERT(0);
22422640 break;
22432641 }
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 */
22442665 PKTORPHAN(pkts[i]);
22452666 datalen += PKTLEN(osh, pkts[i]);
22462667 }
....@@ -2269,7 +2690,7 @@
22692690 }
22702691
22712692 dhd_os_sdlock_txq(bus->dhd);
2272
- txpktqlen = pktq_len(&bus->txq);
2693
+ txpktqlen = pktq_n_pkts_tot(&bus->txq);
22732694 dhd_os_sdunlock_txq(bus->dhd);
22742695
22752696 /* Do flow-control if needed */
....@@ -2277,7 +2698,7 @@
22772698 bool wlfc_enabled = FALSE;
22782699 #ifdef PROP_TXSTATUS
22792700 wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
2280
-#endif
2701
+#endif // endif
22812702 if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
22822703 dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
22832704 }
....@@ -2345,6 +2766,7 @@
23452766 }
23462767 doff += sdpcm_hdrlen;
23472768
2769
+#ifndef BCMSPI
23482770 /* Round send length to next SDIO block */
23492771 if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
23502772 uint16 pad = bus->blocksize - (len % bus->blocksize);
....@@ -2353,13 +2775,13 @@
23532775 } else if (len % DHD_SDALIGN) {
23542776 len += DHD_SDALIGN - (len % DHD_SDALIGN);
23552777 }
2778
+#endif /* BCMSPI */
23562779
23572780 /* Satisfy length-alignment requirements */
23582781 if (forcealign && (len & (ALIGNMENT - 1)))
23592782 len = ROUNDUP(len, ALIGNMENT);
23602783
23612784 ASSERT(ISALIGNED((uintptr)frame, 2));
2362
-
23632785
23642786 /* Need to lock here to protect txseq and SDIO tx calls */
23652787 dhd_os_sdlock(bus->dhd);
....@@ -2404,7 +2826,7 @@
24042826 if (!TXCTLOK(bus) || !dhd_ulp_f2_ready(bus->dhd, bus->sdh))
24052827 #else
24062828 if (!TXCTLOK(bus))
2407
-#endif
2829
+#endif // endif
24082830 {
24092831 DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
24102832 __FUNCTION__, bus->tx_max, bus->tx_seq));
....@@ -2427,9 +2849,28 @@
24272849 } else {
24282850 bus->dhd->txcnt_timeout++;
24292851 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 */
24302860 DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
24312861 __FUNCTION__, bus->dhd->txcnt_timeout));
24322862 }
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 */
24332874 ret = -1;
24342875 bus->ctrl_frame_stat = FALSE;
24352876 goto done;
....@@ -2446,9 +2887,8 @@
24462887 } else if (DHD_HDRS_ON()) {
24472888 prhex("TxHdr", frame, MIN(len, 16));
24482889 }
2449
-#endif
2890
+#endif // endif
24502891 ret = dhd_bcmsdh_send_buffer(bus, frame, len);
2451
-
24522892 }
24532893 bus->ctrl_frame_stat = FALSE;
24542894 #ifdef DHD_ULP
....@@ -2456,7 +2896,8 @@
24562896 #endif /* DHD_ULP */
24572897
24582898 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)) {
24602901 bus->activity = FALSE;
24612902 dhdsdio_bussleep(bus, TRUE);
24622903 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -2469,9 +2910,17 @@
24692910 else
24702911 bus->dhd->tx_ctlpkts++;
24712912
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 {
24732918 return -ETIMEDOUT;
2474
-
2919
+ }
2920
+#else
2921
+ return -ETIMEDOUT;
2922
+#endif /* DHD_PM_CONTROL_FROM_FILE */
2923
+ }
24752924 if (ret == BCME_NODEVICE)
24762925 err_nodevice++;
24772926 else
....@@ -2503,41 +2952,73 @@
25032952 if (rxlen) {
25042953 DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
25052954 __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);
25182955 } 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 */
25232989 }
25242990 if (timeleft == 0) {
25252991 if (rxlen == 0)
25262992 bus->dhd->rxcnt_timeout++;
25272993 DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
25282994 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 {
25313003 bus->dhd->rxcnt_timeout = 0;
3004
+ }
25323005
25333006 if (rxlen)
25343007 bus->dhd->rx_ctlpkts++;
25353008 else
25363009 bus->dhd->rx_ctlerrs++;
25373010
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
25393019 return -ETIMEDOUT;
2540
-
3020
+#endif /* DHD_PM_CONTROL_FROM_FILE */
3021
+ }
25413022 if (bus->dhd->dongle_trap_occured)
25423023 return -EREMOTEIO;
25433024
....@@ -2551,7 +3032,9 @@
25513032 IOV_SDREG,
25523033 IOV_SBREG,
25533034 IOV_SDCIS,
3035
+#ifdef DHD_BUS_MEM_ACCESS
25543036 IOV_MEMBYTES,
3037
+#endif /* DHD_BUS_MEM_ACCESS */
25553038 IOV_RAMSIZE,
25563039 IOV_RAMSTART,
25573040 #ifdef DHD_DEBUG
....@@ -2572,6 +3055,9 @@
25723055 IOV_WATERMARK,
25733056 IOV_MESBUSYCTRL,
25743057 #endif /* USE_SDIOFIFO_IOVAR */
3058
+#if defined(BT_OVER_SDIO)
3059
+ IOV_SDF3,
3060
+#endif /* defined (BT_OVER_SDIO) */
25753061 #ifdef SDTEST
25763062 IOV_PKTGEN,
25773063 IOV_EXTLOOP,
....@@ -2591,65 +3077,78 @@
25913077 IOV_VARS,
25923078 #ifdef SOFTAP
25933079 IOV_FWPATH,
2594
-#endif
3080
+#endif // endif
25953081 IOV_TXGLOMSIZE,
25963082 IOV_TXGLOMMODE,
25973083 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 */
25993089 };
26003090
26013091 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 },
26203112 #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 },
26293121 #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 },
26323124 #endif /* DHD_DEBUG */
26333125 #endif /* DHD_DEBUG */
26343126 #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) },
26373129 #endif /* SDTEST */
26383130 #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 },
26413133 #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 },
26463141 #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 }
26533152 };
26543153
26553154 static void
....@@ -2670,15 +3169,43 @@
26703169 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
26713170 {
26723171 dhd_bus_t *bus = dhdp->bus;
3172
+#if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS)
3173
+ int i;
3174
+#endif // endif
26733175
26743176 bcm_bprintf(strbuf, "Bus SDIO structure:\n");
26753177 bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
26763178 bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
26773179 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,
26793181 bus->rxlen, bus->rx_seq);
26803182 bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
26813183 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
+
26823209 bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
26833210 bus->pollrate, bus->pollcnt, bus->regfails);
26843211
....@@ -2862,11 +3389,6 @@
28623389 else
28633390 dsize = size;
28643391
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
-
28703392 /* Set the backplane window to include the start address */
28713393 if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
28723394 DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
....@@ -2878,15 +3400,9 @@
28783400 DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
28793401 __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
28803402 (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))) {
28853404 DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
28863405 break;
2887
- }
2888
- if (!write) {
2889
- memcpy(data, bus->membuf, dsize);
28903406 }
28913407
28923408 /* Adjust for next transfer (if any) */
....@@ -2919,6 +3435,11 @@
29193435 uint32 addr;
29203436 int rv, i;
29213437 uint32 shaddr = 0;
3438
+
3439
+ /* This temporary WAR for now */
3440
+#if defined(PLATFORM_IMX)
3441
+ return BCME_OK;
3442
+#endif /* defined(PLATFORM_IMX) */
29223443
29233444 if (bus->sih == NULL) {
29243445 if (bus->dhd && bus->dhd->dongle_reset) {
....@@ -2989,6 +3510,59 @@
29893510 return BCME_OK;
29903511 }
29913512
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
+
29923566 #define CONSOLE_LINE_MAX 192
29933567
29943568 #ifdef DHD_DEBUG
....@@ -3000,6 +3574,9 @@
30003574 uint32 n, idx, addr;
30013575 int rv;
30023576
3577
+ if (!DHD_FWLOG_ON())
3578
+ return 0;
3579
+
30033580 /* Don't do anything until FWREADY updates console address */
30043581 if (bus->console_addr == 0)
30053582 return 0;
....@@ -3009,6 +3586,21 @@
30093586
30103587 /* Read console log struct */
30113588 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
+
30123604 if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
30133605 return rv;
30143606
....@@ -3028,6 +3620,9 @@
30283620 /* Skip reading the console buffer if the index pointer has not moved */
30293621 if (idx == c->last)
30303622 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));
30313626
30323627 /* Read the console buffer */
30333628 addr = ltoh32(c->log.buf);
....@@ -3078,8 +3673,7 @@
30783673 char *console_buffer = NULL;
30793674 uint maxstrlen = 256;
30803675 char *str = NULL;
3081
- trap_t tr;
3082
- sdpcm_shared_t sdpcm_shared;
3676
+ sdpcm_shared_t l_sdpcm_shared;
30833677 struct bcmstrbuf strbuf;
30843678 uint32 console_ptr, console_size, console_index;
30853679 uint8 line[CONSOLE_LINE_MAX], ch;
....@@ -3111,36 +3705,36 @@
31113705 goto done;
31123706 }
31133707
3114
- if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
3708
+ if ((bcmerror = dhdsdio_readshared(bus, &l_sdpcm_shared)) < 0)
31153709 goto done;
31163710
31173711 bcm_binit(&strbuf, data, size);
31183712
31193713 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);
31213715
3122
- if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
3716
+ if ((l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
31233717 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
31243718 * (Avoids conflict with real asserts for programmatic parsing of output.)
31253719 */
31263720 bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
31273721 }
31283722
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) {
31303724 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
31313725 * (Avoids conflict with real asserts for programmatic parsing of output.)
31323726 */
31333727 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)
31353729 ?"/assrt" :"");
31363730 } else {
3137
- if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
3731
+ if (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
31383732 /* Download assert */
31393733 bcm_bprintf(&strbuf, "Dongle assert");
3140
- if (sdpcm_shared.assert_exp_addr != 0) {
3734
+ if (l_sdpcm_shared.assert_exp_addr != 0) {
31413735 str[0] = '\0';
31423736 if ((bcmerror = dhdsdio_membytes(bus, FALSE,
3143
- sdpcm_shared.assert_exp_addr,
3737
+ l_sdpcm_shared.assert_exp_addr,
31443738 (uint8 *)str, maxstrlen)) < 0)
31453739 goto done;
31463740
....@@ -3148,10 +3742,10 @@
31483742 bcm_bprintf(&strbuf, " expr \"%s\"", str);
31493743 }
31503744
3151
- if (sdpcm_shared.assert_file_addr != 0) {
3745
+ if (l_sdpcm_shared.assert_file_addr != 0) {
31523746 str[0] = '\0';
31533747 if ((bcmerror = dhdsdio_membytes(bus, FALSE,
3154
- sdpcm_shared.assert_file_addr,
3748
+ l_sdpcm_shared.assert_file_addr,
31553749 (uint8 *)str, maxstrlen)) < 0)
31563750 goto done;
31573751
....@@ -3159,38 +3753,32 @@
31593753 bcm_bprintf(&strbuf, " file \"%s\"", str);
31603754 }
31613755
3162
- bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
3756
+ bcm_bprintf(&strbuf, " line %d ", l_sdpcm_shared.assert_line);
31633757 }
31643758
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;
31663761 bus->dhd->dongle_trap_occured = TRUE;
31673762 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)
31703765 goto done;
31713766
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);
31823768
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);
31843772 if ((rv = dhdsdio_membytes(bus, FALSE, addr,
31853773 (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
31863774 goto printbuf;
31873775
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);
31893777 if ((rv = dhdsdio_membytes(bus, FALSE, addr,
31903778 (uint8 *)&console_size, sizeof(console_size))) < 0)
31913779 goto printbuf;
31923780
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);
31943782 if ((rv = dhdsdio_membytes(bus, FALSE, addr,
31953783 (uint8 *)&console_index, sizeof(console_index))) < 0)
31963784 goto printbuf;
....@@ -3215,7 +3803,6 @@
32153803 line[n] = ch;
32163804 }
32173805
3218
-
32193806 if (n > 0) {
32203807 if (line[n - 1] == '\r')
32213808 n--;
....@@ -3233,14 +3820,17 @@
32333820 }
32343821
32353822 printbuf:
3236
- if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
3823
+ if (l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
32373824 DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
32383825 }
32393826
32403827 #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)) {
32423829 /* Mem dump to a file on device */
3830
+ bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP;
3831
+ dhd_os_sdunlock(bus->dhd);
32433832 dhdsdio_mem_dump(bus);
3833
+ dhd_os_sdlock(bus->dhd);
32443834 }
32453835 #endif /* #if defined(DHD_FW_COREDUMP) */
32463836
....@@ -3256,49 +3846,103 @@
32563846 }
32573847
32583848 #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)
32613851 {
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
+}
32673859
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;
32743866 }
32753867
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
+
32763893 /* 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) {
32813897 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;
32863903 }
32873904 /* Decrement size and increment start address */
32883905 size -= read_size;
32893906 start += read_size;
32903907 databuf += read_size;
32913908 }
3292
- printf("Done\n");
32933909
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);
32993914 }
33003915
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;
33023946 }
33033947 #endif /* DHD_FW_COREDUMP */
33043948
....@@ -3309,7 +3953,7 @@
33093953 return (dhdsdio_mem_dump(bus));
33103954 #else
33113955 return -1;
3312
-#endif
3956
+#endif // endif
33133957 }
33143958
33153959 int
....@@ -3350,22 +3994,14 @@
33503994 }
33513995
33523996 #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
-
33593997 static int
33603998 dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
33613999 {
33624000 int int_val;
33634001 uint32 addr, data, uart_enab = 0;
3364
- uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL;
3365
- uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL;
33664002
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);
33694005 *bcmerror = 0;
33704006
33714007 bcmsdh_reg_write(bus->sdh, addr, 4, 1);
....@@ -3377,24 +4013,6 @@
33774013 if (bcmsdh_regfail(bus->sdh)) {
33784014 *bcmerror = BCME_SDIO_ERROR;
33794015 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;
33984016 }
33994017
34004018 if (!set)
....@@ -3408,21 +4026,10 @@
34084026 *bcmerror = BCME_SDIO_ERROR;
34094027 return -1;
34104028 }
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
- }
34224029
34234030 return (int_val & uart_enab);
34244031 }
3425
-#endif
4032
+#endif // endif
34264033
34274034 static int
34284035 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
....@@ -3442,7 +4049,6 @@
34424049 bcopy(params, &int_val, sizeof(int_val));
34434050
34444051 bool_val = (int_val != 0) ? TRUE : FALSE;
3445
-
34464052
34474053 /* Some ioctls use the bus */
34484054 dhd_os_sdlock(bus->dhd);
....@@ -3553,7 +4159,13 @@
35534159 sd1idle = bool_val;
35544160 break;
35554161
4162
+#ifdef DHD_DEBUG
4163
+ case IOV_GVAL(IOV_CHECKDIED):
4164
+ bcmerror = dhdsdio_checkdied(bus, arg, len);
4165
+ break;
4166
+#endif /* DHD_DEBUG */
35564167
4168
+#ifdef DHD_BUS_MEM_ACCESS
35574169 case IOV_SVAL(IOV_MEMBYTES):
35584170 case IOV_GVAL(IOV_MEMBYTES):
35594171 {
....@@ -3580,7 +4192,13 @@
35804192
35814193 DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
35824194 (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
35844202 /* check if CR4 */
35854203 if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
35864204 /*
....@@ -3642,6 +4260,7 @@
36424260
36434261 break;
36444262 }
4263
+#endif /* DHD_BUS_MEM_ACCESS */
36454264
36464265 case IOV_GVAL(IOV_RAMSIZE):
36474266 int_val = (int32)bus->ramsize;
....@@ -3697,6 +4316,7 @@
36974316 else
36984317 bus->use_rxchain = bool_val;
36994318 break;
4319
+#ifndef BCMSPI
37004320 case IOV_GVAL(IOV_ALIGNCTL):
37014321 int_val = (int32)dhd_alignctl;
37024322 bcopy(&int_val, arg, val_size);
....@@ -3705,6 +4325,7 @@
37054325 case IOV_SVAL(IOV_ALIGNCTL):
37064326 dhd_alignctl = bool_val;
37074327 break;
4328
+#endif /* BCMSPI */
37084329
37094330 case IOV_GVAL(IOV_SDALIGN):
37104331 int_val = DHD_SDALIGN;
....@@ -3724,11 +4345,12 @@
37244345 case IOV_GVAL(IOV_SDREG):
37254346 {
37264347 sdreg_t *sd_ptr;
3727
- uint32 addr, size;
4348
+ uintptr addr;
4349
+ uint size;
37284350
37294351 sd_ptr = (sdreg_t *)params;
37304352
3731
- addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
4353
+ addr = ((uintptr)bus->regs + sd_ptr->offset);
37324354 size = sd_ptr->func;
37334355 int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
37344356 if (bcmsdh_regfail(bus->sdh))
....@@ -3740,11 +4362,12 @@
37404362 case IOV_SVAL(IOV_SDREG):
37414363 {
37424364 sdreg_t *sd_ptr;
3743
- uint32 addr, size;
4365
+ uintptr addr;
4366
+ uint size;
37444367
37454368 sd_ptr = (sdreg_t *)params;
37464369
3747
- addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
4370
+ addr = ((uintptr)bus->regs + sd_ptr->offset);
37484371 size = sd_ptr->func;
37494372 bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
37504373 if (bcmsdh_regfail(bus->sdh))
....@@ -3760,7 +4383,7 @@
37604383
37614384 bcopy(params, &sdreg, sizeof(sdreg));
37624385
3763
- addr = SI_ENUM_BASE + sdreg.offset;
4386
+ addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
37644387 size = sdreg.func;
37654388 int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
37664389 if (bcmsdh_regfail(bus->sdh))
....@@ -3776,7 +4399,7 @@
37764399
37774400 bcopy(params, &sdreg, sizeof(sdreg));
37784401
3779
- addr = SI_ENUM_BASE + sdreg.offset;
4402
+ addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
37804403 size = sdreg.func;
37814404 bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
37824405 if (bcmsdh_regfail(bus->sdh))
....@@ -3833,6 +4456,7 @@
38334456 dhd_txminmax = (uint)int_val;
38344457 break;
38354458
4459
+#ifdef DHD_DEBUG
38364460 case IOV_GVAL(IOV_SERIALCONS):
38374461 int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
38384462 if (bcmerror != 0)
....@@ -3844,10 +4468,9 @@
38444468 case IOV_SVAL(IOV_SERIALCONS):
38454469 dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
38464470 break;
3847
-
3848
-
38494471 #endif /* DHD_DEBUG */
38504472
4473
+#endif /* DHD_DEBUG */
38514474
38524475 #ifdef SDTEST
38534476 case IOV_GVAL(IOV_EXTLOOP):
....@@ -3894,9 +4517,35 @@
38944517 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
38954518 ((uint8)mesbusyctrl | 0x80), NULL);
38964519 break;
3897
-#endif
4520
+#endif // endif
38984521
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));
38994531
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) */
39004549 case IOV_GVAL(IOV_DONGLEISOLATION):
39014550 int_val = bus->dhd->dongle_isolation;
39024551 bcopy(&int_val, arg, val_size);
....@@ -3914,8 +4563,10 @@
39144563 ASSERT(bus->dhd->osh);
39154564 /* ASSERT(bus->cl_devid); */
39164565
4566
+ /* must release sdlock, since devreset also acquires it */
4567
+ dhd_os_sdunlock(bus->dhd);
39174568 dhd_bus_devreset(bus->dhd, (uint8)bool_val);
3918
-
4569
+ dhd_os_sdlock(bus->dhd);
39194570 break;
39204571 /*
39214572 * softap firmware is updated through module parameter or android private command
....@@ -3977,13 +4628,38 @@
39774628 }
39784629 break;
39794630
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
+
39804655 default:
39814656 bcmerror = BCME_UNSUPPORTED;
39824657 break;
39834658 }
39844659
39854660 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)) {
39874663 bus->activity = FALSE;
39884664 dhdsdio_bussleep(bus, TRUE);
39894665 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -4006,10 +4682,10 @@
40064682 uint8 *nvram_ularray;
40074683 #endif /* DHD_DEBUG */
40084684
4685
+#define TOKENSIZE 4
40094686 /* Even if there are no vars are to be written, we still need to set the ramsize. */
40104687 varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
4011
- varaddr = (bus->ramsize - 4) - varsize;
4012
-
4688
+ varaddr = bus->ramsize - varsize - TOKENSIZE;
40134689 varaddr += bus->dongle_ram_base;
40144690
40154691 if (bus->vars) {
....@@ -4021,21 +4697,41 @@
40214697 }
40224698 }
40234699
4024
- vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
4700
+ vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize + TOKENSIZE);
40254701 if (!vbuffer)
40264702 return BCME_NOMEM;
40274703
4028
- bzero(vbuffer, varsize);
4704
+ bzero(vbuffer, varsize + TOKENSIZE);
40294705 bcopy(bus->vars, vbuffer, bus->varsz);
40304706
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
+
40314719 /* 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
+
40334727 #ifdef DHD_DEBUG
40344728 /* Verify NVRAM bytes */
40354729 DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
40364730 nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
4037
- if (!nvram_ularray)
4731
+ if (!nvram_ularray) {
4732
+ MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE);
40384733 return BCME_NOMEM;
4734
+ }
40394735
40404736 /* Upload image to verify downloaded contents. */
40414737 memset(nvram_ularray, 0xaa, varsize);
....@@ -4055,8 +4751,8 @@
40554751
40564752 MFREE(bus->dhd->osh, nvram_ularray, varsize);
40574753 #endif /* DHD_DEBUG */
4754
+ MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE);
40584755
4059
- MFREE(bus->dhd->osh, vbuffer, varsize);
40604756 }
40614757
40624758 phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
....@@ -4068,27 +4764,14 @@
40684764 phys_size, bus->ramsize));
40694765 DHD_INFO(("Vars are at %d, orig varsize is %d\n",
40704766 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);
40904767
40914768 return bcmerror;
4769
+}
4770
+
4771
+bool
4772
+dhd_bus_is_multibp_capable(struct dhd_bus *bus)
4773
+{
4774
+ return MULTIBP_CAP(bus->sih);
40924775 }
40934776
40944777 static int
....@@ -4097,9 +4780,20 @@
40974780 uint retries;
40984781 int bcmerror = 0;
40994782 int foundcr4 = 0;
4783
+ hs_addrs_t bl_hs_addrs = {NULL, NULL};
41004784
41014785 if (!bus->sih)
41024786 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
+
41034797 /* To enter download state, disable ARM and reset SOCRAM.
41044798 * To exit download state, simply reset ARM (default is RAM boot).
41054799 */
....@@ -4165,9 +4859,37 @@
41654859 * [next] Download firmware
41664860 * [done at else] Populate the reset vector
41674861 * [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
+ }
41714893 }
41724894 } else {
41734895 if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
....@@ -4193,15 +4915,21 @@
41934915 */
41944916 if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih))
41954917 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
41974925 if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
41984926 !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
41994927 DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
42004928 bcmerror = BCME_ERROR;
42014929 goto fail;
42024930 }
4931
+#endif // endif
42034932 W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
4204
-
42054933
42064934 if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
42074935 !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
....@@ -4210,19 +4938,59 @@
42104938 goto fail;
42114939 }
42124940 } 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
+
42134974 /* cr4 has no socram, but tcm's */
42144975 /* write vars */
42154976 if ((bcmerror = dhdsdio_write_vars(bus))) {
42164977 DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
42174978 goto fail;
42184979 }
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
42204987 if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
42214988 !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
42224989 DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
42234990 bcmerror = BCME_ERROR;
42244991 goto fail;
42254992 }
4993
+#endif // endif
42264994 W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
42274995
42284996 /* switch back to arm core again */
....@@ -4232,30 +5000,50 @@
42325000 goto fail;
42335001 }
42345002 /* 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));
42375007
4238
- if (bcmerror == BCME_OK) {
4239
- uint32 tmp;
5008
+ if (bcmerror == BCME_OK) {
5009
+ uint32 tmp;
42405010
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));
42445014
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
+ }
42525023 }
42535024 }
4254
-
4255
- /* now remove reset and halt and continue to run CR4 */
42565025 }
42575026
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
+ }
42595047 if (bcmsdh_regfail(bus->sdh)) {
42605048 DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
42615049 bcmerror = BCME_SDIO_ERROR;
....@@ -4269,9 +5057,258 @@
42695057 }
42705058
42715059 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
+ }
42725078 /* Always return to SDIOD core */
42735079 if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
42745080 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
+ }
42755312
42765313 return bcmerror;
42775314 }
....@@ -4338,17 +5375,19 @@
43385375 if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
43395376 &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
43405377 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"));
43425380 } 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));
43455383
43465384 dhdsdio_tune_fifoparam(bus);
43475385 }
43485386 }
43495387 bus->roundup = MIN(max_roundup, bus->blocksize);
43505388
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)) {
43525391 bus->activity = FALSE;
43535392 dhdsdio_bussleep(bus, TRUE);
43545393 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -4408,6 +5447,7 @@
44085447
44095448 if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
44105449 /* if Firmware already hangs disbale any interrupt */
5450
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
44115451 bus->dhd->busstate = DHD_BUS_DOWN;
44125452 bus->hostintmask = 0;
44135453 bcmsdh_intr_disable(bus->sdh);
....@@ -4426,9 +5466,10 @@
44265466 bus->hostintmask = 0;
44275467
44285468 /* 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__));
44305471 bus->dhd->busstate = DHD_BUS_DOWN;
4431
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
5472
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
44325473
44335474 /* Force clocks on backplane to be sure F2 interrupt propagates */
44345475 saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
....@@ -4444,7 +5485,9 @@
44445485 /* Turn off the bus (F2), free any pending packets */
44455486 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
44465487 bcmsdh_intr_disable(bus->sdh);
5488
+#ifndef BCMSPI
44475489 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
5490
+#endif /* !BCMSPI */
44485491
44495492 /* Clear any pending interrupts now that F2 is disabled */
44505493 W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
....@@ -4456,7 +5499,7 @@
44565499
44575500 #ifdef PROP_TXSTATUS
44585501 wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
4459
-#endif
5502
+#endif // endif
44605503 if (!wlfc_enabled) {
44615504 #ifdef DHDTCPACK_SUPPRESS
44625505 /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
....@@ -4464,8 +5507,10 @@
44645507 */
44655508 dhd_tcpack_info_tbl_clean(bus->dhd);
44665509 #endif /* DHDTCPACK_SUPPRESS */
5510
+ dhd_os_sdlock_txq(bus->dhd);
44675511 /* 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);
44695514 }
44705515
44715516 /* Clear any held glomming stuff */
....@@ -4491,9 +5536,9 @@
44915536 dhd_os_sdunlock(bus->dhd);
44925537 }
44935538
4494
-#if defined(BCMSDIOH_TXGLOM) && (defined(BCMSDIOH_STD) || defined(BCMLXSDMMC))
5539
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
44955540 extern uint sd_txglom;
4496
-#endif
5541
+#endif // endif
44975542 void
44985543 dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
44995544 {
....@@ -4508,21 +5553,21 @@
45085553
45095554 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
45105555
4511
-#if defined(BCMSDIOH_STD) || defined(BCMLXSDMMC)
5556
+#ifdef BCMSDIOH_STD
45125557 if (enable)
45135558 enable = sd_txglom;
4514
-#endif /* defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) */
5559
+#endif /* BCMSDIOH_STD */
45155560
45165561 if (enable) {
45175562 rxglom = 1;
45185563 ret = dhd_iovar(dhdp, 0, "bus:rxglom", (char *)&rxglom, sizeof(rxglom), NULL, 0,
4519
- TRUE);
5564
+ TRUE);
45205565 if (ret >= 0)
45215566 bus->txglom_enable = TRUE;
45225567 else {
4523
-#if defined(BCMSDIOH_STD) || defined(BCMLXSDMMC)
5568
+#ifdef BCMSDIOH_STD
45245569 sd_txglom = 0;
4525
-#endif /* defined(BCMSDIOH_STD) || defined(BCMLXSDMMC) */
5570
+#endif /* BCMSDIOH_STD */
45265571 bus->txglom_enable = FALSE;
45275572 }
45285573 } else
....@@ -4538,13 +5583,27 @@
45385583 uint retries = 0;
45395584 uint8 ready, enable;
45405585 int err, ret = 0;
5586
+#ifdef BCMSPI
5587
+ uint32 dstatus = 0; /* gSPI device-status bits */
5588
+#else /* BCMSPI */
45415589 uint8 saveclk;
5590
+#endif /* BCMSPI */
45425591
45435592 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
45445593
45455594 ASSERT(bus->dhd);
45465595 if (!bus->dhd)
45475596 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
+ }
45485607
45495608 if (enforce_mutex)
45505609 dhd_os_sdlock(bus->dhd);
....@@ -4557,11 +5616,37 @@
45575616 goto exit;
45585617 }
45595618
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 */
45605643 /* Force clocks on backplane to be sure F2 interrupt propagates */
45615644 saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
45625645
45635646 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) {
45655650 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
45665651 (saveclk | SBSDIO_HT_AVAIL_REQ), &err);
45675652 } else {
....@@ -4590,25 +5675,33 @@
45905675 while (ready != enable && !dhd_timeout_expired(&tmo))
45915676 ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
45925677
5678
+#endif /* !BCMSPI */
5679
+
45935680 DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
45945681 __FUNCTION__, enable, ready, tmo.elapsed));
4595
-
45965682
45975683 /* If F2 successfully enabled, set core and enable interrupts */
45985684 if (ready == enable) {
45995685 /* 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
46005690 if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
46015691 bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
46025692 ASSERT(bus->regs != NULL);
4603
-
5693
+#endif // endif
46045694 /* Set up the interrupt mask and enable interrupts */
46055695 bus->hostintmask = HOSTINTMASK;
46065696 /* corerev 4 could use the newer interrupt logic to detect the frames */
5697
+#ifndef BCMSPI
46075698 if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
46085699 (bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
46095700 bus->hostintmask &= ~I_HMB_FRAME_IND;
46105701 bus->hostintmask |= I_XMTDATA_AVAIL;
46115702 }
5703
+#endif /* BCMSPI */
5704
+ /* Tell the device which interrupts are of our interest */
46125705 W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
46135706
46145707 if (bus->sih->buscorerev < 15) {
....@@ -4631,7 +5724,9 @@
46315724 bus->intdis = FALSE;
46325725 if (bus->intr) {
46335726 DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
5727
+#ifndef BCMSPI_ANDROID
46345728 bcmsdh_intr_enable(bus->sdh);
5729
+#endif /* !BCMSPI_ANDROID */
46355730 } else {
46365731 DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
46375732 bcmsdh_intr_disable(bus->sdh);
....@@ -4639,12 +5734,20 @@
46395734
46405735 }
46415736
5737
+#ifndef BCMSPI
46425738
46435739 else {
46445740 /* Disable F2 again */
46455741 enable = SDIO_FUNC_ENABLE_1;
46465742 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
46475743 }
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 */
46485751
46495752 if (dhdsdio_sr_cap(bus)) {
46505753 dhdsdio_sr_init(bus);
....@@ -4653,10 +5756,22 @@
46535756 W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
46545757 DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
46555758 __FUNCTION__, bus->hostintmask));
4656
- }
4657
- else
5759
+ } else {
46585760 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
46595761 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 */
46605775
46615776 /* If we didn't come up, turn off backplane clock */
46625777 if (dhdp->busstate != DHD_BUS_DATA)
....@@ -4739,8 +5854,10 @@
47395854
47405855 fail:
47415856 /* 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__));
47435859 bus->dhd->busstate = DHD_BUS_DOWN;
5860
+ }
47445861 }
47455862
47465863 static void
....@@ -4811,7 +5928,6 @@
48115928 goto done;
48125929 }
48135930
4814
-
48155931 /* Read remainder of frame body into the rxctl buffer */
48165932 sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
48175933 (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
....@@ -4832,7 +5948,7 @@
48325948 if (DHD_BYTES_ON() && DHD_CTL_ON()) {
48335949 prhex("RxCtrl", bus->rxctl, len);
48345950 }
4835
-#endif
5951
+#endif // endif
48365952
48375953 /* Point to valid data and indicate its length */
48385954 bus->rxctl += doff;
....@@ -4994,6 +6110,7 @@
49946110 errcode = -1;
49956111 }
49966112 pnext = NULL;
6113
+ BCM_REFERENCE(pnext);
49976114 } else {
49986115 DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
49996116 errcode = -1;
....@@ -5026,8 +6143,7 @@
50266143 prhex("SUPERFRAME", PKTDATA(osh, pfirst),
50276144 MIN(PKTLEN(osh, pfirst), 48));
50286145 }
5029
-#endif
5030
-
6146
+#endif // endif
50316147
50326148 /* Validate the superframe header */
50336149 dptr = (uint8 *)PKTDATA(osh, pfirst);
....@@ -5102,7 +6218,7 @@
51026218 if (DHD_GLOM_ON()) {
51036219 prhex("subframe", dptr, 32);
51046220 }
5105
-#endif
6221
+#endif // endif
51066222
51076223 if ((uint16)~(sublen^check)) {
51086224 DHD_ERROR(("%s (subframe %d): HW hdr error: "
....@@ -5177,7 +6293,7 @@
51776293 if (DHD_BYTES_ON() && DHD_DATA_ON()) {
51786294 prhex("Rx Subframe Data", dptr, dlen);
51796295 }
5180
-#endif
6296
+#endif // endif
51816297
51826298 PKTSETLEN(osh, pfirst, sublen);
51836299 PKTPULL(osh, pfirst, doff);
....@@ -5205,8 +6321,7 @@
52056321
52066322 if (free_buf_count == 0) {
52076323 continue;
5208
- }
5209
- else {
6324
+ } else {
52106325 void *temp;
52116326
52126327 /* go to the end of the chain and attach the pnext there */
....@@ -5223,14 +6338,12 @@
52236338 }
52246339
52256340 num += (uint8)free_buf_count;
5226
- }
5227
- else {
6341
+ } else {
52286342 /* this packet will go up, link back into chain and count it */
52296343
52306344 if (list_tail[ifidx] == NULL) {
52316345 list_head[ifidx] = list_tail[ifidx] = pfirst;
5232
- }
5233
- else {
6346
+ } else {
52346347 PKTSETNEXT(osh, list_tail[ifidx], pfirst);
52356348 list_tail[ifidx] = pfirst;
52366349 }
....@@ -5262,9 +6375,6 @@
52626375 dhd_os_sdunlock(bus->dhd);
52636376 dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
52646377 dhd_os_sdlock(bus->dhd);
5265
-#if defined(SDIO_ISR_THREAD)
5266
- BUS_WAKE(bus);
5267
-#endif
52686378 }
52696379 }
52706380 }
....@@ -5273,7 +6383,6 @@
52736383 }
52746384 return num;
52756385 }
5276
-
52776386
52786387 /* Return TRUE if there may be more frames to read */
52796388 static uint
....@@ -5294,6 +6403,9 @@
52946403 uint rxleft = 0; /* Remaining number of frames allowed */
52956404 int sdret; /* Return code from bcmsdh calls */
52966405 uint8 txmax; /* Maximum tx sequence offered */
6406
+#ifdef BCMSPI
6407
+ uint32 dstatus = 0; /* gSPI device status bits of */
6408
+#endif /* BCMSPI */
52976409 bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
52986410 uint8 *rxbuf;
52996411 int ifidx = 0;
....@@ -5304,10 +6416,9 @@
53046416
53056417 #if defined(DHD_DEBUG) || defined(SDTEST)
53066418 bool sdtest = FALSE; /* To limit message spew from test mode */
5307
-#endif
6419
+#endif // endif
53086420
53096421 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5310
-
53116422 bus->readframes = TRUE;
53126423
53136424 if (!KSO_ENAB(bus)) {
....@@ -5324,11 +6435,43 @@
53246435 maxframes = bus->pktgen_count;
53256436 sdtest = TRUE;
53266437 }
5327
-#endif
6438
+#endif // endif
53286439
53296440 /* Not finished unless we encounter no more frames indication */
53306441 *finished = FALSE;
53316442
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 */
53326475
53336476 for (rxseq = bus->rx_seq, rxleft = maxframes;
53346477 !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
....@@ -5360,7 +6503,7 @@
53606503 */
53616504 bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
53626505 FALSE : TRUE;
5363
-#endif
6506
+#endif // endif
53646507 }
53656508
53666509 /* Handle glomming separately */
....@@ -5382,8 +6525,7 @@
53826525
53836526 if (bus->bus == SPI_BUS) {
53846527 rdlen = len = nextlen;
5385
- }
5386
- else {
6528
+ } else {
53876529 rdlen = len = nextlen << 4;
53886530
53896531 /* Pad read to blocksize for efficiency */
....@@ -5426,6 +6568,20 @@
54266568 bus->f2rxdata++;
54276569 ASSERT(sdret != BCME_PENDING);
54286570
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 */
54296585
54306586 /* Control frame failures need retransmission */
54316587 if (sdret < 0) {
....@@ -5461,6 +6617,19 @@
54616617 pkt, NULL, NULL);
54626618 bus->f2rxdata++;
54636619 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 */
54646633
54656634 if (sdret < 0) {
54666635 DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
....@@ -5522,6 +6691,16 @@
55226691 }
55236692
55246693 /* 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 */
55256704 len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
55266705 if (len_consistent) {
55276706 /* Mismatch, force retry w/normal header (may be >4K) */
....@@ -5536,13 +6715,35 @@
55366715 continue;
55376716 }
55386717
5539
-
55406718 /* Extract software header fields */
55416719 chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
55426720 seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
55436721 doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
55446722 txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
55456723
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 */
55466747 bus->nextlen =
55476748 bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
55486749 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
....@@ -5553,6 +6754,9 @@
55536754 }
55546755
55556756 bus->dhd->rx_readahead_cnt ++;
6757
+#ifdef BCMSPI
6758
+ }
6759
+#endif /* BCMSPI */
55566760 /* Handle Flow Control */
55576761 fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
55586762
....@@ -5581,9 +6785,19 @@
55816785
55826786 /* Check window for sanity */
55836787 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 */
55846795 DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
55856796 __FUNCTION__, txmax, bus->tx_seq));
55866797 txmax = bus->tx_max;
6798
+#ifdef BCMSPI
6799
+ }
6800
+#endif /* BCMSPI */
55876801 }
55886802 bus->tx_max = txmax;
55896803
....@@ -5593,7 +6807,7 @@
55936807 } else if (DHD_HDRS_ON()) {
55946808 prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
55956809 }
5596
-#endif
6810
+#endif // endif
55976811
55986812 if (chan == SDPCM_CONTROL_CHANNEL) {
55996813 if (bus->bus == SPI_BUS) {
....@@ -5660,7 +6874,7 @@
56606874 if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
56616875 prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
56626876 }
5663
-#endif
6877
+#endif // endif
56646878
56656879 /* Extract hardware header fields */
56666880 len = ltoh16_ua(bus->rxhdr);
....@@ -5823,7 +7037,7 @@
58237037 if (DHD_BYTES_ON() && DHD_DATA_ON()) {
58247038 prhex("Rx Data", PKTDATA(osh, pkt), len);
58257039 }
5826
-#endif
7040
+#endif // endif
58277041
58287042 deliver:
58297043 /* Save superframe descriptor and allocate packet frame */
....@@ -5835,7 +7049,7 @@
58357049 if (DHD_GLOM_ON()) {
58367050 prhex("Glom Data", PKTDATA(osh, pkt), len);
58377051 }
5838
-#endif
7052
+#endif // endif
58397053 PKTSETLEN(osh, pkt, len);
58407054 ASSERT(doff == SDPCM_HDRLEN);
58417055 PKTPULL(osh, pkt, SDPCM_HDRLEN);
....@@ -5859,7 +7073,11 @@
58597073 }
58607074 #endif /* SDTEST */
58617075
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 */
58637081 dhd_os_sdlock_rxq(bus->dhd);
58647082 PKTFREE(bus->dhd->osh, pkt, FALSE);
58657083 dhd_os_sdunlock_rxq(bus->dhd);
....@@ -5873,23 +7091,21 @@
58737091 bus->dhd->rx_errors++;
58747092 continue;
58757093 }
7094
+
58767095 if (reorder_info_len) {
58777096 /* Reordering info from the firmware */
58787097 dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
58797098 &pkt, &pkt_count);
58807099 if (pkt_count == 0)
58817100 continue;
5882
- }
5883
- else
7101
+ } else {
58847102 pkt_count = 1;
7103
+ }
58857104
58867105 /* Unlock during rx call */
58877106 dhd_os_sdunlock(bus->dhd);
58887107 dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
58897108 dhd_os_sdlock(bus->dhd);
5890
-#if defined(SDIO_ISR_THREAD)
5891
- BUS_WAKE(bus);
5892
-#endif
58937109 }
58947110 rxcount = maxframes - rxleft;
58957111 #ifdef DHD_DEBUG
....@@ -5951,6 +7167,7 @@
59517167 bus->sdpcm_ver, SDPCM_PROT_VERSION));
59527168 else
59537169 DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
7170
+#ifndef BCMSPI
59547171 /* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
59557172 if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
59567173 (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) {
....@@ -5963,6 +7180,7 @@
59637180
59647181 val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
59657182 }
7183
+#endif /* BCMSPI */
59667184
59677185 #ifdef DHD_DEBUG
59687186 /* Retrieve console state address now that firmware should have updated it */
....@@ -5970,7 +7188,7 @@
59707188 sdpcm_shared_t shared;
59717189 if (dhdsdio_readshared(bus, &shared) == 0)
59727190 bus->console_addr = shared.console_addr;
5973
- }
7191
+ }
59747192 #endif /* DHD_DEBUG */
59757193 }
59767194
....@@ -5995,7 +7213,7 @@
59957213 if (hmb_data & HMB_DATA_FWHALT) {
59967214 DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"));
59977215 dhdsdio_checkdied(bus, NULL, 0);
5998
- bus->dhd->busstate = DHD_BUS_DOWN;
7216
+ DHD_ERROR(("Not doing bus down untill memdump done \n"));
59997217 }
60007218
60017219 /* Shouldn't be any others */
....@@ -6016,60 +7234,6 @@
60167234 return intstatus;
60177235 }
60187236
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
-
60737237 static bool
60747238 dhdsdio_dpc(dhd_bus_t *bus)
60757239 {
....@@ -6083,23 +7247,23 @@
60837247 bool rxdone = TRUE; /* Flag for no more read data */
60847248 bool resched = FALSE; /* Flag indicating resched wanted */
60857249 unsigned long flags;
7250
+#ifdef DEBUG_DPC_THREAD_WATCHDOG
7251
+ bool is_resched_by_readframe = FALSE;
7252
+#endif /* DEBUG_DPC_THREAD_WATCHDOG */
60867253 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
60877254
6088
- if (in_irq())
6089
- return TRUE;
6090
-
60917255 dhd_os_sdlock(bus->dhd);
6092
- DHD_GENERAL_LOCK(bus->dhd, flags);
7256
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
60937257 if (bus->dhd->busstate == DHD_BUS_DOWN) {
60947258 DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
60957259 bus->intstatus = 0;
6096
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
7260
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
60977261 dhd_os_sdunlock(bus->dhd);
60987262 return 0;
60997263 }
61007264
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);
61037267
61047268 /* Start with leftover status bits */
61057269 intstatus = bus->intstatus;
....@@ -6119,6 +7283,7 @@
61197283 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
61207284 if (err) {
61217285 DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
7286
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
61227287 bus->dhd->busstate = DHD_BUS_DOWN;
61237288 } else {
61247289 ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
....@@ -6129,6 +7294,7 @@
61297294 clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
61307295 if (err) {
61317296 DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
7297
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
61327298 bus->dhd->busstate = DHD_BUS_DOWN;
61337299 }
61347300
....@@ -6139,6 +7305,7 @@
61397305 if (err) {
61407306 DHD_ERROR(("%s: error reading DEVCTL: %d\n",
61417307 __FUNCTION__, err));
7308
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
61427309 bus->dhd->busstate = DHD_BUS_DOWN;
61437310 }
61447311 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
....@@ -6146,6 +7313,7 @@
61467313 if (err) {
61477314 DHD_ERROR(("%s: error writing DEVCTL: %d\n",
61487315 __FUNCTION__, err));
7316
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
61497317 bus->dhd->busstate = DHD_BUS_DOWN;
61507318 }
61517319 bus->clkstate = CLK_AVAIL;
....@@ -6164,6 +7332,10 @@
61647332 /* Pending interrupt indicates new device status */
61657333 if (bus->ipend) {
61667334 bus->ipend = FALSE;
7335
+#if defined(BT_OVER_SDIO)
7336
+ bcmsdh_btsdio_process_f3_intr();
7337
+#endif /* defined (BT_OVER_SDIO) */
7338
+
61677339 R_SDREG(newstatus, &regs->intstatus, retries);
61687340 bus->f1regdata++;
61697341 if (bcmsdh_regfail(bus->sdh))
....@@ -6172,10 +7344,11 @@
61727344 bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
61737345 if (newstatus) {
61747346 bus->f1regdata++;
7347
+#ifndef BCMSPI
61757348 if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
61767349 (newstatus == I_XMTDATA_AVAIL)) {
6177
- }
6178
- else
7350
+ } else
7351
+#endif /* BCMSPI */
61797352 W_SDREG(newstatus, &regs->intstatus, retries);
61807353 }
61817354 }
....@@ -6200,23 +7373,30 @@
62007373 /* Handle host mailbox indication */
62017374 if (intstatus & I_HMB_HOST_INT) {
62027375 uint32 hmbdata = 0;
7376
+
62037377 intstatus &= ~I_HMB_HOST_INT;
62047378 intstatus |= dhdsdio_hostmail(bus, &hmbdata);
6205
- /* ULP prototyping. Redowload fw on oob interupt */
7379
+
62067380 #ifdef DHD_ULP
7381
+ /* ULP prototyping. Redowload fw on oob interupt */
7382
+
62077383 /* all the writes after this point CAN use cached sbwad value */
62087384 bcmsdh_force_sbwad_calc(bus->sdh, FALSE);
62097385
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)) {
62117387 if (dhd_bus_ulp_reinit_fw(bus) < 0) {
62127388 DHD_ERROR(("%s:%d FW redownload failed\n",
62137389 __FUNCTION__, __LINE__));
62147390 goto exit;
62157391 }
62167392 }
6217
-#endif
7393
+#endif // endif
62187394
62197395 }
7396
+
7397
+#ifdef DHD_UCODE_DOWNLOAD
7398
+exit_ucode:
7399
+#endif /* DHD_UCODE_DOWNLOAD */
62207400
62217401 /* Just being here means nothing more to do for chipactive */
62227402 if (intstatus & I_CHIPACTIVE) {
....@@ -6287,6 +7467,10 @@
62877467 bcmsdh_oob_intr_set(bus->sdh, TRUE);
62887468 #endif /* defined(OOB_INTR_ONLY) */
62897469 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 */
62907474 }
62917475
62927476 #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
....@@ -6307,7 +7491,7 @@
63077491
63087492 #ifdef PROP_TXSTATUS
63097493 dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
6310
-#endif
7494
+#endif // endif
63117495
63127496 if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
63137497 dhdsdio_sendpendctl(bus);
....@@ -6347,6 +7531,7 @@
63477531 } else {
63487532 DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
63497533 __FUNCTION__));
7534
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
63507535 bus->dhd->busstate = DHD_BUS_DOWN;
63517536 bus->intstatus = 0;
63527537 }
....@@ -6361,7 +7546,8 @@
63617546 bus->dpc_sched = resched;
63627547
63637548 /* 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)) {
63657551 bus->activity = FALSE;
63667552 dhdsdio_bussleep(bus, TRUE);
63677553 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -6372,15 +7558,29 @@
63727558 if (!resched && dhd_dpcpoll) {
63737559 if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
63747560 resched = TRUE;
7561
+#ifdef DEBUG_DPC_THREAD_WATCHDOG
7562
+ is_resched_by_readframe = TRUE;
7563
+#endif /* DEBUG_DPC_THREAD_WATCHDOG */
63757564 }
63767565 }
63777566
63787567 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));
63797575
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);
63827582 dhd_os_busbusy_wake(bus->dhd);
6383
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
7583
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
63847584
63857585 return resched;
63867586 }
....@@ -6395,6 +7595,66 @@
63957595 resched = dhdsdio_dpc(bus);
63967596
63977597 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
+
63987658 }
63997659
64007660 #ifdef SDTEST
....@@ -6535,7 +7795,7 @@
65357795 data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
65367796 prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
65377797 }
6538
-#endif
7798
+#endif // endif
65397799
65407800 /* Send it */
65417801 if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
....@@ -6586,7 +7846,6 @@
65867846 if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
65877847 bus->pktgen_fail++;
65887848 }
6589
-
65907849
65917850 static void
65927851 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
....@@ -6704,24 +7963,24 @@
67047963 {
67057964 int err = 0;
67067965
6707
-#if defined(OOB_INTR_ONLY)
7966
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
67087967 err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
6709
-#endif
7968
+#endif // endif
67107969 return err;
67117970 }
67127971
67137972 void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
67147973 {
6715
-#if defined(OOB_INTR_ONLY)
7974
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
67167975 bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
6717
-#endif
7976
+#endif // endif
67187977 }
67197978
67207979 void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
67217980 {
6722
-#if defined(OOB_INTR_ONLY)
7981
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
67237982 bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
6724
-#endif
7983
+#endif // endif
67257984 }
67267985
67277986 void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
....@@ -6764,14 +8023,14 @@
67648023 if (!SLPAUTO_ENAB(bus) && bus->sleeping)
67658024 return FALSE;
67668025
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);
67718030 return FALSE;
67728031 }
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);
67758034
67768035 dhd_os_sdlock(bus->dhd);
67778036
....@@ -6785,12 +8044,21 @@
67858044 /* Check device if no interrupts */
67868045 if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
67878046
8047
+#ifndef BCMSPI
67888048 if (!bus->dpc_sched) {
67898049 uint8 devpend;
67908050 devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
67918051 SDIOD_CCCR_INTPEND, NULL);
67928052 intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
67938053 }
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 */
67948062
67958063 /* If there is something, make like the ISR and schedule the DPC */
67968064 if (intstatus) {
....@@ -6810,17 +8078,17 @@
68108078
68118079 #ifdef DHD_DEBUG
68128080 /* 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) {
68148082 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;
68178085 /* Make sure backplane clock is on */
68188086 if (SLPAUTO_ENAB(bus))
68198087 dhdsdio_bussleep(bus, FALSE);
68208088 else
68218089 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 */
68248092 }
68258093 }
68268094 #endif /* DHD_DEBUG */
....@@ -6836,7 +8104,7 @@
68368104 bus->pktgen_tick = 0;
68378105 dhdsdio_pktgen(bus);
68388106 }
6839
-#endif
8107
+#endif // endif
68408108
68418109 /* On idle timeout clear activity flag and/or turn off clock */
68428110 #ifdef DHD_USE_IDLECOUNT
....@@ -6845,8 +8113,23 @@
68458113 else {
68468114 bus->idlecount++;
68478115
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)) {
68508133 DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
68518134 if (SLPAUTO_ENAB(bus)) {
68528135 if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
....@@ -6858,19 +8141,23 @@
68588141 }
68598142 }
68608143 #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)) {
68628146 if (++bus->idlecount >= bus->idletime) {
68638147 bus->idlecount = 0;
68648148 if (bus->activity) {
68658149 bus->activity = FALSE;
8150
+#if !defined(OEM_ANDROID)
8151
+ } else {
8152
+#endif // endif
68668153 if (SLPAUTO_ENAB(bus)) {
68678154 if (!bus->readframes)
68688155 dhdsdio_bussleep(bus, TRUE);
68698156 else
68708157 bus->reqbussleep = TRUE;
6871
- }
6872
- else
8158
+ } else {
68738159 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8160
+ }
68748161 }
68758162 }
68768163 }
....@@ -6878,14 +8165,14 @@
68788165
68798166 dhd_os_sdunlock(bus->dhd);
68808167
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);
68848172
68858173 return bus->ipend;
68868174 }
68878175
6888
-#ifdef DHD_DEBUG
68898176 extern int
68908177 dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
68918178 {
....@@ -6936,7 +8223,8 @@
69368223 rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
69378224
69388225 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)) {
69408228 bus->activity = FALSE;
69418229 dhdsdio_bussleep(bus, TRUE);
69428230 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -6946,9 +8234,8 @@
69468234
69478235 return rv;
69488236 }
6949
-#endif /* DHD_DEBUG */
69508237
6951
-#ifdef DHD_DEBUG
8238
+#if defined(DHD_DEBUG) && !defined(BCMSDIOLITE) && !defined(BCMSPI)
69528239 static void
69538240 dhd_dump_cis(uint fn, uint8 *cis)
69548241 {
....@@ -6981,53 +8268,15 @@
69818268 static bool
69828269 dhdsdio_chipmatch(uint16 chipid)
69838270 {
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;
70188271 if (chipid == BCM4335_CHIP_ID)
70198272 return TRUE;
70208273 if (chipid == BCM4339_CHIP_ID)
70218274 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))
70258276 return TRUE;
70268277 if (chipid == BCM4350_CHIP_ID)
70278278 return TRUE;
70288279 if (chipid == BCM4354_CHIP_ID)
7029
- return TRUE;
7030
- if (chipid == BCM4356_CHIP_ID)
70318280 return TRUE;
70328281 if (chipid == BCM4358_CHIP_ID)
70338282 return TRUE;
....@@ -7037,84 +8286,34 @@
70378286 return TRUE;
70388287 if (BCM4349_CHIP(chipid))
70398288 return TRUE;
8289
+ if (chipid == BCM4373_CHIP_ID)
8290
+ return TRUE;
8291
+ if (chipid == BCM4364_CHIP_ID)
8292
+ return TRUE;
8293
+
70408294 if (chipid == BCM43012_CHIP_ID)
70418295 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)
70438314 return TRUE;
70448315 return FALSE;
70458316 }
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 */
71188317
71198318 static void *
71208319 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
....@@ -7122,10 +8321,15 @@
71228321 {
71238322 int ret;
71248323 dhd_bus_t *bus;
7125
-#ifdef GET_OTP_MAC_ENABLE
7126
- struct ether_addr ea_addr;
7127
-#endif
71288324
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
71298333
71308334 /* Init global variables at run-time, not as part of the declaration.
71318335 * This is required to support init/de-init of the driver. Initialization
....@@ -7135,22 +8339,32 @@
71358339 */
71368340 dhd_txbound = DHD_TXBOUND;
71378341 dhd_rxbound = DHD_RXBOUND;
8342
+#ifdef BCMSPI
8343
+ dhd_alignctl = FALSE;
8344
+#else
71388345 dhd_alignctl = TRUE;
8346
+#endif /* BCMSPI */
71398347 sd1idle = TRUE;
71408348 dhd_readahead = TRUE;
71418349 retrydata = FALSE;
71428350
8351
+#ifdef DISABLE_FLOW_CONTROL
71438352 dhd_doflow = FALSE;
8353
+#endif /* DISABLE_FLOW_CONTROL */
71448354 dhd_dongle_ramsize = 0;
71458355 dhd_txminmax = DHD_TXMINMAX;
71468356
8357
+#ifdef BCMSPI
8358
+ forcealign = FALSE;
8359
+#else
71478360 forcealign = TRUE;
8361
+#endif /* !BCMSPI */
71488362
71498363 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
71508364 DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
71518365
71528366 /* We make assumptions about address window mappings */
7153
- ASSERT((uintptr)regsva == SI_ENUM_BASE);
8367
+ ASSERT((uintptr)regsva == si_enum_base(devid));
71548368
71558369 /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
71568370 * means early parse could fail, so here we should get either an ID
....@@ -7169,27 +8383,6 @@
71698383
71708384 /* Check the Device ID and make sure it's one that we support */
71718385 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;
71938386 case 0:
71948387 DHD_INFO(("%s: allow device id 0, will check chip internals\n",
71958388 __FUNCTION__));
....@@ -7202,8 +8395,16 @@
72028395 }
72038396
72048397 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
72058405 DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
72068406 goto forcereturn;
8407
+#endif /* BCMSPI && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI)) */
72078408 }
72088409
72098410 /* Allocate private bus interface state */
....@@ -7219,8 +8420,11 @@
72198420 bus->slot_num = slot;
72208421 bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
72218422 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
72228426
7223
-#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16)
8427
+#if defined(SUPPORT_P2P_GO_PS)
72248428 init_waitqueue_head(&bus->bus_sleep);
72258429 #endif /* LINUX && SUPPORT_P2P_GO_PS */
72268430
....@@ -7269,24 +8473,47 @@
72698473 if (dhd_download_fw_on_driverload) {
72708474 if ((ret = dhd_bus_start(bus->dhd)) != 0) {
72718475 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) */
72728479 goto fail;
72738480 }
72748481 }
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 */
72828500
72838501 /* 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
+ {
72858504 DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
72868505 goto fail;
72878506 }
72888507
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 */
72898512
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
72908517
72918518 return bus;
72928519
....@@ -7294,6 +8521,10 @@
72948521 dhdsdio_release(bus, osh);
72958522
72968523 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
72978528
72988529 return NULL;
72998530 }
....@@ -7302,87 +8533,220 @@
73028533 dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
73038534 uint16 devid)
73048535 {
7305
- int err = 0;
8536
+#ifdef BCMSPI
8537
+ uint32 spidreg = 0;
8538
+#else
73068539 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};
73078548
8549
+ BCM_REFERENCE(value);
73088550 bus->alp_only = TRUE;
73098551 bus->sih = NULL;
73108552
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
+
73118590 /* 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))) {
73138592 DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
73148593 }
73158594
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 */
73208604
8605
+#ifndef BCMSPI /* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
73218606
73228607 /* Force PLL off until si_attach() programs PLL control regs */
73238608
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);
73248612
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;
73398617 }
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
+ }
73408730
73418731 #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()) {
73728733 dhd_dump_cis(fn, cis[fn]);
73738734 }
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
- }
73858735 #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
+ }
73868750
73878751 /* si_attach() will provide an SI handle and scan the backplane */
73888752 if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
....@@ -7395,12 +8759,6 @@
73958759 DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
73968760 bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
73978761 #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
-
74048762
74058763 bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
74068764
....@@ -7415,11 +8773,7 @@
74158773 else
74168774 bus->kso = TRUE;
74178775
7418
- if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) {
7419
- }
7420
-
74218776 si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
7422
-
74238777
74248778 /* Get info on the ARM and SOCRAM cores... */
74258779 if (!DHD_NOPMU(bus)) {
....@@ -7447,32 +8801,29 @@
74478801 switch ((uint16)bus->sih->chip) {
74488802 case BCM4335_CHIP_ID:
74498803 case BCM4339_CHIP_ID:
7450
- case BCM43349_CHIP_ID:
74518804 bus->dongle_ram_base = CR4_4335_RAM_BASE;
74528805 break;
74538806 case BCM4350_CHIP_ID:
74548807 case BCM4354_CHIP_ID:
7455
- case BCM4356_CHIP_ID:
74568808 case BCM4358_CHIP_ID:
74578809 bus->dongle_ram_base = CR4_4350_RAM_BASE;
74588810 break;
74598811 case BCM4360_CHIP_ID:
74608812 bus->dongle_ram_base = CR4_4360_RAM_BASE;
74618813 break;
7462
- case BCM4345_CHIP_ID:
7463
- case BCM43454_CHIP_ID:
8814
+ CASE_BCM4345_CHIP:
74648815 bus->dongle_ram_base = (bus->sih->chiprev < 6) /* from 4345C0 */
74658816 ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
74668817 break;
74678818 case BCM4349_CHIP_GRPID:
7468
- /* RAM base changed from 4349c0(revid=9) onwards */
8819
+ /* RAM based changed from 4349c0(revid=9) onwards */
74698820 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);
74718822 break;
74728823 case BCM4373_CHIP_ID:
74738824 bus->dongle_ram_base = CR4_4373_RAM_BASE;
74748825 /* 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
74768827 */
74778828 {
74788829 uint fn = 2;
....@@ -7480,17 +8831,49 @@
74808831 if (bcmsdh_iovar_op(sdh, "sd_blocksize",
74818832 NULL, 0, &fn, sizeof(fn), TRUE) != BCME_OK) {
74828833 DHD_ERROR(("%s: Set F2 Block size error\n",
7483
- __FUNCTION__));
8834
+ __FUNCTION__));
74848835 goto fail;
74858836 }
74868837 }
74878838 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 */
74888862 default:
74898863 bus->dongle_ram_base = 0;
74908864 DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
74918865 __FUNCTION__, bus->dongle_ram_base));
74928866 }
74938867 }
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
+
74948877 bus->ramsize = bus->orig_ramsize;
74958878 if (dhd_dongle_ramsize)
74968879 dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
....@@ -7502,15 +8885,23 @@
75028885 }
75038886
75048887 /* ...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
75058894 if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
75068895 !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
75078896 DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
75088897 goto fail;
75098898 }
8899
+#endif // endif
75108900 bus->sdpcmrev = si_corerev(bus->sih);
75118901
75128902 /* Set core control so an SDIO reset does a backplane reset */
75138903 OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
8904
+#ifndef BCMSPI
75148905 bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
75158906
75168907 if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
....@@ -7523,7 +8914,7 @@
75238914 val |= CC_XMTDATAAVAIL_CTRL;
75248915 W_REG(osh, &bus->regs->corecontrol, val);
75258916 }
7526
-
8917
+#endif /* BCMSPI */
75278918
75288919 pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
75298920
....@@ -7571,21 +8962,6 @@
75718962 goto fail;
75728963 }
75738964
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
-
75898965 /* Align the buffer */
75908966 if ((uintptr)bus->databuf % DHD_SDALIGN)
75918967 bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
....@@ -7611,23 +8987,21 @@
76118987 dhdsdio_pktgen_init(bus);
76128988 #endif /* SDTEST */
76138989
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 */
76238994
8995
+ DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
76248996 bus->dhd->busstate = DHD_BUS_DOWN;
76258997 bus->sleeping = FALSE;
76268998 bus->rxflow = FALSE;
76278999 bus->prev_rxlim_hit = 0;
76289000
9001
+#ifndef BCMSPI
76299002 /* Done with backplane-dependent accesses, can drop clock... */
76309003 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
9004
+#endif /* !BCMSPI */
76319005
76329006 /* ...and initialize clock/power states */
76339007 bus->clkstate = CLK_SDONLY;
....@@ -7659,10 +9033,10 @@
76599033 if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
76609034 &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
76619035 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"));
76639037 } 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));
76669040
76679041 dhdsdio_tune_fifoparam(bus);
76689042 }
....@@ -7710,6 +9084,15 @@
77109084
77119085 ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
77129086
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) */
77139096
77149097 return ret;
77159098 }
....@@ -7719,6 +9102,17 @@
77199102 {
77209103 int ret;
77219104
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 */
77229116
77239117 DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
77249118 __FUNCTION__, bus->fw_path, bus->nv_path));
....@@ -7727,16 +9121,7 @@
77279121 /* Download the firmware */
77289122 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
77299123
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);
77409125
77419126 dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
77429127
....@@ -7755,6 +9140,9 @@
77559140 ASSERT(osh);
77569141
77579142 if (bus->dhd) {
9143
+#if defined(DEBUGGER) || defined(DHD_DSCOPE)
9144
+ debugger_close();
9145
+#endif /* DEBUGGER || DHD_DSCOPE */
77589146 dongle_isolation = bus->dhd->dongle_isolation;
77599147 dhd_detach(bus->dhd);
77609148 }
....@@ -7774,7 +9162,7 @@
77749162 #ifdef DHD_DEBUG
77759163 if (bus->console.buf != NULL)
77769164 MFREE(osh, bus->console.buf, bus->console.bufsize);
7777
-#endif
9165
+#endif // endif
77789166
77799167 #ifdef DHDENABLE_TAILPAD
77809168 if (bus->pad_pkt)
....@@ -7798,7 +9186,7 @@
77989186 if (bus->rxbuf) {
77999187 #ifndef CONFIG_DHD_USE_STATIC_BUF
78009188 MFREE(osh, bus->rxbuf, bus->rxblen);
7801
-#endif
9189
+#endif // endif
78029190 bus->rxctl = bus->rxbuf = NULL;
78039191 bus->rxlen = 0;
78049192 }
....@@ -7806,13 +9194,8 @@
78069194 if (bus->databuf) {
78079195 #ifndef CONFIG_DHD_USE_STATIC_BUF
78089196 MFREE(osh, bus->databuf, MAX_DATA_BUF);
7809
-#endif
9197
+#endif // endif
78109198 bus->databuf = NULL;
7811
- }
7812
-
7813
- if (bus->membuf) {
7814
- MFREE(osh, bus->membuf, MAX_DATA_BUF);
7815
- bus->membuf = NULL;
78169199 }
78179200
78189201 if (bus->vars && bus->varsz) {
....@@ -7822,10 +9205,13 @@
78229205
78239206 }
78249207
7825
-
78269208 static void
78279209 dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
78289210 {
9211
+#if !defined(BCMLXSDMMC)
9212
+ int32 bcmerror = BCME_ERROR;
9213
+#endif // endif
9214
+
78299215 DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
78309216 bus->dhd, bus->dhd->dongle_reset));
78319217
....@@ -7833,12 +9219,53 @@
78339219 return;
78349220
78359221 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. */
78369224 #if !defined(BCMLXSDMMC)
78379225 if (bus->dhd) {
78389226 dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
78399227 }
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
+ }
78429269 #endif /* !defined(BCMLXSDMMC) */
78439270 if (bus->dhd) {
78449271 dhdsdio_clkctl(bus, CLK_NONE, FALSE);
....@@ -7860,14 +9287,26 @@
78609287
78619288 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
78629289
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
78649298
78659299 if (bus) {
78669300 ASSERT(bus->dhd);
9301
+ /* Advertise bus cleanup during rmmod */
9302
+ dhdsdio_advertise_bus_cleanup(bus->dhd);
78679303 dhdsdio_release(bus, bus->dhd->osh);
78689304 }
78699305
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 */
78719310
78729311 DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
78739312 }
....@@ -7876,13 +9315,14 @@
78769315 dhdsdio_suspend(void *context)
78779316 {
78789317 int ret = 0;
7879
-#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16)
9318
+#ifdef SUPPORT_P2P_GO_PS
78809319 int wait_time = 0;
78819320 #endif /* SUPPORT_P2P_GO_PS */
78829321
78839322 dhd_bus_t *bus = (dhd_bus_t*)context;
78849323 unsigned long flags;
78859324
9325
+ DHD_ERROR(("%s Enter\n", __FUNCTION__));
78869326 if (bus->dhd == NULL) {
78879327 DHD_ERROR(("bus not inited\n"));
78889328 return BCME_ERROR;
....@@ -7891,59 +9331,63 @@
78919331 DHD_ERROR(("prot is not inited\n"));
78929332 return BCME_ERROR;
78939333 }
7894
- //added by May 20190628
9334
+
78959335 if (bus->dhd->up == FALSE) {
78969336 return BCME_OK;
78979337 }
7898
- DHD_GENERAL_LOCK(bus->dhd, flags);
9338
+
9339
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
78999340 if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
79009341 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);
79029343 return BCME_ERROR;
79039344 }
7904
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
9345
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
79059346 if (bus->dhd->dongle_reset) {
79069347 DHD_ERROR(("Dongle is in reset state.\n"));
79079348 return -EIO;
79089349 }
79099350
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);
79119354 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)) {
79139356 DHD_ERROR(("Tx Request is not ended\n"));
79149357 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);
79169361 return -EBUSY;
79179362 }
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);
79209365
7921
-#if defined(SUPPORT_P2P_GO_PS) || defined(SUSPEND16)
9366
+#ifdef SUPPORT_P2P_GO_PS
79229367 if (bus->idletime > 0) {
79239368 wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
79249369 }
79259370 #endif /* SUPPORT_P2P_GO_PS */
79269371 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)) {
79299374 if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
79309375 if (!bus->sleeping) {
7931
- bus->dhd->busstate = DHD_BUS_DATA;
7932
- return 1;
9376
+ ret = 1;
79339377 }
79349378 }
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;
79409379 }
79419380 #endif /* SUPPORT_P2P_GO_PS */
79429381
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);
79459389 dhd_os_busbusy_wake(bus->dhd);
7946
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
9390
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
79479391 return ret;
79489392 }
79499393
....@@ -7951,24 +9395,33 @@
79519395 dhdsdio_resume(void *context)
79529396 {
79539397 dhd_bus_t *bus = (dhd_bus_t*)context;
7954
- unsigned long flags;
9398
+ ulong flags;
79559399
7956
- //added by May 20190628
9400
+ DHD_ERROR(("%s Enter\n", __FUNCTION__));
9401
+
79579402 if (bus->dhd->up == FALSE) {
79589403 return BCME_OK;
79599404 }
79609405
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);
79649409
7965
-#if defined(OOB_INTR_ONLY)
9410
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
79669411 if (dhd_os_check_if_up(bus->dhd))
79679412 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
+
79699423 return 0;
79709424 }
7971
-
79729425
79739426 /* Register/Unregister functions are called by the main DHD entry
79749427 * point (e.g. module insertion) to link with the bus driver, in
....@@ -8011,96 +9464,6 @@
80119464 }
80129465 #endif /* defined(BCMLXSDMMC) */
80139466
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
-
81049467 static int
81059468 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
81069469 {
....@@ -8110,21 +9473,24 @@
81109473 void *image = NULL;
81119474 uint8 *memblock = NULL, *memptr;
81129475 uint memblock_size = MEMBLOCK;
9476
+ struct trx_header *trx_hdr;
9477
+ bool trx_chk = TRUE;
81139478 #ifdef DHD_DEBUG_DOWNLOADTIME
81149479 unsigned long initial_jiffies = 0;
81159480 uint firmware_sz = 0;
8116
-#endif
9481
+#endif // endif
81179482
81189483 DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
81199484
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__));
81229488 goto err;
9489
+ }
81239490
81249491 /* Update the dongle image download block size depending on the F1 block size */
81259492 if (sd_f1_blocksize == 512)
81269493 memblock_size = MAX_MEMBLOCK;
8127
-
81289494 memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
81299495 if (memblock == NULL) {
81309496 DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
....@@ -8136,7 +9502,7 @@
81369502
81379503 #ifdef DHD_DEBUG_DOWNLOADTIME
81389504 initial_jiffies = jiffies;
8139
-#endif
9505
+#endif // endif
81409506
81419507 /* Download image */
81429508 while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
....@@ -8156,6 +9522,16 @@
81569522 }
81579523 }
81589524
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
+
81599535 bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
81609536 if (bcmerror) {
81619537 DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
....@@ -8166,24 +9542,148 @@
81669542 offset += memblock_size;
81679543 #ifdef DHD_DEBUG_DOWNLOADTIME
81689544 firmware_sz += len;
8169
-#endif
9545
+#endif // endif
81709546 }
81719547
81729548 #ifdef DHD_DEBUG_DOWNLOADTIME
81739549 DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
81749550 firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
8175
-#endif
9551
+#endif // endif
81769552
81779553 err:
81789554 if (memblock)
81799555 MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
81809556
81819557 if (image)
8182
- dhd_os_close_image(image);
9558
+ dhd_os_close_image1(bus->dhd, image);
81839559
81849560 return bcmerror;
81859561 }
81869562
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 */
81879687
81889688 static int
81899689 dhdsdio_download_nvram(struct dhd_bus *bus)
....@@ -8202,7 +9702,7 @@
82029702
82039703 /* For Get nvram from UEFI */
82049704 if (nvram_file_exists)
8205
- image = dhd_os_open_image(pnv_path);
9705
+ image = dhd_os_open_image1(bus->dhd, pnv_path);
82069706
82079707 memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
82089708 if (memblock == NULL) {
....@@ -8229,8 +9729,7 @@
82299729 DHD_ERROR(("%s: error downloading vars: %d\n",
82309730 __FUNCTION__, bcmerror));
82319731 }
8232
- }
8233
- else {
9732
+ } else {
82349733 DHD_ERROR(("%s: error reading nvram file: %d\n",
82359734 __FUNCTION__, len));
82369735 bcmerror = BCME_SDIO_ERROR;
....@@ -8241,7 +9740,7 @@
82419740 MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
82429741
82439742 if (image)
8244
- dhd_os_close_image(image);
9743
+ dhd_os_close_image1(bus->dhd, image);
82459744
82469745 return bcmerror;
82479746 }
....@@ -8256,11 +9755,7 @@
82569755
82579756 /* Out immediately if no image to download */
82589757 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;
82649759 }
82659760
82669761 /* Keep arm in reset */
....@@ -8273,31 +9768,14 @@
82739768 if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
82749769 if (dhdsdio_download_code_file(bus, bus->fw_path)) {
82759770 DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
8276
-#ifdef BCMEMBEDIMAGE
8277
- embed = TRUE;
8278
-#else
82799771 goto err;
8280
-#endif
8281
- }
8282
- else {
9772
+ } else {
82839773 embed = FALSE;
82849774 dlok = TRUE;
82859775 }
82869776 }
82879777
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
82999778 BCM_REFERENCE(embed);
8300
-#endif
83019779 if (!dlok) {
83029780 DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
83039781 goto err;
....@@ -8323,7 +9801,7 @@
83239801
83249802 static int
83259803 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)
83279805 {
83289806 int status;
83299807
....@@ -8332,14 +9810,14 @@
83329810 return BCME_NODEVICE;
83339811 }
83349812
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);
83369814
83379815 return status;
83389816 }
83399817
83409818 static int
83419819 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)
83439821 {
83449822 int ret;
83459823 int i = 0;
....@@ -8353,8 +9831,11 @@
83539831
83549832 sdh = bus->sdh;
83559833 do {
9834
+ if (fn == 2)
9835
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_CHIP_CTRL_DATA, 0x80, NULL);
9836
+
83569837 ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
8357
- pkt, complete, handle);
9838
+ pkt, complete_fn, handle);
83589839
83599840 bus->f2txdata++;
83609841 ASSERT(ret != BCME_PENDING);
....@@ -8457,15 +9938,15 @@
84579938 unsigned long flags;
84589939 int timeleft;
84599940
8460
- DHD_GENERAL_LOCK(dhdp, flags);
9941
+ DHD_LINUX_GENERAL_LOCK(dhdp, flags);
84619942 dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
8462
- DHD_GENERAL_UNLOCK(dhdp, flags);
9943
+ DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
84639944
84649945 timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
8465
- if (timeleft == 0) {
9946
+ if ((timeleft == 0) || (timeleft == 1)) {
84669947 DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
84679948 __FUNCTION__, dhdp->dhd_bus_busy_state));
8468
- BUG_ON(1);
9949
+ ASSERT(0);
84699950 }
84709951
84719952 return;
....@@ -8486,56 +9967,62 @@
84869967 dhdsdio_advertise_bus_cleanup(bus->dhd);
84879968 dhd_os_sdlock(dhdp);
84889969 dhd_os_wd_timer(dhdp, 0);
9970
+#if defined(OEM_ANDROID)
84899971 #if !defined(IGNORE_ETH0_DOWN)
84909972 /* Force flow control as protection when stop come before ifconfig_down */
84919973 dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
84929974 #endif /* !defined(IGNORE_ETH0_DOWN) */
9975
+#endif /* OEM_ANDROID */
84939976 /* Expect app to have torn down any connection before calling */
84949977 /* Stop the bus, disable F2 */
84959978 dhd_bus_stop(bus, FALSE);
8496
-
8497
-#if defined(OOB_INTR_ONLY)
9979
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
84989980 /* Clean up any pending IRQ */
84999981 dhd_enable_oob_intr(bus, FALSE);
85009982 bcmsdh_oob_intr_set(bus->sdh, FALSE);
85019983 bcmsdh_oob_intr_unregister(bus->sdh);
8502
-#endif
9984
+#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
85039985
85049986 /* Clean tx/rx buffer pointers, detach from the dongle */
85059987 dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
85069988
85079989 bus->dhd->dongle_reset = TRUE;
9990
+ DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__));
85089991 bus->dhd->up = FALSE;
85099992 dhd_txglom_enable(dhdp, FALSE);
85109993 dhd_os_sdunlock(dhdp);
85119994
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__));
85139997 bus->dhd->busstate = DHD_BUS_DOWN;
8514
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
9998
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
85159999
8516
- DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__));
10000
+ DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__));
851710001 /* App can now remove power from device */
851810002 } else
851910003 bcmerror = BCME_SDIO_ERROR;
852010004 } else {
852110005 /* App must have restored power to device before calling */
852210006
8523
- DHD_ERROR(("\n\n%s: == WLAN ON ==\n", __FUNCTION__));
10007
+ DHD_ERROR(("\n\n%s: == Power ON ==\n", __FUNCTION__));
852410008
852510009 if (bus->dhd->dongle_reset) {
852610010 /* Turn on WLAN */
852710011 dhd_os_sdlock(dhdp);
8528
- /* Reset SD client */
10012
+ /* Reset SD client -- required if devreset is called
10013
+ * via 'dhd devreset' iovar
10014
+ */
852910015 bcmsdh_reset(bus->sdh);
8530
-
853110016 /* Attempt to re-attach & download */
853210017 if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
8533
- (uint32 *)SI_ENUM_BASE,
10018
+ (uint32 *)(uintptr)si_enum_base(bus->cl_devid),
853410019 bus->cl_devid)) {
853510020
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__));
853710023 bus->dhd->busstate = DHD_BUS_DOWN;
8538
- DHD_GENERAL_UNLOCK(bus->dhd, flags);
10024
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10025
+
853910026 /* Attempt to download binary to the dongle */
854010027 if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
854110028 dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
....@@ -8543,20 +10030,20 @@
854310030 /* Re-init bus, enable F2 transfer */
854410031 bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
854510032 if (bcmerror == BCME_OK) {
8546
-#if defined(OOB_INTR_ONLY)
10033
+#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
854710034 dhd_enable_oob_intr(bus, TRUE);
854810035 bcmsdh_oob_intr_register(bus->sdh,
854910036 dhdsdio_isr, bus);
855010037 bcmsdh_oob_intr_set(bus->sdh, TRUE);
8551
-#endif
10038
+#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
855210039
855310040 bus->dhd->dongle_reset = FALSE;
855410041 bus->dhd->up = TRUE;
855510042
8556
-#if !defined(IGNORE_ETH0_DOWN)
10043
+#if defined(OEM_ANDROID) && !defined(IGNORE_ETH0_DOWN)
855710044 /* Restore flow control */
855810045 dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
8559
-#endif
10046
+#endif /* defined(OEM_ANDROID) && (!defined(IGNORE_ETH0_DOWN)) */
856010047 dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
856110048
856210049 DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
....@@ -8578,16 +10065,17 @@
857810065 bcmerror = BCME_SDIO_ERROR;
857910066 }
858010067
8581
- dhd_os_sdunlock(dhdp);
10068
+ dhd_os_sdunlock(dhdp);
858210069 } else {
8583
- bcmerror = BCME_SDIO_ERROR;
858410070 DHD_INFO(("%s called when dongle is not in reset\n",
858510071 __FUNCTION__));
10072
+#if defined(OEM_ANDROID)
858610073 DHD_INFO(("Will call dhd_bus_start instead\n"));
858710074 dhd_bus_resume(dhdp, 1);
858810075 if ((bcmerror = dhd_bus_start(dhdp)) != 0)
858910076 DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
859010077 __FUNCTION__, bcmerror));
10078
+#endif /* defined(OEM_ANDROID) */
859110079 }
859210080 }
859310081 return bcmerror;
....@@ -8644,6 +10132,193 @@
864410132 return dhdsdio_membytes(bus, set, address, data, size);
864510133 }
864610134
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 */
864710322
864810323 void
864910324 dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path)
....@@ -8695,7 +10370,7 @@
869510370
869610371 #ifdef PROP_TXSTATUS
869710372 wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
8698
-#endif
10373
+#endif // endif
869910374 if (!wlfc_enabled) {
870010375 #ifdef DHDTCPACK_SUPPRESS
870110376 /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
....@@ -8704,7 +10379,7 @@
870410379 dhd_tcpack_info_tbl_clean(bus->dhd);
870510380 #endif /* DHDTCPACK_SUPPRESS */
870610381 /* Clear the data packet queues */
8707
- pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0);
10382
+ pktq_flush(dhdp->osh, &bus->txq, TRUE);
870810383 }
870910384 }
871010385
....@@ -8733,10 +10408,10 @@
873310408 #endif /* BCMSDIO */
873410409
873510410 #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)
873710413 {
873810414 uint32 rval;
8739
- struct dhd_bus *bus = (struct dhd_bus *) h;
874010415
874110416 dhd_os_sdlock(bus->dhd);
874210417
....@@ -8751,10 +10426,9 @@
875110426 return rval;
875210427 }
875310428
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)
875510431 {
8756
- struct dhd_bus *bus = (struct dhd_bus *) h;
8757
-
875810432 dhd_os_sdlock(bus->dhd);
875910433
876010434 BUS_WAKE(bus);
....@@ -8765,10 +10439,350 @@
876510439
876610440 dhd_os_sdunlock(bus->dhd);
876710441 }
10442
+
876810443 #endif /* DEBUGGER */
876910444
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
+}
877010752
877110753 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
877210786 dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len)
877310787 {
877410788 int ret = -1;
....@@ -8782,7 +10796,56 @@
878210796 return ret;
878310797 }
878410798
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
+
878510847 #ifdef DHD_ULP
10848
+
878610849 /* Function to disable console messages on entering ULP mode */
878710850 void
878810851 dhd_bus_ulp_disable_console(dhd_pub_t *dhdp)
....@@ -8795,7 +10858,7 @@
879510858
879610859 /* Flush the console buffer before disabling */
879710860 dhdsdio_readconsole(dhdp->bus);
8798
- dhd_console_ms = 0;
10861
+ dhdp->dhd_console_ms = 0;
879910862 #endif /* DHD_DEBUG */
880010863 }
880110864
....@@ -8821,10 +10884,10 @@
882110884 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
882210885
882310886 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)
882510888 dhd_enable_oob_intr(bus, TRUE);
882610889 bcmsdh_oob_intr_set(bus->sdh, TRUE);
8827
-#endif
10890
+#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
882810891 #ifdef DHD_DEBUG
882910892 /* Re-enable the console messages on FW redownload to default value */
883010893 dhd_ulp_restore_console_interval(bus->dhd);
....@@ -8840,73 +10903,40 @@
884010903
884110904 return bcmerror;
884210905 }
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
-}
891210906 #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 */