xref: /freebsd/sys/contrib/dev/broadcom/brcm80211/brcmfmac/pcie.c (revision 902136e0fe112383ec64d2ef43a446063b5e6417)
1b4c3e9b5SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2b4c3e9b5SBjoern A. Zeeb /*
3b4c3e9b5SBjoern A. Zeeb  * Copyright (c) 2014 Broadcom Corporation
4b4c3e9b5SBjoern A. Zeeb  */
5b4c3e9b5SBjoern A. Zeeb 
6b4c3e9b5SBjoern A. Zeeb #include <linux/kernel.h>
7b4c3e9b5SBjoern A. Zeeb #include <linux/module.h>
8b4c3e9b5SBjoern A. Zeeb #include <linux/firmware.h>
9b4c3e9b5SBjoern A. Zeeb #include <linux/pci.h>
10b4c3e9b5SBjoern A. Zeeb #include <linux/vmalloc.h>
11b4c3e9b5SBjoern A. Zeeb #include <linux/delay.h>
12b4c3e9b5SBjoern A. Zeeb #include <linux/interrupt.h>
13b4c3e9b5SBjoern A. Zeeb #include <linux/bcma/bcma.h>
14b4c3e9b5SBjoern A. Zeeb #include <linux/sched.h>
15b4c3e9b5SBjoern A. Zeeb #include <linux/sched/signal.h>
16b4c3e9b5SBjoern A. Zeeb #include <linux/kthread.h>
17b4c3e9b5SBjoern A. Zeeb #include <linux/io.h>
18b4c3e9b5SBjoern A. Zeeb #include <linux/random.h>
19b4c3e9b5SBjoern A. Zeeb #include <linux/unaligned.h>
20b4c3e9b5SBjoern A. Zeeb 
21b4c3e9b5SBjoern A. Zeeb #include <soc.h>
22b4c3e9b5SBjoern A. Zeeb #include <chipcommon.h>
23b4c3e9b5SBjoern A. Zeeb #include <brcmu_utils.h>
24b4c3e9b5SBjoern A. Zeeb #include <brcmu_wifi.h>
25b4c3e9b5SBjoern A. Zeeb #include <brcm_hw_ids.h>
26b4c3e9b5SBjoern A. Zeeb 
27b4c3e9b5SBjoern A. Zeeb /* Custom brcmf_err() that takes bus arg and passes it further */
28b4c3e9b5SBjoern A. Zeeb #define brcmf_err(bus, fmt, ...)					\
29b4c3e9b5SBjoern A. Zeeb 	do {								\
30b4c3e9b5SBjoern A. Zeeb 		if (IS_ENABLED(CONFIG_BRCMDBG) ||			\
31b4c3e9b5SBjoern A. Zeeb 		    IS_ENABLED(CONFIG_BRCM_TRACING) ||			\
32b4c3e9b5SBjoern A. Zeeb 		    net_ratelimit())					\
33b4c3e9b5SBjoern A. Zeeb 			__brcmf_err(bus, __func__, fmt, ##__VA_ARGS__);	\
34b4c3e9b5SBjoern A. Zeeb 	} while (0)
35b4c3e9b5SBjoern A. Zeeb 
36b4c3e9b5SBjoern A. Zeeb #include "debug.h"
37b4c3e9b5SBjoern A. Zeeb #include "bus.h"
38b4c3e9b5SBjoern A. Zeeb #include "commonring.h"
39b4c3e9b5SBjoern A. Zeeb #include "msgbuf.h"
40b4c3e9b5SBjoern A. Zeeb #include "pcie.h"
41b4c3e9b5SBjoern A. Zeeb #include "firmware.h"
42b4c3e9b5SBjoern A. Zeeb #include "chip.h"
43b4c3e9b5SBjoern A. Zeeb #include "core.h"
44b4c3e9b5SBjoern A. Zeeb #include "common.h"
45b4c3e9b5SBjoern A. Zeeb 
46b4c3e9b5SBjoern A. Zeeb 
47b4c3e9b5SBjoern A. Zeeb enum brcmf_pcie_state {
48b4c3e9b5SBjoern A. Zeeb 	BRCMFMAC_PCIE_STATE_DOWN,
49b4c3e9b5SBjoern A. Zeeb 	BRCMFMAC_PCIE_STATE_UP
50b4c3e9b5SBjoern A. Zeeb };
51b4c3e9b5SBjoern A. Zeeb 
52b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(43602, "brcmfmac43602-pcie");
53b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4350, "brcmfmac4350-pcie");
54b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie");
55b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4355, "brcmfmac4355-pcie");
56b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4355C1, "brcmfmac4355c1-pcie");
57b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-pcie");
58b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(43570, "brcmfmac43570-pcie");
59b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4358, "brcmfmac4358-pcie");
60b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4359, "brcmfmac4359-pcie");
61b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4359C, "brcmfmac4359c-pcie");
62b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4364B2, "brcmfmac4364b2-pcie");
63b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4364B3, "brcmfmac4364b3-pcie");
64b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie");
65b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
66b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
67b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
68b4c3e9b5SBjoern A. Zeeb BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
69b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie");
70b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
71b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
72b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
73b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
74b4c3e9b5SBjoern A. Zeeb BRCMF_FW_CLM_DEF(54591, "brcmfmac54591-pcie");
75b4c3e9b5SBjoern A. Zeeb 
76b4c3e9b5SBjoern A. Zeeb /* firmware config files */
77b4c3e9b5SBjoern A. Zeeb MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
78b4c3e9b5SBjoern A. Zeeb MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
79b4c3e9b5SBjoern A. Zeeb 
80b4c3e9b5SBjoern A. Zeeb /* per-board firmware binaries */
81b4c3e9b5SBjoern A. Zeeb MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
82b4c3e9b5SBjoern A. Zeeb MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
83b4c3e9b5SBjoern A. Zeeb MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txcap_blob");
84b4c3e9b5SBjoern A. Zeeb 
85b4c3e9b5SBjoern A. Zeeb static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
86b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
87b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
88b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
89b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),
90b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C),
91b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0x000007FF, 4355),
92b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0x00002000, 54591),
93b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0xFFFFF800, 4355C1), /* rev ID 12/C2 seen */
94b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
95b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
96b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
97b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
98b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
99b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0x000001FF, 4359),
100b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFE00, 4359C),
101b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0x0000000F, 4364B2), /* 3 */
102b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFF0, 4364B3), /* 4 */
103b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),
104b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),
105b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
106b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
107b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
108b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
109b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
110b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
111b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */
112b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
113b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
114b4c3e9b5SBjoern A. Zeeb 	BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */
115b4c3e9b5SBjoern A. Zeeb };
116b4c3e9b5SBjoern A. Zeeb 
117b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FW_UP_TIMEOUT		5000 /* msec */
118b4c3e9b5SBjoern A. Zeeb 
119b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_REG_MAP_SIZE			(32 * 1024)
120b4c3e9b5SBjoern A. Zeeb 
121b4c3e9b5SBjoern A. Zeeb /* backplane addres space accessed by BAR0 */
122b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_BAR0_WINDOW			0x80
123b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_BAR0_REG_SIZE		0x1000
124b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_BAR0_WRAPPERBASE		0x70
125b4c3e9b5SBjoern A. Zeeb 
126b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET	0x1000
127b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET	0x2000
128b4c3e9b5SBjoern A. Zeeb 
129b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_ARMCR4REG_BANKIDX		0x40
130b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_ARMCR4REG_BANKPDA		0x4C
131b4c3e9b5SBjoern A. Zeeb 
132b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_REG_INTSTATUS		0x90
133b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_REG_INTMASK			0x94
134b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_REG_SBMBX			0x98
135b4c3e9b5SBjoern A. Zeeb 
136b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_REG_LINK_STATUS_CTRL		0xBC
137b4c3e9b5SBjoern A. Zeeb 
138b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_INTMASK		0x24
139b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_MAILBOXINT		0x48
140b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK		0x4C
141b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_CONFIGADDR		0x120
142b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_CONFIGDATA		0x124
143b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0	0x140
144b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1	0x144
145b4c3e9b5SBjoern A. Zeeb 
146b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_PCIE2REG_INTMASK		0xC14
147b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT	0xC30
148b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK	0xC34
149b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0	0xA20
150b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1	0xA24
151b4c3e9b5SBjoern A. Zeeb 
152b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE2_INTA			0x01
153b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE2_INTB			0x02
154b4c3e9b5SBjoern A. Zeeb 
155b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_INT_0			0x01
156b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_INT_1			0x02
157b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_INT_DEF			(BRCMF_PCIE_INT_0 | \
158b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_INT_1)
159b4c3e9b5SBjoern A. Zeeb 
160b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MB_INT_FN0_0			0x0100
161b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MB_INT_FN0_1			0x0200
162b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H0_DB0		0x10000
163b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H0_DB1		0x20000
164b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H1_DB0		0x40000
165b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H1_DB1		0x80000
166b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H2_DB0		0x100000
167b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H2_DB1		0x200000
168b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H3_DB0		0x400000
169b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_MB_INT_D2H3_DB1		0x800000
170b4c3e9b5SBjoern A. Zeeb 
171b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MB_INT_FN0			(BRCMF_PCIE_MB_INT_FN0_0 | \
172b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_FN0_1)
173b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MB_INT_D2H_DB		(BRCMF_PCIE_MB_INT_D2H0_DB0 | \
174b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H0_DB1 | \
175b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H1_DB0 | \
176b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H1_DB1 | \
177b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H2_DB0 | \
178b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H2_DB1 | \
179b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H3_DB0 | \
180b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_MB_INT_D2H3_DB1)
181b4c3e9b5SBjoern A. Zeeb 
182b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H0_DB0		0x1
183b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H0_DB1		0x2
184b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H1_DB0		0x4
185b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H1_DB1		0x8
186b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H2_DB0		0x10
187b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H2_DB1		0x20
188b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H3_DB0		0x40
189b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H3_DB1		0x80
190b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H4_DB0		0x100
191b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H4_DB1		0x200
192b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H5_DB0		0x400
193b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H5_DB1		0x800
194b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H6_DB0		0x1000
195b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H6_DB1		0x2000
196b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H7_DB0		0x4000
197b4c3e9b5SBjoern A. Zeeb #define	BRCMF_PCIE_64_MB_INT_D2H7_DB1		0x8000
198b4c3e9b5SBjoern A. Zeeb 
199b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_64_MB_INT_D2H_DB		(BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \
200b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \
201b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \
202b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \
203b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \
204b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \
205b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \
206b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \
207b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \
208b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \
209b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \
210b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \
211b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \
212b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \
213b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \
214b4c3e9b5SBjoern A. Zeeb 						 BRCMF_PCIE_64_MB_INT_D2H7_DB1)
215b4c3e9b5SBjoern A. Zeeb 
216b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_SHARED_VERSION_7		7
217b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MIN_SHARED_VERSION		5
218b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MAX_SHARED_VERSION		BRCMF_PCIE_SHARED_VERSION_7
219b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_SHARED_VERSION_MASK		0x00FF
220b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_SHARED_DMA_INDEX		0x10000
221b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_SHARED_DMA_2B_IDX		0x100000
222b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_SHARED_HOSTRDY_DB1		0x10000000
223b4c3e9b5SBjoern A. Zeeb 
224b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FLAGS_HTOD_SPLIT		0x4000
225b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FLAGS_DTOH_SPLIT		0x8000
226b4c3e9b5SBjoern A. Zeeb 
227b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_MAX_RXBUFPOST_OFFSET	34
228b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_RING_BASE_OFFSET		52
229b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_RX_DATAOFFSET_OFFSET	36
230b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_CONSOLE_ADDR_OFFSET	20
231b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET	40
232b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET	44
233b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_RING_INFO_ADDR_OFFSET	48
234b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET	52
235b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET	56
236b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET	64
237b4c3e9b5SBjoern A. Zeeb #define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET	68
238b4c3e9b5SBjoern A. Zeeb 
239b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_H2D_RING_COUNT_OFFSET	0
240b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_D2H_RING_COUNT_OFFSET	1
241b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_H2D_RING_MEM_OFFSET		4
242b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_H2D_RING_STATE_OFFSET	8
243b4c3e9b5SBjoern A. Zeeb 
244b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_MEM_BASE_ADDR_OFFSET		8
245b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_MAX_ITEM_OFFSET		4
246b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_LEN_ITEMS_OFFSET		6
247b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_MEM_SZ			16
248b4c3e9b5SBjoern A. Zeeb #define BRCMF_RING_STATE_SZ			8
249b4c3e9b5SBjoern A. Zeeb 
250b4c3e9b5SBjoern A. Zeeb #define BRCMF_DEF_MAX_RXBUFPOST			255
251b4c3e9b5SBjoern A. Zeeb 
252b4c3e9b5SBjoern A. Zeeb #define BRCMF_CONSOLE_BUFADDR_OFFSET		8
253b4c3e9b5SBjoern A. Zeeb #define BRCMF_CONSOLE_BUFSIZE_OFFSET		12
254b4c3e9b5SBjoern A. Zeeb #define BRCMF_CONSOLE_WRITEIDX_OFFSET		16
255b4c3e9b5SBjoern A. Zeeb 
256b4c3e9b5SBjoern A. Zeeb #define BRCMF_DMA_D2H_SCRATCH_BUF_LEN		8
257b4c3e9b5SBjoern A. Zeeb #define BRCMF_DMA_D2H_RINGUPD_BUF_LEN		1024
258b4c3e9b5SBjoern A. Zeeb 
259b4c3e9b5SBjoern A. Zeeb #define BRCMF_D2H_DEV_D3_ACK			0x00000001
260b4c3e9b5SBjoern A. Zeeb #define BRCMF_D2H_DEV_DS_ENTER_REQ		0x00000002
261b4c3e9b5SBjoern A. Zeeb #define BRCMF_D2H_DEV_DS_EXIT_NOTE		0x00000004
262b4c3e9b5SBjoern A. Zeeb #define BRCMF_D2H_DEV_FWHALT			0x10000000
263b4c3e9b5SBjoern A. Zeeb 
264b4c3e9b5SBjoern A. Zeeb #define BRCMF_H2D_HOST_D3_INFORM		0x00000001
265b4c3e9b5SBjoern A. Zeeb #define BRCMF_H2D_HOST_DS_ACK			0x00000002
266b4c3e9b5SBjoern A. Zeeb #define BRCMF_H2D_HOST_D0_INFORM_IN_USE		0x00000008
267b4c3e9b5SBjoern A. Zeeb #define BRCMF_H2D_HOST_D0_INFORM		0x00000010
268b4c3e9b5SBjoern A. Zeeb 
269b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_MBDATA_TIMEOUT		msecs_to_jiffies(2000)
270b4c3e9b5SBjoern A. Zeeb 
271b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_STATUS_CMD		0x4
272b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_PM_CSR		0x4C
273b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_MSI_CAP		0x58
274b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_MSI_ADDR_L		0x5C
275b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_MSI_ADDR_H		0x60
276b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_MSI_DATA		0x64
277b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL	0xBC
278b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2	0xDC
279b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_RBAR_CTRL		0x228
280b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1	0x248
281b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG	0x4E0
282b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG	0x4F4
283b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB	3
284b4c3e9b5SBjoern A. Zeeb 
285b4c3e9b5SBjoern A. Zeeb /* Magic number at a magic location to find RAM size */
286b4c3e9b5SBjoern A. Zeeb #define BRCMF_RAMSIZE_MAGIC			0x534d4152	/* SMAR */
287b4c3e9b5SBjoern A. Zeeb #define BRCMF_RAMSIZE_OFFSET			0x6c
288b4c3e9b5SBjoern A. Zeeb 
289b4c3e9b5SBjoern A. Zeeb 
290b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_console {
291b4c3e9b5SBjoern A. Zeeb 	u32 base_addr;
292b4c3e9b5SBjoern A. Zeeb 	u32 buf_addr;
293b4c3e9b5SBjoern A. Zeeb 	u32 bufsize;
294b4c3e9b5SBjoern A. Zeeb 	u32 read_idx;
295b4c3e9b5SBjoern A. Zeeb 	u8 log_str[256];
296b4c3e9b5SBjoern A. Zeeb 	u8 log_idx;
297b4c3e9b5SBjoern A. Zeeb };
298b4c3e9b5SBjoern A. Zeeb 
299b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_shared_info {
300b4c3e9b5SBjoern A. Zeeb 	u32 tcm_base_address;
301b4c3e9b5SBjoern A. Zeeb 	u32 flags;
302b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
303b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *flowrings;
304b4c3e9b5SBjoern A. Zeeb 	u16 max_rxbufpost;
305b4c3e9b5SBjoern A. Zeeb 	u16 max_flowrings;
306b4c3e9b5SBjoern A. Zeeb 	u16 max_submissionrings;
307b4c3e9b5SBjoern A. Zeeb 	u16 max_completionrings;
308b4c3e9b5SBjoern A. Zeeb 	u32 rx_dataoffset;
309b4c3e9b5SBjoern A. Zeeb 	u32 htod_mb_data_addr;
310b4c3e9b5SBjoern A. Zeeb 	u32 dtoh_mb_data_addr;
311b4c3e9b5SBjoern A. Zeeb 	u32 ring_info_addr;
312b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_console console;
313b4c3e9b5SBjoern A. Zeeb 	void *scratch;
314b4c3e9b5SBjoern A. Zeeb 	dma_addr_t scratch_dmahandle;
315b4c3e9b5SBjoern A. Zeeb 	void *ringupd;
316b4c3e9b5SBjoern A. Zeeb 	dma_addr_t ringupd_dmahandle;
317b4c3e9b5SBjoern A. Zeeb 	u8 version;
318b4c3e9b5SBjoern A. Zeeb };
319b4c3e9b5SBjoern A. Zeeb 
320b4c3e9b5SBjoern A. Zeeb #define BRCMF_OTP_MAX_PARAM_LEN 16
321b4c3e9b5SBjoern A. Zeeb 
322b4c3e9b5SBjoern A. Zeeb struct brcmf_otp_params {
323b4c3e9b5SBjoern A. Zeeb 	char module[BRCMF_OTP_MAX_PARAM_LEN];
324b4c3e9b5SBjoern A. Zeeb 	char vendor[BRCMF_OTP_MAX_PARAM_LEN];
325b4c3e9b5SBjoern A. Zeeb 	char version[BRCMF_OTP_MAX_PARAM_LEN];
326b4c3e9b5SBjoern A. Zeeb 	bool valid;
327b4c3e9b5SBjoern A. Zeeb };
328b4c3e9b5SBjoern A. Zeeb 
329b4c3e9b5SBjoern A. Zeeb struct brcmf_pciedev_info {
330b4c3e9b5SBjoern A. Zeeb 	enum brcmf_pcie_state state;
331b4c3e9b5SBjoern A. Zeeb 	bool in_irq;
332b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev;
333b4c3e9b5SBjoern A. Zeeb 	char fw_name[BRCMF_FW_NAME_LEN];
334b4c3e9b5SBjoern A. Zeeb 	char nvram_name[BRCMF_FW_NAME_LEN];
335b4c3e9b5SBjoern A. Zeeb 	char clm_name[BRCMF_FW_NAME_LEN];
336b4c3e9b5SBjoern A. Zeeb 	char txcap_name[BRCMF_FW_NAME_LEN];
337b4c3e9b5SBjoern A. Zeeb 	const struct firmware *clm_fw;
338b4c3e9b5SBjoern A. Zeeb 	const struct firmware *txcap_fw;
339b4c3e9b5SBjoern A. Zeeb 	const struct brcmf_pcie_reginfo *reginfo;
340b4c3e9b5SBjoern A. Zeeb 	void __iomem *regs;
341b4c3e9b5SBjoern A. Zeeb 	void __iomem *tcm;
342b4c3e9b5SBjoern A. Zeeb 	u32 ram_base;
343b4c3e9b5SBjoern A. Zeeb 	u32 ram_size;
344b4c3e9b5SBjoern A. Zeeb 	struct brcmf_chip *ci;
345b4c3e9b5SBjoern A. Zeeb 	u32 coreid;
346b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_shared_info shared;
347b4c3e9b5SBjoern A. Zeeb 	wait_queue_head_t mbdata_resp_wait;
348b4c3e9b5SBjoern A. Zeeb 	bool mbdata_completed;
349b4c3e9b5SBjoern A. Zeeb 	bool irq_allocated;
350b4c3e9b5SBjoern A. Zeeb 	bool wowl_enabled;
351b4c3e9b5SBjoern A. Zeeb 	u8 dma_idx_sz;
352b4c3e9b5SBjoern A. Zeeb 	void *idxbuf;
353b4c3e9b5SBjoern A. Zeeb 	u32 idxbuf_sz;
354b4c3e9b5SBjoern A. Zeeb 	dma_addr_t idxbuf_dmahandle;
355b4c3e9b5SBjoern A. Zeeb 	u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
356b4c3e9b5SBjoern A. Zeeb 	void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
357b4c3e9b5SBjoern A. Zeeb 			  u16 value);
358b4c3e9b5SBjoern A. Zeeb 	struct brcmf_mp_device *settings;
359b4c3e9b5SBjoern A. Zeeb 	struct brcmf_otp_params otp;
360b4c3e9b5SBjoern A. Zeeb 	bool fwseed;
361b4c3e9b5SBjoern A. Zeeb #ifdef DEBUG
362b4c3e9b5SBjoern A. Zeeb 	u32 console_interval;
363b4c3e9b5SBjoern A. Zeeb 	bool console_active;
364b4c3e9b5SBjoern A. Zeeb 	struct timer_list timer;
365b4c3e9b5SBjoern A. Zeeb #endif
366b4c3e9b5SBjoern A. Zeeb };
367b4c3e9b5SBjoern A. Zeeb 
368b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_ringbuf {
369b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring commonring;
370b4c3e9b5SBjoern A. Zeeb 	dma_addr_t dma_handle;
371b4c3e9b5SBjoern A. Zeeb 	u32 w_idx_addr;
372b4c3e9b5SBjoern A. Zeeb 	u32 r_idx_addr;
373b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
374b4c3e9b5SBjoern A. Zeeb 	u8 id;
375b4c3e9b5SBjoern A. Zeeb };
376b4c3e9b5SBjoern A. Zeeb 
377b4c3e9b5SBjoern A. Zeeb /**
378b4c3e9b5SBjoern A. Zeeb  * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info
379b4c3e9b5SBjoern A. Zeeb  *
380b4c3e9b5SBjoern A. Zeeb  * @ringmem: dongle memory pointer to ring memory location
381b4c3e9b5SBjoern A. Zeeb  * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers
382b4c3e9b5SBjoern A. Zeeb  * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers
383b4c3e9b5SBjoern A. Zeeb  * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers
384b4c3e9b5SBjoern A. Zeeb  * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers
385b4c3e9b5SBjoern A. Zeeb  * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers
386b4c3e9b5SBjoern A. Zeeb  * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers
387b4c3e9b5SBjoern A. Zeeb  * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers
388b4c3e9b5SBjoern A. Zeeb  * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers
389b4c3e9b5SBjoern A. Zeeb  * @max_flowrings: maximum number of tx flow rings supported.
390b4c3e9b5SBjoern A. Zeeb  * @max_submissionrings: maximum number of submission rings(h2d) supported.
391b4c3e9b5SBjoern A. Zeeb  * @max_completionrings: maximum number of completion rings(d2h) supported.
392b4c3e9b5SBjoern A. Zeeb  */
393b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_dhi_ringinfo {
394b4c3e9b5SBjoern A. Zeeb 	__le32			ringmem;
395b4c3e9b5SBjoern A. Zeeb 	__le32			h2d_w_idx_ptr;
396b4c3e9b5SBjoern A. Zeeb 	__le32			h2d_r_idx_ptr;
397b4c3e9b5SBjoern A. Zeeb 	__le32			d2h_w_idx_ptr;
398b4c3e9b5SBjoern A. Zeeb 	__le32			d2h_r_idx_ptr;
399b4c3e9b5SBjoern A. Zeeb 	struct msgbuf_buf_addr	h2d_w_idx_hostaddr;
400b4c3e9b5SBjoern A. Zeeb 	struct msgbuf_buf_addr	h2d_r_idx_hostaddr;
401b4c3e9b5SBjoern A. Zeeb 	struct msgbuf_buf_addr	d2h_w_idx_hostaddr;
402b4c3e9b5SBjoern A. Zeeb 	struct msgbuf_buf_addr	d2h_r_idx_hostaddr;
403b4c3e9b5SBjoern A. Zeeb 	__le16			max_flowrings;
404b4c3e9b5SBjoern A. Zeeb 	__le16			max_submissionrings;
405b4c3e9b5SBjoern A. Zeeb 	__le16			max_completionrings;
406b4c3e9b5SBjoern A. Zeeb };
407b4c3e9b5SBjoern A. Zeeb 
408b4c3e9b5SBjoern A. Zeeb static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
409b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
410b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM,
411b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM,
412b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM,
413b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM
414b4c3e9b5SBjoern A. Zeeb };
415b4c3e9b5SBjoern A. Zeeb 
416b4c3e9b5SBjoern A. Zeeb static const u32 brcmf_ring_itemsize_pre_v7[BRCMF_NROF_COMMON_MSGRINGS] = {
417b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
418b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
419b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
420b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7,
421b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7
422b4c3e9b5SBjoern A. Zeeb };
423b4c3e9b5SBjoern A. Zeeb 
424b4c3e9b5SBjoern A. Zeeb static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
425b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
426b4c3e9b5SBjoern A. Zeeb 	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
427b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
428b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE,
429b4c3e9b5SBjoern A. Zeeb 	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
430b4c3e9b5SBjoern A. Zeeb };
431b4c3e9b5SBjoern A. Zeeb 
432b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_reginfo {
433b4c3e9b5SBjoern A. Zeeb 	u32 intmask;
434b4c3e9b5SBjoern A. Zeeb 	u32 mailboxint;
435b4c3e9b5SBjoern A. Zeeb 	u32 mailboxmask;
436b4c3e9b5SBjoern A. Zeeb 	u32 h2d_mailbox_0;
437b4c3e9b5SBjoern A. Zeeb 	u32 h2d_mailbox_1;
438b4c3e9b5SBjoern A. Zeeb 	u32 int_d2h_db;
439b4c3e9b5SBjoern A. Zeeb 	u32 int_fn0;
440b4c3e9b5SBjoern A. Zeeb };
441b4c3e9b5SBjoern A. Zeeb 
442b4c3e9b5SBjoern A. Zeeb static const struct brcmf_pcie_reginfo brcmf_reginfo_default = {
443b4c3e9b5SBjoern A. Zeeb 	.intmask = BRCMF_PCIE_PCIE2REG_INTMASK,
444b4c3e9b5SBjoern A. Zeeb 	.mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT,
445b4c3e9b5SBjoern A. Zeeb 	.mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
446b4c3e9b5SBjoern A. Zeeb 	.h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,
447b4c3e9b5SBjoern A. Zeeb 	.h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1,
448b4c3e9b5SBjoern A. Zeeb 	.int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB,
449b4c3e9b5SBjoern A. Zeeb 	.int_fn0 = BRCMF_PCIE_MB_INT_FN0,
450b4c3e9b5SBjoern A. Zeeb };
451b4c3e9b5SBjoern A. Zeeb 
452b4c3e9b5SBjoern A. Zeeb static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = {
453b4c3e9b5SBjoern A. Zeeb 	.intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK,
454b4c3e9b5SBjoern A. Zeeb 	.mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT,
455b4c3e9b5SBjoern A. Zeeb 	.mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK,
456b4c3e9b5SBjoern A. Zeeb 	.h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0,
457b4c3e9b5SBjoern A. Zeeb 	.h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1,
458b4c3e9b5SBjoern A. Zeeb 	.int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB,
459b4c3e9b5SBjoern A. Zeeb 	.int_fn0 = 0,
460b4c3e9b5SBjoern A. Zeeb };
461b4c3e9b5SBjoern A. Zeeb 
462b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_setup(struct device *dev, int ret,
463b4c3e9b5SBjoern A. Zeeb 			     struct brcmf_fw_request *fwreq);
464b4c3e9b5SBjoern A. Zeeb static struct brcmf_fw_request *
465b4c3e9b5SBjoern A. Zeeb brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);
466b4c3e9b5SBjoern A. Zeeb static void
467b4c3e9b5SBjoern A. Zeeb brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active);
468b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_debugfs_create(struct device *dev);
469b4c3e9b5SBjoern A. Zeeb 
470*902136e0SBjoern A. Zeeb #if defined(__FreeBSD__)
471*902136e0SBjoern A. Zeeb #define	VPAA(_x, _a)	(void __iomem *)((uintptr_t)(_x) + (_a))
472*902136e0SBjoern A. Zeeb #endif
473*902136e0SBjoern A. Zeeb 
474b4c3e9b5SBjoern A. Zeeb static u16
brcmf_pcie_read_reg16(struct brcmf_pciedev_info * devinfo,u32 reg_offset)475b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
476b4c3e9b5SBjoern A. Zeeb {
477*902136e0SBjoern A. Zeeb #if defined(__linux__)
478b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->regs + reg_offset;
479*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
480*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->regs, reg_offset);
481*902136e0SBjoern A. Zeeb #endif
482b4c3e9b5SBjoern A. Zeeb 
483b4c3e9b5SBjoern A. Zeeb 	return ioread16(address);
484b4c3e9b5SBjoern A. Zeeb }
485b4c3e9b5SBjoern A. Zeeb 
486b4c3e9b5SBjoern A. Zeeb static u32
brcmf_pcie_read_reg32(struct brcmf_pciedev_info * devinfo,u32 reg_offset)487b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
488b4c3e9b5SBjoern A. Zeeb {
489*902136e0SBjoern A. Zeeb #if defined(__linux__)
490b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->regs + reg_offset;
491*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
492*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->regs, reg_offset);
493*902136e0SBjoern A. Zeeb #endif
494b4c3e9b5SBjoern A. Zeeb 
495b4c3e9b5SBjoern A. Zeeb 	return (ioread32(address));
496b4c3e9b5SBjoern A. Zeeb }
497b4c3e9b5SBjoern A. Zeeb 
498b4c3e9b5SBjoern A. Zeeb 
499b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_write_reg32(struct brcmf_pciedev_info * devinfo,u32 reg_offset,u32 value)500b4c3e9b5SBjoern A. Zeeb brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
501b4c3e9b5SBjoern A. Zeeb 		       u32 value)
502b4c3e9b5SBjoern A. Zeeb {
503*902136e0SBjoern A. Zeeb #if defined(__linux__)
504b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->regs + reg_offset;
505*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
506*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->regs, reg_offset);
507*902136e0SBjoern A. Zeeb #endif
508b4c3e9b5SBjoern A. Zeeb 
509b4c3e9b5SBjoern A. Zeeb 	iowrite32(value, address);
510b4c3e9b5SBjoern A. Zeeb }
511b4c3e9b5SBjoern A. Zeeb 
512b4c3e9b5SBjoern A. Zeeb 
513b4c3e9b5SBjoern A. Zeeb static u8
brcmf_pcie_read_tcm8(struct brcmf_pciedev_info * devinfo,u32 mem_offset)514b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
515b4c3e9b5SBjoern A. Zeeb {
516*902136e0SBjoern A. Zeeb #if defined(__linux__)
517b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
518*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
519*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->tcm, mem_offset);
520*902136e0SBjoern A. Zeeb #endif
521b4c3e9b5SBjoern A. Zeeb 
522b4c3e9b5SBjoern A. Zeeb 	return (ioread8(address));
523b4c3e9b5SBjoern A. Zeeb }
524b4c3e9b5SBjoern A. Zeeb 
525b4c3e9b5SBjoern A. Zeeb 
526b4c3e9b5SBjoern A. Zeeb static u16
brcmf_pcie_read_tcm16(struct brcmf_pciedev_info * devinfo,u32 mem_offset)527b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
528b4c3e9b5SBjoern A. Zeeb {
529*902136e0SBjoern A. Zeeb #if defined(__linux__)
530b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
531*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
532*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->tcm, mem_offset);
533*902136e0SBjoern A. Zeeb #endif
534b4c3e9b5SBjoern A. Zeeb 
535b4c3e9b5SBjoern A. Zeeb 	return (ioread16(address));
536b4c3e9b5SBjoern A. Zeeb }
537b4c3e9b5SBjoern A. Zeeb 
538b4c3e9b5SBjoern A. Zeeb 
539b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_write_tcm16(struct brcmf_pciedev_info * devinfo,u32 mem_offset,u16 value)540b4c3e9b5SBjoern A. Zeeb brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
541b4c3e9b5SBjoern A. Zeeb 		       u16 value)
542b4c3e9b5SBjoern A. Zeeb {
543*902136e0SBjoern A. Zeeb #if defined(__linux__)
544b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
545*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
546*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->tcm, mem_offset);
547*902136e0SBjoern A. Zeeb #endif
548b4c3e9b5SBjoern A. Zeeb 
549b4c3e9b5SBjoern A. Zeeb 	iowrite16(value, address);
550b4c3e9b5SBjoern A. Zeeb }
551b4c3e9b5SBjoern A. Zeeb 
552b4c3e9b5SBjoern A. Zeeb 
553b4c3e9b5SBjoern A. Zeeb static u16
brcmf_pcie_read_idx(struct brcmf_pciedev_info * devinfo,u32 mem_offset)554b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
555b4c3e9b5SBjoern A. Zeeb {
556*902136e0SBjoern A. Zeeb #if defined(__linux__)
557b4c3e9b5SBjoern A. Zeeb 	u16 *address = devinfo->idxbuf + mem_offset;
558*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
559*902136e0SBjoern A. Zeeb 	u16 *address = (void *)((uintptr_t)devinfo->idxbuf + mem_offset);
560*902136e0SBjoern A. Zeeb #endif
561b4c3e9b5SBjoern A. Zeeb 
562b4c3e9b5SBjoern A. Zeeb 	return (*(address));
563b4c3e9b5SBjoern A. Zeeb }
564b4c3e9b5SBjoern A. Zeeb 
565b4c3e9b5SBjoern A. Zeeb 
566b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_write_idx(struct brcmf_pciedev_info * devinfo,u32 mem_offset,u16 value)567b4c3e9b5SBjoern A. Zeeb brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
568b4c3e9b5SBjoern A. Zeeb 		     u16 value)
569b4c3e9b5SBjoern A. Zeeb {
570*902136e0SBjoern A. Zeeb #if defined(__linux__)
571b4c3e9b5SBjoern A. Zeeb 	u16 *address = devinfo->idxbuf + mem_offset;
572*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
573*902136e0SBjoern A. Zeeb 	u16 *address = (void *)((uintptr_t)devinfo->idxbuf + mem_offset);
574*902136e0SBjoern A. Zeeb #endif
575b4c3e9b5SBjoern A. Zeeb 
576b4c3e9b5SBjoern A. Zeeb 	*(address) = value;
577b4c3e9b5SBjoern A. Zeeb }
578b4c3e9b5SBjoern A. Zeeb 
579b4c3e9b5SBjoern A. Zeeb 
580b4c3e9b5SBjoern A. Zeeb static u32
brcmf_pcie_read_tcm32(struct brcmf_pciedev_info * devinfo,u32 mem_offset)581b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
582b4c3e9b5SBjoern A. Zeeb {
583*902136e0SBjoern A. Zeeb #if defined(__linux__)
584b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
585*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
586*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->tcm, mem_offset);
587*902136e0SBjoern A. Zeeb #endif
588b4c3e9b5SBjoern A. Zeeb 
589b4c3e9b5SBjoern A. Zeeb 	return (ioread32(address));
590b4c3e9b5SBjoern A. Zeeb }
591b4c3e9b5SBjoern A. Zeeb 
592b4c3e9b5SBjoern A. Zeeb 
593b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_write_tcm32(struct brcmf_pciedev_info * devinfo,u32 mem_offset,u32 value)594b4c3e9b5SBjoern A. Zeeb brcmf_pcie_write_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
595b4c3e9b5SBjoern A. Zeeb 		       u32 value)
596b4c3e9b5SBjoern A. Zeeb {
597*902136e0SBjoern A. Zeeb #if defined(__linux__)
598b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
599*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
600*902136e0SBjoern A. Zeeb 	void __iomem *address = VPAA(devinfo->tcm, mem_offset);
601*902136e0SBjoern A. Zeeb #endif
602b4c3e9b5SBjoern A. Zeeb 
603b4c3e9b5SBjoern A. Zeeb 	iowrite32(value, address);
604b4c3e9b5SBjoern A. Zeeb }
605b4c3e9b5SBjoern A. Zeeb 
606b4c3e9b5SBjoern A. Zeeb 
607b4c3e9b5SBjoern A. Zeeb static u32
brcmf_pcie_read_ram32(struct brcmf_pciedev_info * devinfo,u32 mem_offset)608b4c3e9b5SBjoern A. Zeeb brcmf_pcie_read_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
609b4c3e9b5SBjoern A. Zeeb {
610*902136e0SBjoern A. Zeeb #if defined(__linux__)
611b4c3e9b5SBjoern A. Zeeb 	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
612*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
613*902136e0SBjoern A. Zeeb 	void __iomem *addr = VPAA(devinfo->tcm, devinfo->ci->rambase + mem_offset);
614*902136e0SBjoern A. Zeeb #endif
615b4c3e9b5SBjoern A. Zeeb 
616b4c3e9b5SBjoern A. Zeeb 	return (ioread32(addr));
617b4c3e9b5SBjoern A. Zeeb }
618b4c3e9b5SBjoern A. Zeeb 
619b4c3e9b5SBjoern A. Zeeb 
620b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_write_ram32(struct brcmf_pciedev_info * devinfo,u32 mem_offset,u32 value)621b4c3e9b5SBjoern A. Zeeb brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
622b4c3e9b5SBjoern A. Zeeb 		       u32 value)
623b4c3e9b5SBjoern A. Zeeb {
624*902136e0SBjoern A. Zeeb #if defined(__linux__)
625b4c3e9b5SBjoern A. Zeeb 	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
626*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
627*902136e0SBjoern A. Zeeb 	void __iomem *addr = VPAA(devinfo->tcm, devinfo->ci->rambase + mem_offset);
628*902136e0SBjoern A. Zeeb #endif
629b4c3e9b5SBjoern A. Zeeb 
630b4c3e9b5SBjoern A. Zeeb 	iowrite32(value, addr);
631b4c3e9b5SBjoern A. Zeeb }
632b4c3e9b5SBjoern A. Zeeb 
633b4c3e9b5SBjoern A. Zeeb 
634b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info * devinfo,u32 mem_offset,void * dstaddr,u32 len)635b4c3e9b5SBjoern A. Zeeb brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
636b4c3e9b5SBjoern A. Zeeb 			  void *dstaddr, u32 len)
637b4c3e9b5SBjoern A. Zeeb {
638*902136e0SBjoern A. Zeeb #if defined(__linux__)
639b4c3e9b5SBjoern A. Zeeb 	void __iomem *address = devinfo->tcm + mem_offset;
640*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
641*902136e0SBjoern A. Zeeb 	u8 __iomem *address = (void *)((uintptr_t)devinfo->tcm + mem_offset);
642*902136e0SBjoern A. Zeeb #endif
643b4c3e9b5SBjoern A. Zeeb 	__le32 *dst32;
644b4c3e9b5SBjoern A. Zeeb 	__le16 *dst16;
645b4c3e9b5SBjoern A. Zeeb 	u8 *dst8;
646b4c3e9b5SBjoern A. Zeeb 
647b4c3e9b5SBjoern A. Zeeb 	if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) {
648b4c3e9b5SBjoern A. Zeeb 		if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) {
649b4c3e9b5SBjoern A. Zeeb 			dst8 = (u8 *)dstaddr;
650b4c3e9b5SBjoern A. Zeeb 			while (len) {
651b4c3e9b5SBjoern A. Zeeb 				*dst8 = ioread8(address);
652b4c3e9b5SBjoern A. Zeeb 				address++;
653b4c3e9b5SBjoern A. Zeeb 				dst8++;
654b4c3e9b5SBjoern A. Zeeb 				len--;
655b4c3e9b5SBjoern A. Zeeb 			}
656b4c3e9b5SBjoern A. Zeeb 		} else {
657b4c3e9b5SBjoern A. Zeeb 			len = len / 2;
658b4c3e9b5SBjoern A. Zeeb 			dst16 = (__le16 *)dstaddr;
659b4c3e9b5SBjoern A. Zeeb 			while (len) {
660b4c3e9b5SBjoern A. Zeeb 				*dst16 = cpu_to_le16(ioread16(address));
661b4c3e9b5SBjoern A. Zeeb 				address += 2;
662b4c3e9b5SBjoern A. Zeeb 				dst16++;
663b4c3e9b5SBjoern A. Zeeb 				len--;
664b4c3e9b5SBjoern A. Zeeb 			}
665b4c3e9b5SBjoern A. Zeeb 		}
666b4c3e9b5SBjoern A. Zeeb 	} else {
667b4c3e9b5SBjoern A. Zeeb 		len = len / 4;
668b4c3e9b5SBjoern A. Zeeb 		dst32 = (__le32 *)dstaddr;
669b4c3e9b5SBjoern A. Zeeb 		while (len) {
670b4c3e9b5SBjoern A. Zeeb 			*dst32 = cpu_to_le32(ioread32(address));
671b4c3e9b5SBjoern A. Zeeb 			address += 4;
672b4c3e9b5SBjoern A. Zeeb 			dst32++;
673b4c3e9b5SBjoern A. Zeeb 			len--;
674b4c3e9b5SBjoern A. Zeeb 		}
675b4c3e9b5SBjoern A. Zeeb 	}
676b4c3e9b5SBjoern A. Zeeb }
677b4c3e9b5SBjoern A. Zeeb 
678b4c3e9b5SBjoern A. Zeeb 
679b4c3e9b5SBjoern A. Zeeb #define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \
680b4c3e9b5SBjoern A. Zeeb 		CHIPCREGOFFS(reg))
681b4c3e9b5SBjoern A. Zeeb #define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
682b4c3e9b5SBjoern A. Zeeb 		CHIPCREGOFFS(reg), value)
683b4c3e9b5SBjoern A. Zeeb 
684b4c3e9b5SBjoern A. Zeeb 
685b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_select_core(struct brcmf_pciedev_info * devinfo,u16 coreid)686b4c3e9b5SBjoern A. Zeeb brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
687b4c3e9b5SBjoern A. Zeeb {
688b4c3e9b5SBjoern A. Zeeb 	const struct pci_dev *pdev = devinfo->pdev;
689b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
690b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
691b4c3e9b5SBjoern A. Zeeb 	u32 bar0_win;
692b4c3e9b5SBjoern A. Zeeb 
693b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(devinfo->ci, coreid);
694b4c3e9b5SBjoern A. Zeeb 	if (core) {
695b4c3e9b5SBjoern A. Zeeb 		bar0_win = core->base;
696b4c3e9b5SBjoern A. Zeeb 		pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, bar0_win);
697b4c3e9b5SBjoern A. Zeeb 		if (pci_read_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW,
698b4c3e9b5SBjoern A. Zeeb 					  &bar0_win) == 0) {
699b4c3e9b5SBjoern A. Zeeb 			if (bar0_win != core->base) {
700b4c3e9b5SBjoern A. Zeeb 				bar0_win = core->base;
701b4c3e9b5SBjoern A. Zeeb 				pci_write_config_dword(pdev,
702b4c3e9b5SBjoern A. Zeeb 						       BRCMF_PCIE_BAR0_WINDOW,
703b4c3e9b5SBjoern A. Zeeb 						       bar0_win);
704b4c3e9b5SBjoern A. Zeeb 			}
705b4c3e9b5SBjoern A. Zeeb 		}
706b4c3e9b5SBjoern A. Zeeb 	} else {
707b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Unsupported core selected %x\n", coreid);
708b4c3e9b5SBjoern A. Zeeb 	}
709b4c3e9b5SBjoern A. Zeeb }
710b4c3e9b5SBjoern A. Zeeb 
711b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_reset_device(struct brcmf_pciedev_info * devinfo)712b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
713b4c3e9b5SBjoern A. Zeeb {
714b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
715b4c3e9b5SBjoern A. Zeeb 	static const u16 cfg_offset[] = {
716b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_STATUS_CMD,
717b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_PM_CSR,
718b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_MSI_CAP,
719b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_MSI_ADDR_L,
720b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_MSI_ADDR_H,
721b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_MSI_DATA,
722b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
723b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_RBAR_CTRL,
724b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
725b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
726b4c3e9b5SBjoern A. Zeeb 		BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG
727b4c3e9b5SBjoern A. Zeeb 	};
728b4c3e9b5SBjoern A. Zeeb 	u32 i;
729b4c3e9b5SBjoern A. Zeeb 	u32 val;
730b4c3e9b5SBjoern A. Zeeb 	u32 lsc;
731b4c3e9b5SBjoern A. Zeeb 
732b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->ci)
733b4c3e9b5SBjoern A. Zeeb 		return;
734b4c3e9b5SBjoern A. Zeeb 
735b4c3e9b5SBjoern A. Zeeb 	/* Disable ASPM */
736b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
737b4c3e9b5SBjoern A. Zeeb 	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
738b4c3e9b5SBjoern A. Zeeb 			      &lsc);
739b4c3e9b5SBjoern A. Zeeb 	val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
740b4c3e9b5SBjoern A. Zeeb 	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
741b4c3e9b5SBjoern A. Zeeb 			       val);
742b4c3e9b5SBjoern A. Zeeb 
743b4c3e9b5SBjoern A. Zeeb 	/* Watchdog reset */
744b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
745b4c3e9b5SBjoern A. Zeeb 	WRITECC32(devinfo, watchdog, 4);
746*902136e0SBjoern A. Zeeb #if defined(__linux__)
747b4c3e9b5SBjoern A. Zeeb 	msleep(100);
748*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
749*902136e0SBjoern A. Zeeb 	linux_msleep(100);
750*902136e0SBjoern A. Zeeb #endif
751b4c3e9b5SBjoern A. Zeeb 
752b4c3e9b5SBjoern A. Zeeb 	/* Restore ASPM */
753b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
754b4c3e9b5SBjoern A. Zeeb 	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
755b4c3e9b5SBjoern A. Zeeb 			       lsc);
756b4c3e9b5SBjoern A. Zeeb 
757b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
758b4c3e9b5SBjoern A. Zeeb 	if (core->rev <= 13) {
759b4c3e9b5SBjoern A. Zeeb 		for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
760b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_write_reg32(devinfo,
761b4c3e9b5SBjoern A. Zeeb 					       BRCMF_PCIE_PCIE2REG_CONFIGADDR,
762b4c3e9b5SBjoern A. Zeeb 					       cfg_offset[i]);
763b4c3e9b5SBjoern A. Zeeb 			val = brcmf_pcie_read_reg32(devinfo,
764b4c3e9b5SBjoern A. Zeeb 				BRCMF_PCIE_PCIE2REG_CONFIGDATA);
765b4c3e9b5SBjoern A. Zeeb 			brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
766b4c3e9b5SBjoern A. Zeeb 				  cfg_offset[i], val);
767b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_write_reg32(devinfo,
768b4c3e9b5SBjoern A. Zeeb 					       BRCMF_PCIE_PCIE2REG_CONFIGDATA,
769b4c3e9b5SBjoern A. Zeeb 					       val);
770b4c3e9b5SBjoern A. Zeeb 		}
771b4c3e9b5SBjoern A. Zeeb 	}
772b4c3e9b5SBjoern A. Zeeb }
773b4c3e9b5SBjoern A. Zeeb 
774b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_attach(struct brcmf_pciedev_info * devinfo)775b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
776b4c3e9b5SBjoern A. Zeeb {
777b4c3e9b5SBjoern A. Zeeb 	u32 config;
778b4c3e9b5SBjoern A. Zeeb 
779b4c3e9b5SBjoern A. Zeeb 	/* BAR1 window may not be sized properly */
780b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
781b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
782b4c3e9b5SBjoern A. Zeeb 	config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
783b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
784b4c3e9b5SBjoern A. Zeeb 
785b4c3e9b5SBjoern A. Zeeb 	device_wakeup_enable(&devinfo->pdev->dev);
786b4c3e9b5SBjoern A. Zeeb }
787b4c3e9b5SBjoern A. Zeeb 
788b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_enter_download_state(struct brcmf_pciedev_info * devinfo)789b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
790b4c3e9b5SBjoern A. Zeeb {
791b4c3e9b5SBjoern A. Zeeb 	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
792b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
793b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
794b4c3e9b5SBjoern A. Zeeb 				       5);
795b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
796b4c3e9b5SBjoern A. Zeeb 				       0);
797b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
798b4c3e9b5SBjoern A. Zeeb 				       7);
799b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
800b4c3e9b5SBjoern A. Zeeb 				       0);
801b4c3e9b5SBjoern A. Zeeb 	}
802b4c3e9b5SBjoern A. Zeeb 	return 0;
803b4c3e9b5SBjoern A. Zeeb }
804b4c3e9b5SBjoern A. Zeeb 
805b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_exit_download_state(struct brcmf_pciedev_info * devinfo,u32 resetintr)806b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
807b4c3e9b5SBjoern A. Zeeb 					  u32 resetintr)
808b4c3e9b5SBjoern A. Zeeb {
809b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
810b4c3e9b5SBjoern A. Zeeb 
811b4c3e9b5SBjoern A. Zeeb 	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
812b4c3e9b5SBjoern A. Zeeb 		core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_INTERNAL_MEM);
813b4c3e9b5SBjoern A. Zeeb 		brcmf_chip_resetcore(core, 0, 0, 0);
814b4c3e9b5SBjoern A. Zeeb 	}
815b4c3e9b5SBjoern A. Zeeb 
816b4c3e9b5SBjoern A. Zeeb 	if (!brcmf_chip_set_active(devinfo->ci, resetintr))
817b4c3e9b5SBjoern A. Zeeb 		return -EIO;
818b4c3e9b5SBjoern A. Zeeb 	return 0;
819b4c3e9b5SBjoern A. Zeeb }
820b4c3e9b5SBjoern A. Zeeb 
821b4c3e9b5SBjoern A. Zeeb 
822b4c3e9b5SBjoern A. Zeeb static int
brcmf_pcie_send_mb_data(struct brcmf_pciedev_info * devinfo,u32 htod_mb_data)823b4c3e9b5SBjoern A. Zeeb brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
824b4c3e9b5SBjoern A. Zeeb {
825b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_shared_info *shared;
826b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
827b4c3e9b5SBjoern A. Zeeb 	u32 addr;
828b4c3e9b5SBjoern A. Zeeb 	u32 cur_htod_mb_data;
829b4c3e9b5SBjoern A. Zeeb 	u32 i;
830b4c3e9b5SBjoern A. Zeeb 
831b4c3e9b5SBjoern A. Zeeb 	shared = &devinfo->shared;
832b4c3e9b5SBjoern A. Zeeb 	addr = shared->htod_mb_data_addr;
833b4c3e9b5SBjoern A. Zeeb 	cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
834b4c3e9b5SBjoern A. Zeeb 
835b4c3e9b5SBjoern A. Zeeb 	if (cur_htod_mb_data != 0)
836b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",
837b4c3e9b5SBjoern A. Zeeb 			  cur_htod_mb_data);
838b4c3e9b5SBjoern A. Zeeb 
839b4c3e9b5SBjoern A. Zeeb 	i = 0;
840b4c3e9b5SBjoern A. Zeeb 	while (cur_htod_mb_data != 0) {
841*902136e0SBjoern A. Zeeb #if defined(__linux__)
842b4c3e9b5SBjoern A. Zeeb 		msleep(10);
843*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
844*902136e0SBjoern A. Zeeb 		linux_msleep(10);
845*902136e0SBjoern A. Zeeb #endif
846b4c3e9b5SBjoern A. Zeeb 		i++;
847b4c3e9b5SBjoern A. Zeeb 		if (i > 100)
848b4c3e9b5SBjoern A. Zeeb 			return -EIO;
849b4c3e9b5SBjoern A. Zeeb 		cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
850b4c3e9b5SBjoern A. Zeeb 	}
851b4c3e9b5SBjoern A. Zeeb 
852b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);
853b4c3e9b5SBjoern A. Zeeb 	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
854b4c3e9b5SBjoern A. Zeeb 
855b4c3e9b5SBjoern A. Zeeb 	/* Send mailbox interrupt twice as a hardware workaround */
856b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
857b4c3e9b5SBjoern A. Zeeb 	if (core->rev <= 13)
858b4c3e9b5SBjoern A. Zeeb 		pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
859b4c3e9b5SBjoern A. Zeeb 
860b4c3e9b5SBjoern A. Zeeb 	return 0;
861b4c3e9b5SBjoern A. Zeeb }
862b4c3e9b5SBjoern A. Zeeb 
863b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info * devinfo)864b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
865b4c3e9b5SBjoern A. Zeeb {
866b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_shared_info *shared;
867b4c3e9b5SBjoern A. Zeeb 	u32 addr;
868b4c3e9b5SBjoern A. Zeeb 	u32 dtoh_mb_data;
869b4c3e9b5SBjoern A. Zeeb 
870b4c3e9b5SBjoern A. Zeeb 	shared = &devinfo->shared;
871b4c3e9b5SBjoern A. Zeeb 	addr = shared->dtoh_mb_data_addr;
872b4c3e9b5SBjoern A. Zeeb 	dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
873b4c3e9b5SBjoern A. Zeeb 
874b4c3e9b5SBjoern A. Zeeb 	if (!dtoh_mb_data)
875b4c3e9b5SBjoern A. Zeeb 		return;
876b4c3e9b5SBjoern A. Zeeb 
877b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, 0);
878b4c3e9b5SBjoern A. Zeeb 
879b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
880b4c3e9b5SBjoern A. Zeeb 	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ)  {
881b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
882b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
883b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
884b4c3e9b5SBjoern A. Zeeb 	}
885b4c3e9b5SBjoern A. Zeeb 	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
886b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
887b4c3e9b5SBjoern A. Zeeb 	if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
888b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
889b4c3e9b5SBjoern A. Zeeb 		devinfo->mbdata_completed = true;
890b4c3e9b5SBjoern A. Zeeb 		wake_up(&devinfo->mbdata_resp_wait);
891b4c3e9b5SBjoern A. Zeeb 	}
892b4c3e9b5SBjoern A. Zeeb 	if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
893b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
894b4c3e9b5SBjoern A. Zeeb 		brcmf_fw_crashed(&devinfo->pdev->dev);
895b4c3e9b5SBjoern A. Zeeb 	}
896b4c3e9b5SBjoern A. Zeeb }
897b4c3e9b5SBjoern A. Zeeb 
898b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_bus_console_init(struct brcmf_pciedev_info * devinfo)899b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
900b4c3e9b5SBjoern A. Zeeb {
901b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_shared_info *shared;
902b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_console *console;
903b4c3e9b5SBjoern A. Zeeb 	u32 addr;
904b4c3e9b5SBjoern A. Zeeb 
905b4c3e9b5SBjoern A. Zeeb 	shared = &devinfo->shared;
906b4c3e9b5SBjoern A. Zeeb 	console = &shared->console;
907b4c3e9b5SBjoern A. Zeeb 	addr = shared->tcm_base_address + BRCMF_SHARED_CONSOLE_ADDR_OFFSET;
908b4c3e9b5SBjoern A. Zeeb 	console->base_addr = brcmf_pcie_read_tcm32(devinfo, addr);
909b4c3e9b5SBjoern A. Zeeb 
910b4c3e9b5SBjoern A. Zeeb 	addr = console->base_addr + BRCMF_CONSOLE_BUFADDR_OFFSET;
911b4c3e9b5SBjoern A. Zeeb 	console->buf_addr = brcmf_pcie_read_tcm32(devinfo, addr);
912b4c3e9b5SBjoern A. Zeeb 	addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
913b4c3e9b5SBjoern A. Zeeb 	console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
914b4c3e9b5SBjoern A. Zeeb 
915b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
916b4c3e9b5SBjoern A. Zeeb 		  console->base_addr, console->buf_addr, console->bufsize);
917b4c3e9b5SBjoern A. Zeeb }
918b4c3e9b5SBjoern A. Zeeb 
919b4c3e9b5SBjoern A. Zeeb /**
920b4c3e9b5SBjoern A. Zeeb  * brcmf_pcie_bus_console_read - reads firmware messages
921b4c3e9b5SBjoern A. Zeeb  *
922b4c3e9b5SBjoern A. Zeeb  * @devinfo: pointer to the device data structure
923b4c3e9b5SBjoern A. Zeeb  * @error: specifies if error has occurred (prints messages unconditionally)
924b4c3e9b5SBjoern A. Zeeb  */
brcmf_pcie_bus_console_read(struct brcmf_pciedev_info * devinfo,bool error)925b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
926b4c3e9b5SBjoern A. Zeeb 					bool error)
927b4c3e9b5SBjoern A. Zeeb {
928b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev = devinfo->pdev;
929b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
930b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_console *console;
931b4c3e9b5SBjoern A. Zeeb 	u32 addr;
932b4c3e9b5SBjoern A. Zeeb 	u8 ch;
933b4c3e9b5SBjoern A. Zeeb 	u32 newidx;
934b4c3e9b5SBjoern A. Zeeb 
935b4c3e9b5SBjoern A. Zeeb 	if (!error && !BRCMF_FWCON_ON())
936b4c3e9b5SBjoern A. Zeeb 		return;
937b4c3e9b5SBjoern A. Zeeb 
938b4c3e9b5SBjoern A. Zeeb 	console = &devinfo->shared.console;
939b4c3e9b5SBjoern A. Zeeb 	if (!console->base_addr)
940b4c3e9b5SBjoern A. Zeeb 		return;
941b4c3e9b5SBjoern A. Zeeb 	addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
942b4c3e9b5SBjoern A. Zeeb 	newidx = brcmf_pcie_read_tcm32(devinfo, addr);
943b4c3e9b5SBjoern A. Zeeb 	while (newidx != console->read_idx) {
944b4c3e9b5SBjoern A. Zeeb 		addr = console->buf_addr + console->read_idx;
945b4c3e9b5SBjoern A. Zeeb 		ch = brcmf_pcie_read_tcm8(devinfo, addr);
946b4c3e9b5SBjoern A. Zeeb 		console->read_idx++;
947b4c3e9b5SBjoern A. Zeeb 		if (console->read_idx == console->bufsize)
948b4c3e9b5SBjoern A. Zeeb 			console->read_idx = 0;
949b4c3e9b5SBjoern A. Zeeb 		if (ch == '\r')
950b4c3e9b5SBjoern A. Zeeb 			continue;
951b4c3e9b5SBjoern A. Zeeb 		console->log_str[console->log_idx] = ch;
952b4c3e9b5SBjoern A. Zeeb 		console->log_idx++;
953b4c3e9b5SBjoern A. Zeeb 		if ((ch != '\n') &&
954b4c3e9b5SBjoern A. Zeeb 		    (console->log_idx == (sizeof(console->log_str) - 2))) {
955b4c3e9b5SBjoern A. Zeeb 			ch = '\n';
956b4c3e9b5SBjoern A. Zeeb 			console->log_str[console->log_idx] = ch;
957b4c3e9b5SBjoern A. Zeeb 			console->log_idx++;
958b4c3e9b5SBjoern A. Zeeb 		}
959b4c3e9b5SBjoern A. Zeeb 		if (ch == '\n') {
960b4c3e9b5SBjoern A. Zeeb 			console->log_str[console->log_idx] = 0;
961b4c3e9b5SBjoern A. Zeeb 			if (error)
962b4c3e9b5SBjoern A. Zeeb 				__brcmf_err(bus, __func__, "CONSOLE: %s",
963b4c3e9b5SBjoern A. Zeeb 					    console->log_str);
964b4c3e9b5SBjoern A. Zeeb 			else
965b4c3e9b5SBjoern A. Zeeb 				pr_debug("CONSOLE: %s", console->log_str);
966b4c3e9b5SBjoern A. Zeeb 			console->log_idx = 0;
967b4c3e9b5SBjoern A. Zeeb 		}
968b4c3e9b5SBjoern A. Zeeb 	}
969b4c3e9b5SBjoern A. Zeeb }
970b4c3e9b5SBjoern A. Zeeb 
971b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_intr_disable(struct brcmf_pciedev_info * devinfo)972b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
973b4c3e9b5SBjoern A. Zeeb {
974b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
975b4c3e9b5SBjoern A. Zeeb }
976b4c3e9b5SBjoern A. Zeeb 
977b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_intr_enable(struct brcmf_pciedev_info * devinfo)978b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
979b4c3e9b5SBjoern A. Zeeb {
980b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
981b4c3e9b5SBjoern A. Zeeb 			       devinfo->reginfo->int_d2h_db |
982b4c3e9b5SBjoern A. Zeeb 			       devinfo->reginfo->int_fn0);
983b4c3e9b5SBjoern A. Zeeb }
984b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_hostready(struct brcmf_pciedev_info * devinfo)985b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
986b4c3e9b5SBjoern A. Zeeb {
987b4c3e9b5SBjoern A. Zeeb 	if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
988b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo,
989b4c3e9b5SBjoern A. Zeeb 				       devinfo->reginfo->h2d_mailbox_1, 1);
990b4c3e9b5SBjoern A. Zeeb }
991b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_quick_check_isr(int irq,void * arg)992b4c3e9b5SBjoern A. Zeeb static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
993b4c3e9b5SBjoern A. Zeeb {
994b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
995b4c3e9b5SBjoern A. Zeeb 
996b4c3e9b5SBjoern A. Zeeb 	if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
997b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_intr_disable(devinfo);
998b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Enter\n");
999b4c3e9b5SBjoern A. Zeeb 		return IRQ_WAKE_THREAD;
1000b4c3e9b5SBjoern A. Zeeb 	}
1001b4c3e9b5SBjoern A. Zeeb 	return IRQ_NONE;
1002b4c3e9b5SBjoern A. Zeeb }
1003b4c3e9b5SBjoern A. Zeeb 
1004b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_isr_thread(int irq,void * arg)1005b4c3e9b5SBjoern A. Zeeb static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
1006b4c3e9b5SBjoern A. Zeeb {
1007b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
1008b4c3e9b5SBjoern A. Zeeb 	u32 status;
1009b4c3e9b5SBjoern A. Zeeb 
1010b4c3e9b5SBjoern A. Zeeb 	devinfo->in_irq = true;
1011b4c3e9b5SBjoern A. Zeeb 	status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1012b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter %x\n", status);
1013b4c3e9b5SBjoern A. Zeeb 	if (status) {
1014b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
1015b4c3e9b5SBjoern A. Zeeb 				       status);
1016b4c3e9b5SBjoern A. Zeeb 		if (status & devinfo->reginfo->int_fn0)
1017b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_handle_mb_data(devinfo);
1018b4c3e9b5SBjoern A. Zeeb 		if (status & devinfo->reginfo->int_d2h_db) {
1019b4c3e9b5SBjoern A. Zeeb 			if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
1020b4c3e9b5SBjoern A. Zeeb 				brcmf_proto_msgbuf_rx_trigger(
1021b4c3e9b5SBjoern A. Zeeb 							&devinfo->pdev->dev);
1022b4c3e9b5SBjoern A. Zeeb 		}
1023b4c3e9b5SBjoern A. Zeeb 	}
1024b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, false);
1025b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
1026b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_intr_enable(devinfo);
1027b4c3e9b5SBjoern A. Zeeb 	devinfo->in_irq = false;
1028b4c3e9b5SBjoern A. Zeeb 	return IRQ_HANDLED;
1029b4c3e9b5SBjoern A. Zeeb }
1030b4c3e9b5SBjoern A. Zeeb 
1031b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_request_irq(struct brcmf_pciedev_info * devinfo)1032b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
1033b4c3e9b5SBjoern A. Zeeb {
1034b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev = devinfo->pdev;
1035b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
1036b4c3e9b5SBjoern A. Zeeb 
1037b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_intr_disable(devinfo);
1038b4c3e9b5SBjoern A. Zeeb 
1039b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
1040b4c3e9b5SBjoern A. Zeeb 
1041b4c3e9b5SBjoern A. Zeeb 	pci_enable_msi(pdev);
1042b4c3e9b5SBjoern A. Zeeb 	if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr,
1043b4c3e9b5SBjoern A. Zeeb 				 brcmf_pcie_isr_thread, IRQF_SHARED,
1044b4c3e9b5SBjoern A. Zeeb 				 "brcmf_pcie_intr", devinfo)) {
1045b4c3e9b5SBjoern A. Zeeb 		pci_disable_msi(pdev);
1046b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Failed to request IRQ %d\n", pdev->irq);
1047b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1048b4c3e9b5SBjoern A. Zeeb 	}
1049b4c3e9b5SBjoern A. Zeeb 	devinfo->irq_allocated = true;
1050b4c3e9b5SBjoern A. Zeeb 	return 0;
1051b4c3e9b5SBjoern A. Zeeb }
1052b4c3e9b5SBjoern A. Zeeb 
1053b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_release_irq(struct brcmf_pciedev_info * devinfo)1054b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
1055b4c3e9b5SBjoern A. Zeeb {
1056b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev = devinfo->pdev;
1057b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
1058b4c3e9b5SBjoern A. Zeeb 	u32 status;
1059b4c3e9b5SBjoern A. Zeeb 	u32 count;
1060b4c3e9b5SBjoern A. Zeeb 
1061b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->irq_allocated)
1062b4c3e9b5SBjoern A. Zeeb 		return;
1063b4c3e9b5SBjoern A. Zeeb 
1064b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_intr_disable(devinfo);
1065b4c3e9b5SBjoern A. Zeeb 	free_irq(pdev->irq, devinfo);
1066b4c3e9b5SBjoern A. Zeeb 	pci_disable_msi(pdev);
1067b4c3e9b5SBjoern A. Zeeb 
1068*902136e0SBjoern A. Zeeb #if defined(__linux__)
1069b4c3e9b5SBjoern A. Zeeb 	msleep(50);
1070*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1071*902136e0SBjoern A. Zeeb 	linux_msleep(50);
1072*902136e0SBjoern A. Zeeb #endif
1073b4c3e9b5SBjoern A. Zeeb 	count = 0;
1074b4c3e9b5SBjoern A. Zeeb 	while ((devinfo->in_irq) && (count < 20)) {
1075*902136e0SBjoern A. Zeeb #if defined(__linux__)
1076b4c3e9b5SBjoern A. Zeeb 		msleep(50);
1077*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1078*902136e0SBjoern A. Zeeb 		linux_msleep(50);
1079*902136e0SBjoern A. Zeeb #endif
1080b4c3e9b5SBjoern A. Zeeb 		count++;
1081b4c3e9b5SBjoern A. Zeeb 	}
1082b4c3e9b5SBjoern A. Zeeb 	if (devinfo->in_irq)
1083b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Still in IRQ (processing) !!!\n");
1084b4c3e9b5SBjoern A. Zeeb 
1085b4c3e9b5SBjoern A. Zeeb 	status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1086b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
1087b4c3e9b5SBjoern A. Zeeb 
1088b4c3e9b5SBjoern A. Zeeb 	devinfo->irq_allocated = false;
1089b4c3e9b5SBjoern A. Zeeb }
1090b4c3e9b5SBjoern A. Zeeb 
1091b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_ring_mb_write_rptr(void * ctx)1092b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
1093b4c3e9b5SBjoern A. Zeeb {
1094b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
1095b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = ring->devinfo;
1096b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring *commonring = &ring->commonring;
1097b4c3e9b5SBjoern A. Zeeb 
1098b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
1099b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1100b4c3e9b5SBjoern A. Zeeb 
1101b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
1102b4c3e9b5SBjoern A. Zeeb 		  commonring->w_ptr, ring->id);
1103b4c3e9b5SBjoern A. Zeeb 
1104b4c3e9b5SBjoern A. Zeeb 	devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
1105b4c3e9b5SBjoern A. Zeeb 
1106b4c3e9b5SBjoern A. Zeeb 	return 0;
1107b4c3e9b5SBjoern A. Zeeb }
1108b4c3e9b5SBjoern A. Zeeb 
1109b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_ring_mb_write_wptr(void * ctx)1110b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
1111b4c3e9b5SBjoern A. Zeeb {
1112b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
1113b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = ring->devinfo;
1114b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring *commonring = &ring->commonring;
1115b4c3e9b5SBjoern A. Zeeb 
1116b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
1117b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1118b4c3e9b5SBjoern A. Zeeb 
1119b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
1120b4c3e9b5SBjoern A. Zeeb 		  commonring->r_ptr, ring->id);
1121b4c3e9b5SBjoern A. Zeeb 
1122b4c3e9b5SBjoern A. Zeeb 	devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
1123b4c3e9b5SBjoern A. Zeeb 
1124b4c3e9b5SBjoern A. Zeeb 	return 0;
1125b4c3e9b5SBjoern A. Zeeb }
1126b4c3e9b5SBjoern A. Zeeb 
1127b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_ring_mb_ring_bell(void * ctx)1128b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
1129b4c3e9b5SBjoern A. Zeeb {
1130b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
1131b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = ring->devinfo;
1132b4c3e9b5SBjoern A. Zeeb 
1133b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
1134b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1135b4c3e9b5SBjoern A. Zeeb 
1136b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "RING !\n");
1137b4c3e9b5SBjoern A. Zeeb 	/* Any arbitrary value will do, lets use 1 */
1138b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1);
1139b4c3e9b5SBjoern A. Zeeb 
1140b4c3e9b5SBjoern A. Zeeb 	return 0;
1141b4c3e9b5SBjoern A. Zeeb }
1142b4c3e9b5SBjoern A. Zeeb 
1143b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_ring_mb_update_rptr(void * ctx)1144b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
1145b4c3e9b5SBjoern A. Zeeb {
1146b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
1147b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = ring->devinfo;
1148b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring *commonring = &ring->commonring;
1149b4c3e9b5SBjoern A. Zeeb 
1150b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
1151b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1152b4c3e9b5SBjoern A. Zeeb 
1153b4c3e9b5SBjoern A. Zeeb 	commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
1154b4c3e9b5SBjoern A. Zeeb 
1155b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
1156b4c3e9b5SBjoern A. Zeeb 		  commonring->w_ptr, ring->id);
1157b4c3e9b5SBjoern A. Zeeb 
1158b4c3e9b5SBjoern A. Zeeb 	return 0;
1159b4c3e9b5SBjoern A. Zeeb }
1160b4c3e9b5SBjoern A. Zeeb 
1161b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_ring_mb_update_wptr(void * ctx)1162b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
1163b4c3e9b5SBjoern A. Zeeb {
1164b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
1165b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = ring->devinfo;
1166b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring *commonring = &ring->commonring;
1167b4c3e9b5SBjoern A. Zeeb 
1168b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
1169b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1170b4c3e9b5SBjoern A. Zeeb 
1171b4c3e9b5SBjoern A. Zeeb 	commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
1172b4c3e9b5SBjoern A. Zeeb 
1173b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
1174b4c3e9b5SBjoern A. Zeeb 		  commonring->r_ptr, ring->id);
1175b4c3e9b5SBjoern A. Zeeb 
1176b4c3e9b5SBjoern A. Zeeb 	return 0;
1177b4c3e9b5SBjoern A. Zeeb }
1178b4c3e9b5SBjoern A. Zeeb 
1179b4c3e9b5SBjoern A. Zeeb 
1180b4c3e9b5SBjoern A. Zeeb static void *
brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info * devinfo,u32 size,u32 tcm_dma_phys_addr,dma_addr_t * dma_handle)1181b4c3e9b5SBjoern A. Zeeb brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
1182b4c3e9b5SBjoern A. Zeeb 				     u32 size, u32 tcm_dma_phys_addr,
1183b4c3e9b5SBjoern A. Zeeb 				     dma_addr_t *dma_handle)
1184b4c3e9b5SBjoern A. Zeeb {
1185b4c3e9b5SBjoern A. Zeeb 	void *ring;
1186b4c3e9b5SBjoern A. Zeeb 	u64 address;
1187b4c3e9b5SBjoern A. Zeeb 
1188b4c3e9b5SBjoern A. Zeeb 	ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,
1189b4c3e9b5SBjoern A. Zeeb 				  GFP_KERNEL);
1190b4c3e9b5SBjoern A. Zeeb 	if (!ring)
1191b4c3e9b5SBjoern A. Zeeb 		return NULL;
1192b4c3e9b5SBjoern A. Zeeb 
1193b4c3e9b5SBjoern A. Zeeb 	address = (u64)*dma_handle;
1194b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,
1195b4c3e9b5SBjoern A. Zeeb 			       address & 0xffffffff);
1196b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
1197b4c3e9b5SBjoern A. Zeeb 
1198b4c3e9b5SBjoern A. Zeeb 	return (ring);
1199b4c3e9b5SBjoern A. Zeeb }
1200b4c3e9b5SBjoern A. Zeeb 
1201b4c3e9b5SBjoern A. Zeeb 
1202b4c3e9b5SBjoern A. Zeeb static struct brcmf_pcie_ringbuf *
brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info * devinfo,u32 ring_id,u32 tcm_ring_phys_addr)1203b4c3e9b5SBjoern A. Zeeb brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info *devinfo, u32 ring_id,
1204b4c3e9b5SBjoern A. Zeeb 			      u32 tcm_ring_phys_addr)
1205b4c3e9b5SBjoern A. Zeeb {
1206b4c3e9b5SBjoern A. Zeeb 	void *dma_buf;
1207b4c3e9b5SBjoern A. Zeeb 	dma_addr_t dma_handle;
1208b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring;
1209b4c3e9b5SBjoern A. Zeeb 	u32 size;
1210b4c3e9b5SBjoern A. Zeeb 	u32 addr;
1211b4c3e9b5SBjoern A. Zeeb 	const u32 *ring_itemsize_array;
1212b4c3e9b5SBjoern A. Zeeb 
1213b4c3e9b5SBjoern A. Zeeb 	if (devinfo->shared.version < BRCMF_PCIE_SHARED_VERSION_7)
1214b4c3e9b5SBjoern A. Zeeb 		ring_itemsize_array = brcmf_ring_itemsize_pre_v7;
1215b4c3e9b5SBjoern A. Zeeb 	else
1216b4c3e9b5SBjoern A. Zeeb 		ring_itemsize_array = brcmf_ring_itemsize;
1217b4c3e9b5SBjoern A. Zeeb 
1218b4c3e9b5SBjoern A. Zeeb 	size = brcmf_ring_max_item[ring_id] * ring_itemsize_array[ring_id];
1219b4c3e9b5SBjoern A. Zeeb 	dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,
1220b4c3e9b5SBjoern A. Zeeb 			tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,
1221b4c3e9b5SBjoern A. Zeeb 			&dma_handle);
1222b4c3e9b5SBjoern A. Zeeb 	if (!dma_buf)
1223b4c3e9b5SBjoern A. Zeeb 		return NULL;
1224b4c3e9b5SBjoern A. Zeeb 
1225b4c3e9b5SBjoern A. Zeeb 	addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;
1226b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);
1227b4c3e9b5SBjoern A. Zeeb 	addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;
1228b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm16(devinfo, addr, ring_itemsize_array[ring_id]);
1229b4c3e9b5SBjoern A. Zeeb 
1230b4c3e9b5SBjoern A. Zeeb 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
1231b4c3e9b5SBjoern A. Zeeb 	if (!ring) {
1232b4c3e9b5SBjoern A. Zeeb 		dma_free_coherent(&devinfo->pdev->dev, size, dma_buf,
1233b4c3e9b5SBjoern A. Zeeb 				  dma_handle);
1234b4c3e9b5SBjoern A. Zeeb 		return NULL;
1235b4c3e9b5SBjoern A. Zeeb 	}
1236b4c3e9b5SBjoern A. Zeeb 	brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],
1237b4c3e9b5SBjoern A. Zeeb 				ring_itemsize_array[ring_id], dma_buf);
1238b4c3e9b5SBjoern A. Zeeb 	ring->dma_handle = dma_handle;
1239b4c3e9b5SBjoern A. Zeeb 	ring->devinfo = devinfo;
1240b4c3e9b5SBjoern A. Zeeb 	brcmf_commonring_register_cb(&ring->commonring,
1241b4c3e9b5SBjoern A. Zeeb 				     brcmf_pcie_ring_mb_ring_bell,
1242b4c3e9b5SBjoern A. Zeeb 				     brcmf_pcie_ring_mb_update_rptr,
1243b4c3e9b5SBjoern A. Zeeb 				     brcmf_pcie_ring_mb_update_wptr,
1244b4c3e9b5SBjoern A. Zeeb 				     brcmf_pcie_ring_mb_write_rptr,
1245b4c3e9b5SBjoern A. Zeeb 				     brcmf_pcie_ring_mb_write_wptr, ring);
1246b4c3e9b5SBjoern A. Zeeb 
1247b4c3e9b5SBjoern A. Zeeb 	return (ring);
1248b4c3e9b5SBjoern A. Zeeb }
1249b4c3e9b5SBjoern A. Zeeb 
1250b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_release_ringbuffer(struct device * dev,struct brcmf_pcie_ringbuf * ring)1251b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_release_ringbuffer(struct device *dev,
1252b4c3e9b5SBjoern A. Zeeb 					  struct brcmf_pcie_ringbuf *ring)
1253b4c3e9b5SBjoern A. Zeeb {
1254b4c3e9b5SBjoern A. Zeeb 	void *dma_buf;
1255b4c3e9b5SBjoern A. Zeeb 	u32 size;
1256b4c3e9b5SBjoern A. Zeeb 
1257b4c3e9b5SBjoern A. Zeeb 	if (!ring)
1258b4c3e9b5SBjoern A. Zeeb 		return;
1259b4c3e9b5SBjoern A. Zeeb 
1260b4c3e9b5SBjoern A. Zeeb 	dma_buf = ring->commonring.buf_addr;
1261b4c3e9b5SBjoern A. Zeeb 	if (dma_buf) {
1262b4c3e9b5SBjoern A. Zeeb 		size = ring->commonring.depth * ring->commonring.item_len;
1263b4c3e9b5SBjoern A. Zeeb 		dma_free_coherent(dev, size, dma_buf, ring->dma_handle);
1264b4c3e9b5SBjoern A. Zeeb 	}
1265b4c3e9b5SBjoern A. Zeeb 	kfree(ring);
1266b4c3e9b5SBjoern A. Zeeb }
1267b4c3e9b5SBjoern A. Zeeb 
1268b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info * devinfo)1269b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
1270b4c3e9b5SBjoern A. Zeeb {
1271b4c3e9b5SBjoern A. Zeeb 	u32 i;
1272b4c3e9b5SBjoern A. Zeeb 
1273b4c3e9b5SBjoern A. Zeeb 	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
1274b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_release_ringbuffer(&devinfo->pdev->dev,
1275b4c3e9b5SBjoern A. Zeeb 					      devinfo->shared.commonrings[i]);
1276b4c3e9b5SBjoern A. Zeeb 		devinfo->shared.commonrings[i] = NULL;
1277b4c3e9b5SBjoern A. Zeeb 	}
1278b4c3e9b5SBjoern A. Zeeb 	kfree(devinfo->shared.flowrings);
1279b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.flowrings = NULL;
1280b4c3e9b5SBjoern A. Zeeb 	if (devinfo->idxbuf) {
1281b4c3e9b5SBjoern A. Zeeb 		dma_free_coherent(&devinfo->pdev->dev,
1282b4c3e9b5SBjoern A. Zeeb 				  devinfo->idxbuf_sz,
1283b4c3e9b5SBjoern A. Zeeb 				  devinfo->idxbuf,
1284b4c3e9b5SBjoern A. Zeeb 				  devinfo->idxbuf_dmahandle);
1285b4c3e9b5SBjoern A. Zeeb 		devinfo->idxbuf = NULL;
1286b4c3e9b5SBjoern A. Zeeb 	}
1287b4c3e9b5SBjoern A. Zeeb }
1288b4c3e9b5SBjoern A. Zeeb 
1289b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info * devinfo)1290b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
1291b4c3e9b5SBjoern A. Zeeb {
1292b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
1293b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *ring;
1294b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_ringbuf *rings;
1295b4c3e9b5SBjoern A. Zeeb 	u32 d2h_w_idx_ptr;
1296b4c3e9b5SBjoern A. Zeeb 	u32 d2h_r_idx_ptr;
1297b4c3e9b5SBjoern A. Zeeb 	u32 h2d_w_idx_ptr;
1298b4c3e9b5SBjoern A. Zeeb 	u32 h2d_r_idx_ptr;
1299b4c3e9b5SBjoern A. Zeeb 	u32 ring_mem_ptr;
1300b4c3e9b5SBjoern A. Zeeb 	u32 i;
1301b4c3e9b5SBjoern A. Zeeb 	u64 address;
1302b4c3e9b5SBjoern A. Zeeb 	u32 bufsz;
1303b4c3e9b5SBjoern A. Zeeb 	u8 idx_offset;
1304b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_dhi_ringinfo ringinfo;
1305b4c3e9b5SBjoern A. Zeeb 	u16 max_flowrings;
1306b4c3e9b5SBjoern A. Zeeb 	u16 max_submissionrings;
1307b4c3e9b5SBjoern A. Zeeb 	u16 max_completionrings;
1308b4c3e9b5SBjoern A. Zeeb 
1309*902136e0SBjoern A. Zeeb #if defined(__linux__)
1310b4c3e9b5SBjoern A. Zeeb 	memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr,
1311*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1312*902136e0SBjoern A. Zeeb 	memcpy_fromio(&ringinfo, (void *)((uintptr_t)devinfo->tcm + devinfo->shared.ring_info_addr),
1313*902136e0SBjoern A. Zeeb #endif
1314b4c3e9b5SBjoern A. Zeeb 		      sizeof(ringinfo));
1315b4c3e9b5SBjoern A. Zeeb 	if (devinfo->shared.version >= 6) {
1316b4c3e9b5SBjoern A. Zeeb 		max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings);
1317b4c3e9b5SBjoern A. Zeeb 		max_flowrings = le16_to_cpu(ringinfo.max_flowrings);
1318b4c3e9b5SBjoern A. Zeeb 		max_completionrings = le16_to_cpu(ringinfo.max_completionrings);
1319b4c3e9b5SBjoern A. Zeeb 	} else {
1320b4c3e9b5SBjoern A. Zeeb 		max_submissionrings = le16_to_cpu(ringinfo.max_flowrings);
1321b4c3e9b5SBjoern A. Zeeb 		max_flowrings = max_submissionrings -
1322b4c3e9b5SBjoern A. Zeeb 				BRCMF_NROF_H2D_COMMON_MSGRINGS;
1323b4c3e9b5SBjoern A. Zeeb 		max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
1324b4c3e9b5SBjoern A. Zeeb 	}
1325b4c3e9b5SBjoern A. Zeeb 	if (max_flowrings > 512) {
1326b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings);
1327b4c3e9b5SBjoern A. Zeeb 		return -EIO;
1328b4c3e9b5SBjoern A. Zeeb 	}
1329b4c3e9b5SBjoern A. Zeeb 
1330b4c3e9b5SBjoern A. Zeeb 	if (devinfo->dma_idx_sz != 0) {
1331b4c3e9b5SBjoern A. Zeeb 		bufsz = (max_submissionrings + max_completionrings) *
1332b4c3e9b5SBjoern A. Zeeb 			devinfo->dma_idx_sz * 2;
1333b4c3e9b5SBjoern A. Zeeb 		devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
1334b4c3e9b5SBjoern A. Zeeb 						     &devinfo->idxbuf_dmahandle,
1335b4c3e9b5SBjoern A. Zeeb 						     GFP_KERNEL);
1336b4c3e9b5SBjoern A. Zeeb 		if (!devinfo->idxbuf)
1337b4c3e9b5SBjoern A. Zeeb 			devinfo->dma_idx_sz = 0;
1338b4c3e9b5SBjoern A. Zeeb 	}
1339b4c3e9b5SBjoern A. Zeeb 
1340b4c3e9b5SBjoern A. Zeeb 	if (devinfo->dma_idx_sz == 0) {
1341b4c3e9b5SBjoern A. Zeeb 		d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr);
1342b4c3e9b5SBjoern A. Zeeb 		d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr);
1343b4c3e9b5SBjoern A. Zeeb 		h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr);
1344b4c3e9b5SBjoern A. Zeeb 		h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr);
1345b4c3e9b5SBjoern A. Zeeb 		idx_offset = sizeof(u32);
1346b4c3e9b5SBjoern A. Zeeb 		devinfo->write_ptr = brcmf_pcie_write_tcm16;
1347b4c3e9b5SBjoern A. Zeeb 		devinfo->read_ptr = brcmf_pcie_read_tcm16;
1348b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Using TCM indices\n");
1349b4c3e9b5SBjoern A. Zeeb 	} else {
1350b4c3e9b5SBjoern A. Zeeb 		memset(devinfo->idxbuf, 0, bufsz);
1351b4c3e9b5SBjoern A. Zeeb 		devinfo->idxbuf_sz = bufsz;
1352b4c3e9b5SBjoern A. Zeeb 		idx_offset = devinfo->dma_idx_sz;
1353b4c3e9b5SBjoern A. Zeeb 		devinfo->write_ptr = brcmf_pcie_write_idx;
1354b4c3e9b5SBjoern A. Zeeb 		devinfo->read_ptr = brcmf_pcie_read_idx;
1355b4c3e9b5SBjoern A. Zeeb 
1356b4c3e9b5SBjoern A. Zeeb 		h2d_w_idx_ptr = 0;
1357b4c3e9b5SBjoern A. Zeeb 		address = (u64)devinfo->idxbuf_dmahandle;
1358b4c3e9b5SBjoern A. Zeeb 		ringinfo.h2d_w_idx_hostaddr.low_addr =
1359b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address & 0xffffffff);
1360b4c3e9b5SBjoern A. Zeeb 		ringinfo.h2d_w_idx_hostaddr.high_addr =
1361b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address >> 32);
1362b4c3e9b5SBjoern A. Zeeb 
1363b4c3e9b5SBjoern A. Zeeb 		h2d_r_idx_ptr = h2d_w_idx_ptr +
1364b4c3e9b5SBjoern A. Zeeb 				max_submissionrings * idx_offset;
1365b4c3e9b5SBjoern A. Zeeb 		address += max_submissionrings * idx_offset;
1366b4c3e9b5SBjoern A. Zeeb 		ringinfo.h2d_r_idx_hostaddr.low_addr =
1367b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address & 0xffffffff);
1368b4c3e9b5SBjoern A. Zeeb 		ringinfo.h2d_r_idx_hostaddr.high_addr =
1369b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address >> 32);
1370b4c3e9b5SBjoern A. Zeeb 
1371b4c3e9b5SBjoern A. Zeeb 		d2h_w_idx_ptr = h2d_r_idx_ptr +
1372b4c3e9b5SBjoern A. Zeeb 				max_submissionrings * idx_offset;
1373b4c3e9b5SBjoern A. Zeeb 		address += max_submissionrings * idx_offset;
1374b4c3e9b5SBjoern A. Zeeb 		ringinfo.d2h_w_idx_hostaddr.low_addr =
1375b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address & 0xffffffff);
1376b4c3e9b5SBjoern A. Zeeb 		ringinfo.d2h_w_idx_hostaddr.high_addr =
1377b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address >> 32);
1378b4c3e9b5SBjoern A. Zeeb 
1379b4c3e9b5SBjoern A. Zeeb 		d2h_r_idx_ptr = d2h_w_idx_ptr +
1380b4c3e9b5SBjoern A. Zeeb 				max_completionrings * idx_offset;
1381b4c3e9b5SBjoern A. Zeeb 		address += max_completionrings * idx_offset;
1382b4c3e9b5SBjoern A. Zeeb 		ringinfo.d2h_r_idx_hostaddr.low_addr =
1383b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address & 0xffffffff);
1384b4c3e9b5SBjoern A. Zeeb 		ringinfo.d2h_r_idx_hostaddr.high_addr =
1385b4c3e9b5SBjoern A. Zeeb 			cpu_to_le32(address >> 32);
1386b4c3e9b5SBjoern A. Zeeb 
1387*902136e0SBjoern A. Zeeb #if defined(__linux__)
1388b4c3e9b5SBjoern A. Zeeb 		memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr,
1389*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1390*902136e0SBjoern A. Zeeb 		memcpy_toio((void *)((uintptr_t)devinfo->tcm + devinfo->shared.ring_info_addr),
1391*902136e0SBjoern A. Zeeb #endif
1392b4c3e9b5SBjoern A. Zeeb 			    &ringinfo, sizeof(ringinfo));
1393b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Using host memory indices\n");
1394b4c3e9b5SBjoern A. Zeeb 	}
1395b4c3e9b5SBjoern A. Zeeb 
1396b4c3e9b5SBjoern A. Zeeb 	ring_mem_ptr = le32_to_cpu(ringinfo.ringmem);
1397b4c3e9b5SBjoern A. Zeeb 
1398b4c3e9b5SBjoern A. Zeeb 	for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
1399b4c3e9b5SBjoern A. Zeeb 		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
1400b4c3e9b5SBjoern A. Zeeb 		if (!ring)
1401b4c3e9b5SBjoern A. Zeeb 			goto fail;
1402b4c3e9b5SBjoern A. Zeeb 		ring->w_idx_addr = h2d_w_idx_ptr;
1403b4c3e9b5SBjoern A. Zeeb 		ring->r_idx_addr = h2d_r_idx_ptr;
1404b4c3e9b5SBjoern A. Zeeb 		ring->id = i;
1405b4c3e9b5SBjoern A. Zeeb 		devinfo->shared.commonrings[i] = ring;
1406b4c3e9b5SBjoern A. Zeeb 
1407b4c3e9b5SBjoern A. Zeeb 		h2d_w_idx_ptr += idx_offset;
1408b4c3e9b5SBjoern A. Zeeb 		h2d_r_idx_ptr += idx_offset;
1409b4c3e9b5SBjoern A. Zeeb 		ring_mem_ptr += BRCMF_RING_MEM_SZ;
1410b4c3e9b5SBjoern A. Zeeb 	}
1411b4c3e9b5SBjoern A. Zeeb 
1412b4c3e9b5SBjoern A. Zeeb 	for (i = BRCMF_NROF_H2D_COMMON_MSGRINGS;
1413b4c3e9b5SBjoern A. Zeeb 	     i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
1414b4c3e9b5SBjoern A. Zeeb 		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
1415b4c3e9b5SBjoern A. Zeeb 		if (!ring)
1416b4c3e9b5SBjoern A. Zeeb 			goto fail;
1417b4c3e9b5SBjoern A. Zeeb 		ring->w_idx_addr = d2h_w_idx_ptr;
1418b4c3e9b5SBjoern A. Zeeb 		ring->r_idx_addr = d2h_r_idx_ptr;
1419b4c3e9b5SBjoern A. Zeeb 		ring->id = i;
1420b4c3e9b5SBjoern A. Zeeb 		devinfo->shared.commonrings[i] = ring;
1421b4c3e9b5SBjoern A. Zeeb 
1422b4c3e9b5SBjoern A. Zeeb 		d2h_w_idx_ptr += idx_offset;
1423b4c3e9b5SBjoern A. Zeeb 		d2h_r_idx_ptr += idx_offset;
1424b4c3e9b5SBjoern A. Zeeb 		ring_mem_ptr += BRCMF_RING_MEM_SZ;
1425b4c3e9b5SBjoern A. Zeeb 	}
1426b4c3e9b5SBjoern A. Zeeb 
1427b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.max_flowrings = max_flowrings;
1428b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.max_submissionrings = max_submissionrings;
1429b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.max_completionrings = max_completionrings;
1430b4c3e9b5SBjoern A. Zeeb 	rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL);
1431b4c3e9b5SBjoern A. Zeeb 	if (!rings)
1432b4c3e9b5SBjoern A. Zeeb 		goto fail;
1433b4c3e9b5SBjoern A. Zeeb 
1434b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings);
1435b4c3e9b5SBjoern A. Zeeb 
1436b4c3e9b5SBjoern A. Zeeb 	for (i = 0; i < max_flowrings; i++) {
1437b4c3e9b5SBjoern A. Zeeb 		ring = &rings[i];
1438b4c3e9b5SBjoern A. Zeeb 		ring->devinfo = devinfo;
1439b4c3e9b5SBjoern A. Zeeb 		ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
1440b4c3e9b5SBjoern A. Zeeb 		brcmf_commonring_register_cb(&ring->commonring,
1441b4c3e9b5SBjoern A. Zeeb 					     brcmf_pcie_ring_mb_ring_bell,
1442b4c3e9b5SBjoern A. Zeeb 					     brcmf_pcie_ring_mb_update_rptr,
1443b4c3e9b5SBjoern A. Zeeb 					     brcmf_pcie_ring_mb_update_wptr,
1444b4c3e9b5SBjoern A. Zeeb 					     brcmf_pcie_ring_mb_write_rptr,
1445b4c3e9b5SBjoern A. Zeeb 					     brcmf_pcie_ring_mb_write_wptr,
1446b4c3e9b5SBjoern A. Zeeb 					     ring);
1447b4c3e9b5SBjoern A. Zeeb 		ring->w_idx_addr = h2d_w_idx_ptr;
1448b4c3e9b5SBjoern A. Zeeb 		ring->r_idx_addr = h2d_r_idx_ptr;
1449b4c3e9b5SBjoern A. Zeeb 		h2d_w_idx_ptr += idx_offset;
1450b4c3e9b5SBjoern A. Zeeb 		h2d_r_idx_ptr += idx_offset;
1451b4c3e9b5SBjoern A. Zeeb 	}
1452b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.flowrings = rings;
1453b4c3e9b5SBjoern A. Zeeb 
1454b4c3e9b5SBjoern A. Zeeb 	return 0;
1455b4c3e9b5SBjoern A. Zeeb 
1456b4c3e9b5SBjoern A. Zeeb fail:
1457b4c3e9b5SBjoern A. Zeeb 	brcmf_err(bus, "Allocating ring buffers failed\n");
1458b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_ringbuffers(devinfo);
1459b4c3e9b5SBjoern A. Zeeb 	return -ENOMEM;
1460b4c3e9b5SBjoern A. Zeeb }
1461b4c3e9b5SBjoern A. Zeeb 
1462b4c3e9b5SBjoern A. Zeeb 
1463b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info * devinfo)1464b4c3e9b5SBjoern A. Zeeb brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
1465b4c3e9b5SBjoern A. Zeeb {
1466b4c3e9b5SBjoern A. Zeeb 	if (devinfo->shared.scratch)
1467b4c3e9b5SBjoern A. Zeeb 		dma_free_coherent(&devinfo->pdev->dev,
1468b4c3e9b5SBjoern A. Zeeb 				  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
1469b4c3e9b5SBjoern A. Zeeb 				  devinfo->shared.scratch,
1470b4c3e9b5SBjoern A. Zeeb 				  devinfo->shared.scratch_dmahandle);
1471b4c3e9b5SBjoern A. Zeeb 	if (devinfo->shared.ringupd)
1472b4c3e9b5SBjoern A. Zeeb 		dma_free_coherent(&devinfo->pdev->dev,
1473b4c3e9b5SBjoern A. Zeeb 				  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
1474b4c3e9b5SBjoern A. Zeeb 				  devinfo->shared.ringupd,
1475b4c3e9b5SBjoern A. Zeeb 				  devinfo->shared.ringupd_dmahandle);
1476b4c3e9b5SBjoern A. Zeeb }
1477b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info * devinfo)1478b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
1479b4c3e9b5SBjoern A. Zeeb {
1480b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
1481b4c3e9b5SBjoern A. Zeeb 	u64 address;
1482b4c3e9b5SBjoern A. Zeeb 	u32 addr;
1483b4c3e9b5SBjoern A. Zeeb 
1484b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.scratch =
1485b4c3e9b5SBjoern A. Zeeb 		dma_alloc_coherent(&devinfo->pdev->dev,
1486b4c3e9b5SBjoern A. Zeeb 				   BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
1487b4c3e9b5SBjoern A. Zeeb 				   &devinfo->shared.scratch_dmahandle,
1488b4c3e9b5SBjoern A. Zeeb 				   GFP_KERNEL);
1489b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->shared.scratch)
1490b4c3e9b5SBjoern A. Zeeb 		goto fail;
1491b4c3e9b5SBjoern A. Zeeb 
1492b4c3e9b5SBjoern A. Zeeb 	addr = devinfo->shared.tcm_base_address +
1493b4c3e9b5SBjoern A. Zeeb 	       BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
1494b4c3e9b5SBjoern A. Zeeb 	address = (u64)devinfo->shared.scratch_dmahandle;
1495b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
1496b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
1497b4c3e9b5SBjoern A. Zeeb 	addr = devinfo->shared.tcm_base_address +
1498b4c3e9b5SBjoern A. Zeeb 	       BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
1499b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
1500b4c3e9b5SBjoern A. Zeeb 
1501b4c3e9b5SBjoern A. Zeeb 	devinfo->shared.ringupd =
1502b4c3e9b5SBjoern A. Zeeb 		dma_alloc_coherent(&devinfo->pdev->dev,
1503b4c3e9b5SBjoern A. Zeeb 				   BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
1504b4c3e9b5SBjoern A. Zeeb 				   &devinfo->shared.ringupd_dmahandle,
1505b4c3e9b5SBjoern A. Zeeb 				   GFP_KERNEL);
1506b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->shared.ringupd)
1507b4c3e9b5SBjoern A. Zeeb 		goto fail;
1508b4c3e9b5SBjoern A. Zeeb 
1509b4c3e9b5SBjoern A. Zeeb 	addr = devinfo->shared.tcm_base_address +
1510b4c3e9b5SBjoern A. Zeeb 	       BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
1511b4c3e9b5SBjoern A. Zeeb 	address = (u64)devinfo->shared.ringupd_dmahandle;
1512b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
1513b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
1514b4c3e9b5SBjoern A. Zeeb 	addr = devinfo->shared.tcm_base_address +
1515b4c3e9b5SBjoern A. Zeeb 	       BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET;
1516b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
1517b4c3e9b5SBjoern A. Zeeb 	return 0;
1518b4c3e9b5SBjoern A. Zeeb 
1519b4c3e9b5SBjoern A. Zeeb fail:
1520b4c3e9b5SBjoern A. Zeeb 	brcmf_err(bus, "Allocating scratch buffers failed\n");
1521b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_scratchbuffers(devinfo);
1522b4c3e9b5SBjoern A. Zeeb 	return -ENOMEM;
1523b4c3e9b5SBjoern A. Zeeb }
1524b4c3e9b5SBjoern A. Zeeb 
1525b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_down(struct device * dev)1526b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_down(struct device *dev)
1527b4c3e9b5SBjoern A. Zeeb {
1528b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1529b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *pcie_bus_dev = bus_if->bus_priv.pcie;
1530b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
1531b4c3e9b5SBjoern A. Zeeb 
1532b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_fwcon_timer(devinfo, false);
1533b4c3e9b5SBjoern A. Zeeb }
1534b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_preinit(struct device * dev)1535b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_preinit(struct device *dev)
1536b4c3e9b5SBjoern A. Zeeb {
1537b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1538b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1539b4c3e9b5SBjoern A. Zeeb 
1540b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
1541b4c3e9b5SBjoern A. Zeeb 
1542b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_intr_enable(buspub->devinfo);
1543b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_hostready(buspub->devinfo);
1544b4c3e9b5SBjoern A. Zeeb 
1545b4c3e9b5SBjoern A. Zeeb 	return 0;
1546b4c3e9b5SBjoern A. Zeeb }
1547b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_tx(struct device * dev,struct sk_buff * skb)1548b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
1549b4c3e9b5SBjoern A. Zeeb {
1550b4c3e9b5SBjoern A. Zeeb 	return 0;
1551b4c3e9b5SBjoern A. Zeeb }
1552b4c3e9b5SBjoern A. Zeeb 
1553b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_tx_ctlpkt(struct device * dev,unsigned char * msg,uint len)1554b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_tx_ctlpkt(struct device *dev, unsigned char *msg,
1555b4c3e9b5SBjoern A. Zeeb 				uint len)
1556b4c3e9b5SBjoern A. Zeeb {
1557b4c3e9b5SBjoern A. Zeeb 	return 0;
1558b4c3e9b5SBjoern A. Zeeb }
1559b4c3e9b5SBjoern A. Zeeb 
1560b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_rx_ctlpkt(struct device * dev,unsigned char * msg,uint len)1561b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_rx_ctlpkt(struct device *dev, unsigned char *msg,
1562b4c3e9b5SBjoern A. Zeeb 				uint len)
1563b4c3e9b5SBjoern A. Zeeb {
1564b4c3e9b5SBjoern A. Zeeb 	return 0;
1565b4c3e9b5SBjoern A. Zeeb }
1566b4c3e9b5SBjoern A. Zeeb 
1567b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_wowl_config(struct device * dev,bool enabled)1568b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)
1569b4c3e9b5SBjoern A. Zeeb {
1570b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1571b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1572b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
1573b4c3e9b5SBjoern A. Zeeb 
1574b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);
1575b4c3e9b5SBjoern A. Zeeb 	devinfo->wowl_enabled = enabled;
1576b4c3e9b5SBjoern A. Zeeb }
1577b4c3e9b5SBjoern A. Zeeb 
1578b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_get_ramsize(struct device * dev)1579b4c3e9b5SBjoern A. Zeeb static size_t brcmf_pcie_get_ramsize(struct device *dev)
1580b4c3e9b5SBjoern A. Zeeb {
1581b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1582b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1583b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
1584b4c3e9b5SBjoern A. Zeeb 
1585b4c3e9b5SBjoern A. Zeeb 	return devinfo->ci->ramsize - devinfo->ci->srsize;
1586b4c3e9b5SBjoern A. Zeeb }
1587b4c3e9b5SBjoern A. Zeeb 
1588b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_get_memdump(struct device * dev,void * data,size_t len)1589b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
1590b4c3e9b5SBjoern A. Zeeb {
1591b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1592b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1593b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
1594b4c3e9b5SBjoern A. Zeeb 
1595b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len);
1596b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len);
1597b4c3e9b5SBjoern A. Zeeb 	return 0;
1598b4c3e9b5SBjoern A. Zeeb }
1599b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_get_blob(struct device * dev,const struct firmware ** fw,enum brcmf_blob_type type)1600b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
1601b4c3e9b5SBjoern A. Zeeb 			       enum brcmf_blob_type type)
1602b4c3e9b5SBjoern A. Zeeb {
1603b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1604b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1605b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
1606b4c3e9b5SBjoern A. Zeeb 
1607b4c3e9b5SBjoern A. Zeeb 	switch (type) {
1608b4c3e9b5SBjoern A. Zeeb 	case BRCMF_BLOB_CLM:
1609b4c3e9b5SBjoern A. Zeeb 		*fw = devinfo->clm_fw;
1610b4c3e9b5SBjoern A. Zeeb 		devinfo->clm_fw = NULL;
1611b4c3e9b5SBjoern A. Zeeb 		break;
1612b4c3e9b5SBjoern A. Zeeb 	case BRCMF_BLOB_TXCAP:
1613b4c3e9b5SBjoern A. Zeeb 		*fw = devinfo->txcap_fw;
1614b4c3e9b5SBjoern A. Zeeb 		devinfo->txcap_fw = NULL;
1615b4c3e9b5SBjoern A. Zeeb 		break;
1616b4c3e9b5SBjoern A. Zeeb 	default:
1617b4c3e9b5SBjoern A. Zeeb 		return -ENOENT;
1618b4c3e9b5SBjoern A. Zeeb 	}
1619b4c3e9b5SBjoern A. Zeeb 
1620b4c3e9b5SBjoern A. Zeeb 	if (!*fw)
1621b4c3e9b5SBjoern A. Zeeb 		return -ENOENT;
1622b4c3e9b5SBjoern A. Zeeb 
1623b4c3e9b5SBjoern A. Zeeb 	return 0;
1624b4c3e9b5SBjoern A. Zeeb }
1625b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_reset(struct device * dev)1626b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_reset(struct device *dev)
1627b4c3e9b5SBjoern A. Zeeb {
1628b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
1629b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
1630b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
1631b4c3e9b5SBjoern A. Zeeb 	struct brcmf_fw_request *fwreq;
1632b4c3e9b5SBjoern A. Zeeb 	int err;
1633b4c3e9b5SBjoern A. Zeeb 
1634b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_intr_disable(devinfo);
1635b4c3e9b5SBjoern A. Zeeb 
1636b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, true);
1637b4c3e9b5SBjoern A. Zeeb 
1638b4c3e9b5SBjoern A. Zeeb 	brcmf_detach(dev);
1639b4c3e9b5SBjoern A. Zeeb 
1640b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_irq(devinfo);
1641b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_scratchbuffers(devinfo);
1642b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_ringbuffers(devinfo);
1643b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_reset_device(devinfo);
1644b4c3e9b5SBjoern A. Zeeb 
1645b4c3e9b5SBjoern A. Zeeb 	fwreq = brcmf_pcie_prepare_fw_request(devinfo);
1646b4c3e9b5SBjoern A. Zeeb 	if (!fwreq) {
1647b4c3e9b5SBjoern A. Zeeb 		dev_err(dev, "Failed to prepare FW request\n");
1648b4c3e9b5SBjoern A. Zeeb 		return -ENOMEM;
1649b4c3e9b5SBjoern A. Zeeb 	}
1650b4c3e9b5SBjoern A. Zeeb 
1651b4c3e9b5SBjoern A. Zeeb 	err = brcmf_fw_get_firmwares(dev, fwreq, brcmf_pcie_setup);
1652b4c3e9b5SBjoern A. Zeeb 	if (err) {
1653b4c3e9b5SBjoern A. Zeeb 		dev_err(dev, "Failed to prepare FW request\n");
1654b4c3e9b5SBjoern A. Zeeb 		kfree(fwreq);
1655b4c3e9b5SBjoern A. Zeeb 	}
1656b4c3e9b5SBjoern A. Zeeb 
1657b4c3e9b5SBjoern A. Zeeb 	return err;
1658b4c3e9b5SBjoern A. Zeeb }
1659b4c3e9b5SBjoern A. Zeeb 
1660b4c3e9b5SBjoern A. Zeeb static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
1661b4c3e9b5SBjoern A. Zeeb 	.preinit = brcmf_pcie_preinit,
1662b4c3e9b5SBjoern A. Zeeb 	.txdata = brcmf_pcie_tx,
1663b4c3e9b5SBjoern A. Zeeb 	.stop = brcmf_pcie_down,
1664b4c3e9b5SBjoern A. Zeeb 	.txctl = brcmf_pcie_tx_ctlpkt,
1665b4c3e9b5SBjoern A. Zeeb 	.rxctl = brcmf_pcie_rx_ctlpkt,
1666b4c3e9b5SBjoern A. Zeeb 	.wowl_config = brcmf_pcie_wowl_config,
1667b4c3e9b5SBjoern A. Zeeb 	.get_ramsize = brcmf_pcie_get_ramsize,
1668b4c3e9b5SBjoern A. Zeeb 	.get_memdump = brcmf_pcie_get_memdump,
1669b4c3e9b5SBjoern A. Zeeb 	.get_blob = brcmf_pcie_get_blob,
1670b4c3e9b5SBjoern A. Zeeb 	.reset = brcmf_pcie_reset,
1671b4c3e9b5SBjoern A. Zeeb 	.debugfs_create = brcmf_pcie_debugfs_create,
1672b4c3e9b5SBjoern A. Zeeb };
1673b4c3e9b5SBjoern A. Zeeb 
1674b4c3e9b5SBjoern A. Zeeb 
1675b4c3e9b5SBjoern A. Zeeb static void
1676*902136e0SBjoern A. Zeeb #if defined(__linux__)
brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info * devinfo,u8 * data,u32 data_len)1677b4c3e9b5SBjoern A. Zeeb brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
1678*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1679*902136e0SBjoern A. Zeeb brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, const u8 *data,
1680*902136e0SBjoern A. Zeeb #endif
1681b4c3e9b5SBjoern A. Zeeb 			  u32 data_len)
1682b4c3e9b5SBjoern A. Zeeb {
1683*902136e0SBjoern A. Zeeb #if defined(__linux__)
1684b4c3e9b5SBjoern A. Zeeb 	__le32 *field;
1685*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1686*902136e0SBjoern A. Zeeb 	const __le32 *field;
1687*902136e0SBjoern A. Zeeb #endif
1688b4c3e9b5SBjoern A. Zeeb 	u32 newsize;
1689b4c3e9b5SBjoern A. Zeeb 
1690b4c3e9b5SBjoern A. Zeeb 	if (data_len < BRCMF_RAMSIZE_OFFSET + 8)
1691b4c3e9b5SBjoern A. Zeeb 		return;
1692b4c3e9b5SBjoern A. Zeeb 
1693*902136e0SBjoern A. Zeeb #if defined(__linux__)
1694b4c3e9b5SBjoern A. Zeeb 	field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET];
1695*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1696*902136e0SBjoern A. Zeeb 	field = (const __le32 *)&data[BRCMF_RAMSIZE_OFFSET];
1697*902136e0SBjoern A. Zeeb #endif
1698b4c3e9b5SBjoern A. Zeeb 	if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC)
1699b4c3e9b5SBjoern A. Zeeb 		return;
1700b4c3e9b5SBjoern A. Zeeb 	field++;
1701b4c3e9b5SBjoern A. Zeeb 	newsize = le32_to_cpup(field);
1702b4c3e9b5SBjoern A. Zeeb 
1703b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n",
1704b4c3e9b5SBjoern A. Zeeb 		  newsize);
1705b4c3e9b5SBjoern A. Zeeb 	devinfo->ci->ramsize = newsize;
1706b4c3e9b5SBjoern A. Zeeb }
1707b4c3e9b5SBjoern A. Zeeb 
1708b4c3e9b5SBjoern A. Zeeb 
1709b4c3e9b5SBjoern A. Zeeb static int
brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info * devinfo,u32 sharedram_addr)1710b4c3e9b5SBjoern A. Zeeb brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
1711b4c3e9b5SBjoern A. Zeeb 			       u32 sharedram_addr)
1712b4c3e9b5SBjoern A. Zeeb {
1713b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
1714b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pcie_shared_info *shared;
1715b4c3e9b5SBjoern A. Zeeb 	u32 addr;
1716b4c3e9b5SBjoern A. Zeeb 
1717b4c3e9b5SBjoern A. Zeeb 	shared = &devinfo->shared;
1718b4c3e9b5SBjoern A. Zeeb 	shared->tcm_base_address = sharedram_addr;
1719b4c3e9b5SBjoern A. Zeeb 
1720b4c3e9b5SBjoern A. Zeeb 	shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
1721b4c3e9b5SBjoern A. Zeeb 	shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK);
1722b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);
1723b4c3e9b5SBjoern A. Zeeb 	if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
1724b4c3e9b5SBjoern A. Zeeb 	    (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
1725b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Unsupported PCIE version %d\n",
1726b4c3e9b5SBjoern A. Zeeb 			  shared->version);
1727b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
1728b4c3e9b5SBjoern A. Zeeb 	}
1729b4c3e9b5SBjoern A. Zeeb 
1730b4c3e9b5SBjoern A. Zeeb 	/* check firmware support dma indicies */
1731b4c3e9b5SBjoern A. Zeeb 	if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
1732b4c3e9b5SBjoern A. Zeeb 		if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
1733b4c3e9b5SBjoern A. Zeeb 			devinfo->dma_idx_sz = sizeof(u16);
1734b4c3e9b5SBjoern A. Zeeb 		else
1735b4c3e9b5SBjoern A. Zeeb 			devinfo->dma_idx_sz = sizeof(u32);
1736b4c3e9b5SBjoern A. Zeeb 	}
1737b4c3e9b5SBjoern A. Zeeb 
1738b4c3e9b5SBjoern A. Zeeb 	addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
1739b4c3e9b5SBjoern A. Zeeb 	shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
1740b4c3e9b5SBjoern A. Zeeb 	if (shared->max_rxbufpost == 0)
1741b4c3e9b5SBjoern A. Zeeb 		shared->max_rxbufpost = BRCMF_DEF_MAX_RXBUFPOST;
1742b4c3e9b5SBjoern A. Zeeb 
1743b4c3e9b5SBjoern A. Zeeb 	addr = sharedram_addr + BRCMF_SHARED_RX_DATAOFFSET_OFFSET;
1744b4c3e9b5SBjoern A. Zeeb 	shared->rx_dataoffset = brcmf_pcie_read_tcm32(devinfo, addr);
1745b4c3e9b5SBjoern A. Zeeb 
1746b4c3e9b5SBjoern A. Zeeb 	addr = sharedram_addr + BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET;
1747b4c3e9b5SBjoern A. Zeeb 	shared->htod_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
1748b4c3e9b5SBjoern A. Zeeb 
1749b4c3e9b5SBjoern A. Zeeb 	addr = sharedram_addr + BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET;
1750b4c3e9b5SBjoern A. Zeeb 	shared->dtoh_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
1751b4c3e9b5SBjoern A. Zeeb 
1752b4c3e9b5SBjoern A. Zeeb 	addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;
1753b4c3e9b5SBjoern A. Zeeb 	shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);
1754b4c3e9b5SBjoern A. Zeeb 
1755b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",
1756b4c3e9b5SBjoern A. Zeeb 		  shared->max_rxbufpost, shared->rx_dataoffset);
1757b4c3e9b5SBjoern A. Zeeb 
1758b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_init(devinfo);
1759b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, false);
1760b4c3e9b5SBjoern A. Zeeb 
1761b4c3e9b5SBjoern A. Zeeb 	return 0;
1762b4c3e9b5SBjoern A. Zeeb }
1763b4c3e9b5SBjoern A. Zeeb 
1764b4c3e9b5SBjoern A. Zeeb struct brcmf_random_seed_footer {
1765b4c3e9b5SBjoern A. Zeeb 	__le32 length;
1766b4c3e9b5SBjoern A. Zeeb 	__le32 magic;
1767b4c3e9b5SBjoern A. Zeeb };
1768b4c3e9b5SBjoern A. Zeeb 
1769b4c3e9b5SBjoern A. Zeeb #define BRCMF_RANDOM_SEED_MAGIC		0xfeedc0de
1770b4c3e9b5SBjoern A. Zeeb #define BRCMF_RANDOM_SEED_LENGTH	0x100
1771b4c3e9b5SBjoern A. Zeeb 
1772b4c3e9b5SBjoern A. Zeeb static noinline_for_stack void
brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info * devinfo,u32 address)1773b4c3e9b5SBjoern A. Zeeb brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info *devinfo, u32 address)
1774b4c3e9b5SBjoern A. Zeeb {
1775b4c3e9b5SBjoern A. Zeeb 	u8 randbuf[BRCMF_RANDOM_SEED_LENGTH];
1776b4c3e9b5SBjoern A. Zeeb 
1777b4c3e9b5SBjoern A. Zeeb 	get_random_bytes(randbuf, BRCMF_RANDOM_SEED_LENGTH);
1778*902136e0SBjoern A. Zeeb #if defined(__linux__)
1779b4c3e9b5SBjoern A. Zeeb 	memcpy_toio(devinfo->tcm + address, randbuf, BRCMF_RANDOM_SEED_LENGTH);
1780*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1781*902136e0SBjoern A. Zeeb 	memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), randbuf, BRCMF_RANDOM_SEED_LENGTH);
1782*902136e0SBjoern A. Zeeb #endif
1783b4c3e9b5SBjoern A. Zeeb }
1784b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info * devinfo,const struct firmware * fw,void * nvram,u32 nvram_len)1785b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
1786b4c3e9b5SBjoern A. Zeeb 					const struct firmware *fw, void *nvram,
1787b4c3e9b5SBjoern A. Zeeb 					u32 nvram_len)
1788b4c3e9b5SBjoern A. Zeeb {
1789b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
1790b4c3e9b5SBjoern A. Zeeb 	u32 sharedram_addr;
1791b4c3e9b5SBjoern A. Zeeb 	u32 sharedram_addr_written;
1792b4c3e9b5SBjoern A. Zeeb 	u32 loop_counter;
1793b4c3e9b5SBjoern A. Zeeb 	int err;
1794b4c3e9b5SBjoern A. Zeeb 	u32 address;
1795b4c3e9b5SBjoern A. Zeeb 	u32 resetintr;
1796b4c3e9b5SBjoern A. Zeeb 
1797b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Halt ARM.\n");
1798b4c3e9b5SBjoern A. Zeeb 	err = brcmf_pcie_enter_download_state(devinfo);
1799b4c3e9b5SBjoern A. Zeeb 	if (err)
1800b4c3e9b5SBjoern A. Zeeb 		return err;
1801b4c3e9b5SBjoern A. Zeeb 
1802b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
1803*902136e0SBjoern A. Zeeb #if defined(__linux__)
1804b4c3e9b5SBjoern A. Zeeb 	memcpy_toio(devinfo->tcm + devinfo->ci->rambase,
1805b4c3e9b5SBjoern A. Zeeb 		    (void *)fw->data, fw->size);
1806*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1807*902136e0SBjoern A. Zeeb 	memcpy_toio((void *)((uintptr_t)devinfo->tcm + devinfo->ci->rambase),
1808*902136e0SBjoern A. Zeeb 		    fw->data, fw->size);
1809*902136e0SBjoern A. Zeeb #endif
1810b4c3e9b5SBjoern A. Zeeb 
1811b4c3e9b5SBjoern A. Zeeb 	resetintr = get_unaligned_le32(fw->data);
1812b4c3e9b5SBjoern A. Zeeb 	release_firmware(fw);
1813b4c3e9b5SBjoern A. Zeeb 
1814b4c3e9b5SBjoern A. Zeeb 	/* reset last 4 bytes of RAM address. to be used for shared
1815b4c3e9b5SBjoern A. Zeeb 	 * area. This identifies when FW is running
1816b4c3e9b5SBjoern A. Zeeb 	 */
1817b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
1818b4c3e9b5SBjoern A. Zeeb 
1819b4c3e9b5SBjoern A. Zeeb 	if (nvram) {
1820b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
1821b4c3e9b5SBjoern A. Zeeb 		address = devinfo->ci->rambase + devinfo->ci->ramsize -
1822b4c3e9b5SBjoern A. Zeeb 			  nvram_len;
1823*902136e0SBjoern A. Zeeb #if defined(__linux__)
1824b4c3e9b5SBjoern A. Zeeb 		memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
1825*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1826*902136e0SBjoern A. Zeeb 		memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), nvram, nvram_len);
1827*902136e0SBjoern A. Zeeb #endif
1828b4c3e9b5SBjoern A. Zeeb 		brcmf_fw_nvram_free(nvram);
1829b4c3e9b5SBjoern A. Zeeb 
1830b4c3e9b5SBjoern A. Zeeb 		if (devinfo->fwseed) {
1831b4c3e9b5SBjoern A. Zeeb 			size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
1832b4c3e9b5SBjoern A. Zeeb 			struct brcmf_random_seed_footer footer = {
1833b4c3e9b5SBjoern A. Zeeb 				.length = cpu_to_le32(rand_len),
1834b4c3e9b5SBjoern A. Zeeb 				.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
1835b4c3e9b5SBjoern A. Zeeb 			};
1836b4c3e9b5SBjoern A. Zeeb 
1837b4c3e9b5SBjoern A. Zeeb 			/* Some chips/firmwares expect a buffer of random
1838b4c3e9b5SBjoern A. Zeeb 			 * data to be present before NVRAM
1839b4c3e9b5SBjoern A. Zeeb 			 */
1840b4c3e9b5SBjoern A. Zeeb 			brcmf_dbg(PCIE, "Download random seed\n");
1841b4c3e9b5SBjoern A. Zeeb 
1842b4c3e9b5SBjoern A. Zeeb 			address -= sizeof(footer);
1843*902136e0SBjoern A. Zeeb #if defined(__linux__)
1844b4c3e9b5SBjoern A. Zeeb 			memcpy_toio(devinfo->tcm + address, &footer,
1845*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1846*902136e0SBjoern A. Zeeb 			memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), &footer,
1847*902136e0SBjoern A. Zeeb #endif
1848b4c3e9b5SBjoern A. Zeeb 				    sizeof(footer));
1849b4c3e9b5SBjoern A. Zeeb 
1850b4c3e9b5SBjoern A. Zeeb 			address -= rand_len;
1851b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_provide_random_bytes(devinfo, address);
1852b4c3e9b5SBjoern A. Zeeb 		}
1853b4c3e9b5SBjoern A. Zeeb 	} else {
1854b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
1855b4c3e9b5SBjoern A. Zeeb 			  devinfo->nvram_name);
1856b4c3e9b5SBjoern A. Zeeb 	}
1857b4c3e9b5SBjoern A. Zeeb 
1858b4c3e9b5SBjoern A. Zeeb 	sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
1859b4c3e9b5SBjoern A. Zeeb 						       devinfo->ci->ramsize -
1860b4c3e9b5SBjoern A. Zeeb 						       4);
1861b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Bring ARM in running state\n");
1862b4c3e9b5SBjoern A. Zeeb 	err = brcmf_pcie_exit_download_state(devinfo, resetintr);
1863b4c3e9b5SBjoern A. Zeeb 	if (err)
1864b4c3e9b5SBjoern A. Zeeb 		return err;
1865b4c3e9b5SBjoern A. Zeeb 
1866b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Wait for FW init\n");
1867b4c3e9b5SBjoern A. Zeeb 	sharedram_addr = sharedram_addr_written;
1868b4c3e9b5SBjoern A. Zeeb 	loop_counter = BRCMF_PCIE_FW_UP_TIMEOUT / 50;
1869b4c3e9b5SBjoern A. Zeeb 	while ((sharedram_addr == sharedram_addr_written) && (loop_counter)) {
1870*902136e0SBjoern A. Zeeb #if defined(__linux__)
1871b4c3e9b5SBjoern A. Zeeb 		msleep(50);
1872*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
1873*902136e0SBjoern A. Zeeb 		linux_msleep(50);
1874*902136e0SBjoern A. Zeeb #endif
1875b4c3e9b5SBjoern A. Zeeb 		sharedram_addr = brcmf_pcie_read_ram32(devinfo,
1876b4c3e9b5SBjoern A. Zeeb 						       devinfo->ci->ramsize -
1877b4c3e9b5SBjoern A. Zeeb 						       4);
1878b4c3e9b5SBjoern A. Zeeb 		loop_counter--;
1879b4c3e9b5SBjoern A. Zeeb 	}
1880b4c3e9b5SBjoern A. Zeeb 	if (sharedram_addr == sharedram_addr_written) {
1881b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "FW failed to initialize\n");
1882b4c3e9b5SBjoern A. Zeeb 		return -ENODEV;
1883b4c3e9b5SBjoern A. Zeeb 	}
1884b4c3e9b5SBjoern A. Zeeb 	if (sharedram_addr < devinfo->ci->rambase ||
1885b4c3e9b5SBjoern A. Zeeb 	    sharedram_addr >= devinfo->ci->rambase + devinfo->ci->ramsize) {
1886b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Invalid shared RAM address 0x%08x\n",
1887b4c3e9b5SBjoern A. Zeeb 			  sharedram_addr);
1888b4c3e9b5SBjoern A. Zeeb 		return -ENODEV;
1889b4c3e9b5SBjoern A. Zeeb 	}
1890b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);
1891b4c3e9b5SBjoern A. Zeeb 
1892b4c3e9b5SBjoern A. Zeeb 	return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr));
1893b4c3e9b5SBjoern A. Zeeb }
1894b4c3e9b5SBjoern A. Zeeb 
1895b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_get_resource(struct brcmf_pciedev_info * devinfo)1896b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
1897b4c3e9b5SBjoern A. Zeeb {
1898b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev = devinfo->pdev;
1899b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
1900b4c3e9b5SBjoern A. Zeeb 	int err;
1901b4c3e9b5SBjoern A. Zeeb 	phys_addr_t  bar0_addr, bar1_addr;
1902b4c3e9b5SBjoern A. Zeeb 	ulong bar1_size;
1903b4c3e9b5SBjoern A. Zeeb 
1904b4c3e9b5SBjoern A. Zeeb 	err = pci_enable_device(pdev);
1905b4c3e9b5SBjoern A. Zeeb 	if (err) {
1906b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "pci_enable_device failed err=%d\n", err);
1907b4c3e9b5SBjoern A. Zeeb 		return err;
1908b4c3e9b5SBjoern A. Zeeb 	}
1909b4c3e9b5SBjoern A. Zeeb 
1910b4c3e9b5SBjoern A. Zeeb 	pci_set_master(pdev);
1911b4c3e9b5SBjoern A. Zeeb 
1912b4c3e9b5SBjoern A. Zeeb 	/* Bar-0 mapped address */
1913b4c3e9b5SBjoern A. Zeeb 	bar0_addr = pci_resource_start(pdev, 0);
1914b4c3e9b5SBjoern A. Zeeb 	/* Bar-1 mapped address */
1915b4c3e9b5SBjoern A. Zeeb 	bar1_addr = pci_resource_start(pdev, 2);
1916b4c3e9b5SBjoern A. Zeeb 	/* read Bar-1 mapped memory range */
1917b4c3e9b5SBjoern A. Zeeb 	bar1_size = pci_resource_len(pdev, 2);
1918b4c3e9b5SBjoern A. Zeeb 	if ((bar1_size == 0) || (bar1_addr == 0)) {
1919b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
1920b4c3e9b5SBjoern A. Zeeb 			  bar1_size, (unsigned long long)bar1_addr);
1921b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
1922b4c3e9b5SBjoern A. Zeeb 	}
1923b4c3e9b5SBjoern A. Zeeb 
1924b4c3e9b5SBjoern A. Zeeb 	devinfo->regs = ioremap(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
1925b4c3e9b5SBjoern A. Zeeb 	devinfo->tcm = ioremap(bar1_addr, bar1_size);
1926b4c3e9b5SBjoern A. Zeeb 
1927b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->regs || !devinfo->tcm) {
1928b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "ioremap() failed (%p,%p)\n", devinfo->regs,
1929b4c3e9b5SBjoern A. Zeeb 			  devinfo->tcm);
1930b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
1931b4c3e9b5SBjoern A. Zeeb 	}
1932b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
1933b4c3e9b5SBjoern A. Zeeb 		  devinfo->regs, (unsigned long long)bar0_addr);
1934b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n",
1935b4c3e9b5SBjoern A. Zeeb 		  devinfo->tcm, (unsigned long long)bar1_addr,
1936b4c3e9b5SBjoern A. Zeeb 		  (unsigned int)bar1_size);
1937b4c3e9b5SBjoern A. Zeeb 
1938b4c3e9b5SBjoern A. Zeeb 	return 0;
1939b4c3e9b5SBjoern A. Zeeb }
1940b4c3e9b5SBjoern A. Zeeb 
1941b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_release_resource(struct brcmf_pciedev_info * devinfo)1942b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
1943b4c3e9b5SBjoern A. Zeeb {
1944b4c3e9b5SBjoern A. Zeeb 	if (devinfo->tcm)
1945b4c3e9b5SBjoern A. Zeeb 		iounmap(devinfo->tcm);
1946b4c3e9b5SBjoern A. Zeeb 	if (devinfo->regs)
1947b4c3e9b5SBjoern A. Zeeb 		iounmap(devinfo->regs);
1948b4c3e9b5SBjoern A. Zeeb 
1949b4c3e9b5SBjoern A. Zeeb 	pci_disable_device(devinfo->pdev);
1950b4c3e9b5SBjoern A. Zeeb }
1951b4c3e9b5SBjoern A. Zeeb 
1952b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscore_prep_addr(const struct pci_dev * pdev,u32 addr)1953b4c3e9b5SBjoern A. Zeeb static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
1954b4c3e9b5SBjoern A. Zeeb {
1955b4c3e9b5SBjoern A. Zeeb 	u32 ret_addr;
1956b4c3e9b5SBjoern A. Zeeb 
1957b4c3e9b5SBjoern A. Zeeb 	ret_addr = addr & (BRCMF_PCIE_BAR0_REG_SIZE - 1);
1958b4c3e9b5SBjoern A. Zeeb 	addr &= ~(BRCMF_PCIE_BAR0_REG_SIZE - 1);
1959b4c3e9b5SBjoern A. Zeeb 	pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, addr);
1960b4c3e9b5SBjoern A. Zeeb 
1961b4c3e9b5SBjoern A. Zeeb 	return ret_addr;
1962b4c3e9b5SBjoern A. Zeeb }
1963b4c3e9b5SBjoern A. Zeeb 
1964b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscore_read32(void * ctx,u32 addr)1965b4c3e9b5SBjoern A. Zeeb static u32 brcmf_pcie_buscore_read32(void *ctx, u32 addr)
1966b4c3e9b5SBjoern A. Zeeb {
1967b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
1968b4c3e9b5SBjoern A. Zeeb 
1969b4c3e9b5SBjoern A. Zeeb 	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
1970b4c3e9b5SBjoern A. Zeeb 	return brcmf_pcie_read_reg32(devinfo, addr);
1971b4c3e9b5SBjoern A. Zeeb }
1972b4c3e9b5SBjoern A. Zeeb 
1973b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscore_write32(void * ctx,u32 addr,u32 value)1974b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
1975b4c3e9b5SBjoern A. Zeeb {
1976b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
1977b4c3e9b5SBjoern A. Zeeb 
1978b4c3e9b5SBjoern A. Zeeb 	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
1979b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_reg32(devinfo, addr, value);
1980b4c3e9b5SBjoern A. Zeeb }
1981b4c3e9b5SBjoern A. Zeeb 
1982b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscoreprep(void * ctx)1983b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_buscoreprep(void *ctx)
1984b4c3e9b5SBjoern A. Zeeb {
1985b4c3e9b5SBjoern A. Zeeb 	return brcmf_pcie_get_resource(ctx);
1986b4c3e9b5SBjoern A. Zeeb }
1987b4c3e9b5SBjoern A. Zeeb 
1988b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscore_reset(void * ctx,struct brcmf_chip * chip)1989b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
1990b4c3e9b5SBjoern A. Zeeb {
1991b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
1992b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
1993b4c3e9b5SBjoern A. Zeeb 	u32 val, reg;
1994b4c3e9b5SBjoern A. Zeeb 
1995b4c3e9b5SBjoern A. Zeeb 	devinfo->ci = chip;
1996b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_reset_device(devinfo);
1997b4c3e9b5SBjoern A. Zeeb 
1998b4c3e9b5SBjoern A. Zeeb 	/* reginfo is not ready yet */
1999b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2);
2000b4c3e9b5SBjoern A. Zeeb 	if (core->rev >= 64)
2001b4c3e9b5SBjoern A. Zeeb 		reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;
2002b4c3e9b5SBjoern A. Zeeb 	else
2003b4c3e9b5SBjoern A. Zeeb 		reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
2004b4c3e9b5SBjoern A. Zeeb 
2005b4c3e9b5SBjoern A. Zeeb 	val = brcmf_pcie_read_reg32(devinfo, reg);
2006b4c3e9b5SBjoern A. Zeeb 	if (val != 0xffffffff)
2007b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_write_reg32(devinfo, reg, val);
2008b4c3e9b5SBjoern A. Zeeb 
2009b4c3e9b5SBjoern A. Zeeb 	return 0;
2010b4c3e9b5SBjoern A. Zeeb }
2011b4c3e9b5SBjoern A. Zeeb 
2012b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_buscore_activate(void * ctx,struct brcmf_chip * chip,u32 rstvec)2013b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
2014b4c3e9b5SBjoern A. Zeeb 					u32 rstvec)
2015b4c3e9b5SBjoern A. Zeeb {
2016b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
2017b4c3e9b5SBjoern A. Zeeb 
2018b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_write_tcm32(devinfo, 0, rstvec);
2019b4c3e9b5SBjoern A. Zeeb }
2020b4c3e9b5SBjoern A. Zeeb 
2021b4c3e9b5SBjoern A. Zeeb 
2022b4c3e9b5SBjoern A. Zeeb static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
2023b4c3e9b5SBjoern A. Zeeb 	.prepare = brcmf_pcie_buscoreprep,
2024b4c3e9b5SBjoern A. Zeeb 	.reset = brcmf_pcie_buscore_reset,
2025b4c3e9b5SBjoern A. Zeeb 	.activate = brcmf_pcie_buscore_activate,
2026b4c3e9b5SBjoern A. Zeeb 	.read32 = brcmf_pcie_buscore_read32,
2027b4c3e9b5SBjoern A. Zeeb 	.write32 = brcmf_pcie_buscore_write32,
2028b4c3e9b5SBjoern A. Zeeb };
2029b4c3e9b5SBjoern A. Zeeb 
2030b4c3e9b5SBjoern A. Zeeb #define BRCMF_OTP_SYS_VENDOR	0x15
2031b4c3e9b5SBjoern A. Zeeb #define BRCMF_OTP_BRCM_CIS	0x80
2032b4c3e9b5SBjoern A. Zeeb 
2033b4c3e9b5SBjoern A. Zeeb #define BRCMF_OTP_VENDOR_HDR	0x00000008
2034b4c3e9b5SBjoern A. Zeeb 
2035b4c3e9b5SBjoern A. Zeeb static int
brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info * devinfo,u8 * data,size_t size)2036b4c3e9b5SBjoern A. Zeeb brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo,
2037b4c3e9b5SBjoern A. Zeeb 				u8 *data, size_t size)
2038b4c3e9b5SBjoern A. Zeeb {
2039b4c3e9b5SBjoern A. Zeeb 	int idx = 4;
2040b4c3e9b5SBjoern A. Zeeb 	const char *chip_params;
2041b4c3e9b5SBjoern A. Zeeb 	const char *board_params;
2042b4c3e9b5SBjoern A. Zeeb 	const char *p;
2043b4c3e9b5SBjoern A. Zeeb 
2044b4c3e9b5SBjoern A. Zeeb 	/* 4-byte header and two empty strings */
2045b4c3e9b5SBjoern A. Zeeb 	if (size < 6)
2046b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2047b4c3e9b5SBjoern A. Zeeb 
2048b4c3e9b5SBjoern A. Zeeb 	if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR)
2049b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2050b4c3e9b5SBjoern A. Zeeb 
2051b4c3e9b5SBjoern A. Zeeb 	chip_params = &data[idx];
2052b4c3e9b5SBjoern A. Zeeb 
2053b4c3e9b5SBjoern A. Zeeb 	/* Skip first string, including terminator */
2054b4c3e9b5SBjoern A. Zeeb 	idx += strnlen(chip_params, size - idx) + 1;
2055b4c3e9b5SBjoern A. Zeeb 	if (idx >= size)
2056b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2057b4c3e9b5SBjoern A. Zeeb 
2058b4c3e9b5SBjoern A. Zeeb 	board_params = &data[idx];
2059b4c3e9b5SBjoern A. Zeeb 
2060b4c3e9b5SBjoern A. Zeeb 	/* Skip to terminator of second string */
2061b4c3e9b5SBjoern A. Zeeb 	idx += strnlen(board_params, size - idx);
2062b4c3e9b5SBjoern A. Zeeb 	if (idx >= size)
2063b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2064b4c3e9b5SBjoern A. Zeeb 
2065b4c3e9b5SBjoern A. Zeeb 	/* At this point both strings are guaranteed NUL-terminated */
2066b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "OTP: chip_params='%s' board_params='%s'\n",
2067b4c3e9b5SBjoern A. Zeeb 		  chip_params, board_params);
2068b4c3e9b5SBjoern A. Zeeb 
2069b4c3e9b5SBjoern A. Zeeb 	p = skip_spaces(board_params);
2070b4c3e9b5SBjoern A. Zeeb 	while (*p) {
2071b4c3e9b5SBjoern A. Zeeb 		char tag = *p++;
2072b4c3e9b5SBjoern A. Zeeb 		const char *end;
2073b4c3e9b5SBjoern A. Zeeb 		size_t len;
2074b4c3e9b5SBjoern A. Zeeb 
2075b4c3e9b5SBjoern A. Zeeb 		if (*p++ != '=') /* implicit NUL check */
2076b4c3e9b5SBjoern A. Zeeb 			return -EINVAL;
2077b4c3e9b5SBjoern A. Zeeb 
2078b4c3e9b5SBjoern A. Zeeb 		/* *p might be NUL here, if so end == p and len == 0 */
2079b4c3e9b5SBjoern A. Zeeb 		end = strchrnul(p, ' ');
2080b4c3e9b5SBjoern A. Zeeb 		len = end - p;
2081b4c3e9b5SBjoern A. Zeeb 
2082b4c3e9b5SBjoern A. Zeeb 		/* leave 1 byte for NUL in destination string */
2083b4c3e9b5SBjoern A. Zeeb 		if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1))
2084b4c3e9b5SBjoern A. Zeeb 			return -EINVAL;
2085b4c3e9b5SBjoern A. Zeeb 
2086b4c3e9b5SBjoern A. Zeeb 		/* Copy len characters plus a NUL terminator */
2087b4c3e9b5SBjoern A. Zeeb 		switch (tag) {
2088b4c3e9b5SBjoern A. Zeeb 		case 'M':
2089b4c3e9b5SBjoern A. Zeeb 			strscpy(devinfo->otp.module, p, len + 1);
2090b4c3e9b5SBjoern A. Zeeb 			break;
2091b4c3e9b5SBjoern A. Zeeb 		case 'V':
2092b4c3e9b5SBjoern A. Zeeb 			strscpy(devinfo->otp.vendor, p, len + 1);
2093b4c3e9b5SBjoern A. Zeeb 			break;
2094b4c3e9b5SBjoern A. Zeeb 		case 'm':
2095b4c3e9b5SBjoern A. Zeeb 			strscpy(devinfo->otp.version, p, len + 1);
2096b4c3e9b5SBjoern A. Zeeb 			break;
2097b4c3e9b5SBjoern A. Zeeb 		}
2098b4c3e9b5SBjoern A. Zeeb 
2099b4c3e9b5SBjoern A. Zeeb 		/* Skip to next arg, if any */
2100b4c3e9b5SBjoern A. Zeeb 		p = skip_spaces(end);
2101b4c3e9b5SBjoern A. Zeeb 	}
2102b4c3e9b5SBjoern A. Zeeb 
2103b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n",
2104b4c3e9b5SBjoern A. Zeeb 		  devinfo->otp.module, devinfo->otp.vendor,
2105b4c3e9b5SBjoern A. Zeeb 		  devinfo->otp.version);
2106b4c3e9b5SBjoern A. Zeeb 
2107b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->otp.module[0] ||
2108b4c3e9b5SBjoern A. Zeeb 	    !devinfo->otp.vendor[0] ||
2109b4c3e9b5SBjoern A. Zeeb 	    !devinfo->otp.version[0])
2110b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2111b4c3e9b5SBjoern A. Zeeb 
2112b4c3e9b5SBjoern A. Zeeb 	devinfo->otp.valid = true;
2113b4c3e9b5SBjoern A. Zeeb 	return 0;
2114b4c3e9b5SBjoern A. Zeeb }
2115b4c3e9b5SBjoern A. Zeeb 
2116b4c3e9b5SBjoern A. Zeeb static int
brcmf_pcie_parse_otp(struct brcmf_pciedev_info * devinfo,u8 * otp,size_t size)2117b4c3e9b5SBjoern A. Zeeb brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size)
2118b4c3e9b5SBjoern A. Zeeb {
2119b4c3e9b5SBjoern A. Zeeb 	int p = 0;
2120b4c3e9b5SBjoern A. Zeeb 	int ret = -EINVAL;
2121b4c3e9b5SBjoern A. Zeeb 
2122b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "parse_otp size=%zd\n", size);
2123b4c3e9b5SBjoern A. Zeeb 
2124b4c3e9b5SBjoern A. Zeeb 	while (p < (size - 1)) {
2125b4c3e9b5SBjoern A. Zeeb 		u8 type = otp[p];
2126b4c3e9b5SBjoern A. Zeeb 		u8 length = otp[p + 1];
2127b4c3e9b5SBjoern A. Zeeb 
2128b4c3e9b5SBjoern A. Zeeb 		if (type == 0)
2129b4c3e9b5SBjoern A. Zeeb 			break;
2130b4c3e9b5SBjoern A. Zeeb 
2131b4c3e9b5SBjoern A. Zeeb 		if ((p + 2 + length) > size)
2132b4c3e9b5SBjoern A. Zeeb 			break;
2133b4c3e9b5SBjoern A. Zeeb 
2134b4c3e9b5SBjoern A. Zeeb 		switch (type) {
2135b4c3e9b5SBjoern A. Zeeb 		case BRCMF_OTP_SYS_VENDOR:
2136b4c3e9b5SBjoern A. Zeeb 			brcmf_dbg(PCIE, "OTP @ 0x%x (%d): SYS_VENDOR\n",
2137b4c3e9b5SBjoern A. Zeeb 				  p, length);
2138b4c3e9b5SBjoern A. Zeeb 			ret = brcmf_pcie_parse_otp_sys_vendor(devinfo,
2139b4c3e9b5SBjoern A. Zeeb 							      &otp[p + 2],
2140b4c3e9b5SBjoern A. Zeeb 							      length);
2141b4c3e9b5SBjoern A. Zeeb 			break;
2142b4c3e9b5SBjoern A. Zeeb 		case BRCMF_OTP_BRCM_CIS:
2143b4c3e9b5SBjoern A. Zeeb 			brcmf_dbg(PCIE, "OTP @ 0x%x (%d): BRCM_CIS\n",
2144b4c3e9b5SBjoern A. Zeeb 				  p, length);
2145b4c3e9b5SBjoern A. Zeeb 			break;
2146b4c3e9b5SBjoern A. Zeeb 		default:
2147b4c3e9b5SBjoern A. Zeeb 			brcmf_dbg(PCIE, "OTP @ 0x%x (%d): Unknown type 0x%x\n",
2148b4c3e9b5SBjoern A. Zeeb 				  p, length, type);
2149b4c3e9b5SBjoern A. Zeeb 			break;
2150b4c3e9b5SBjoern A. Zeeb 		}
2151b4c3e9b5SBjoern A. Zeeb 
2152b4c3e9b5SBjoern A. Zeeb 		p += 2 + length;
2153b4c3e9b5SBjoern A. Zeeb 	}
2154b4c3e9b5SBjoern A. Zeeb 
2155b4c3e9b5SBjoern A. Zeeb 	return ret;
2156b4c3e9b5SBjoern A. Zeeb }
2157b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_read_otp(struct brcmf_pciedev_info * devinfo)2158b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
2159b4c3e9b5SBjoern A. Zeeb {
2160b4c3e9b5SBjoern A. Zeeb 	const struct pci_dev *pdev = devinfo->pdev;
2161b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
2162b4c3e9b5SBjoern A. Zeeb 	u32 coreid, base, words, idx, sromctl;
2163b4c3e9b5SBjoern A. Zeeb 	u16 *otp;
2164b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
2165b4c3e9b5SBjoern A. Zeeb 	int ret;
2166b4c3e9b5SBjoern A. Zeeb 
2167b4c3e9b5SBjoern A. Zeeb 	switch (devinfo->ci->chip) {
2168b4c3e9b5SBjoern A. Zeeb 	case BRCM_CC_4355_CHIP_ID:
2169b4c3e9b5SBjoern A. Zeeb 		coreid = BCMA_CORE_CHIPCOMMON;
2170b4c3e9b5SBjoern A. Zeeb 		base = 0x8c0;
2171b4c3e9b5SBjoern A. Zeeb 		words = 0xb2;
2172b4c3e9b5SBjoern A. Zeeb 		break;
2173b4c3e9b5SBjoern A. Zeeb 	case BRCM_CC_4364_CHIP_ID:
2174b4c3e9b5SBjoern A. Zeeb 		coreid = BCMA_CORE_CHIPCOMMON;
2175b4c3e9b5SBjoern A. Zeeb 		base = 0x8c0;
2176b4c3e9b5SBjoern A. Zeeb 		words = 0x1a0;
2177b4c3e9b5SBjoern A. Zeeb 		break;
2178b4c3e9b5SBjoern A. Zeeb 	case BRCM_CC_4377_CHIP_ID:
2179b4c3e9b5SBjoern A. Zeeb 	case BRCM_CC_4378_CHIP_ID:
2180b4c3e9b5SBjoern A. Zeeb 		coreid = BCMA_CORE_GCI;
2181b4c3e9b5SBjoern A. Zeeb 		base = 0x1120;
2182b4c3e9b5SBjoern A. Zeeb 		words = 0x170;
2183b4c3e9b5SBjoern A. Zeeb 		break;
2184b4c3e9b5SBjoern A. Zeeb 	case BRCM_CC_4387_CHIP_ID:
2185b4c3e9b5SBjoern A. Zeeb 		coreid = BCMA_CORE_GCI;
2186b4c3e9b5SBjoern A. Zeeb 		base = 0x113c;
2187b4c3e9b5SBjoern A. Zeeb 		words = 0x170;
2188b4c3e9b5SBjoern A. Zeeb 		break;
2189b4c3e9b5SBjoern A. Zeeb 	default:
2190b4c3e9b5SBjoern A. Zeeb 		/* OTP not supported on this chip */
2191b4c3e9b5SBjoern A. Zeeb 		return 0;
2192b4c3e9b5SBjoern A. Zeeb 	}
2193b4c3e9b5SBjoern A. Zeeb 
2194b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(devinfo->ci, coreid);
2195b4c3e9b5SBjoern A. Zeeb 	if (!core) {
2196b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "No OTP core\n");
2197b4c3e9b5SBjoern A. Zeeb 		return -ENODEV;
2198b4c3e9b5SBjoern A. Zeeb 	}
2199b4c3e9b5SBjoern A. Zeeb 
2200b4c3e9b5SBjoern A. Zeeb 	if (coreid == BCMA_CORE_CHIPCOMMON) {
2201b4c3e9b5SBjoern A. Zeeb 		/* Chips with OTP accessed via ChipCommon need additional
2202b4c3e9b5SBjoern A. Zeeb 		 * handling to access the OTP
2203b4c3e9b5SBjoern A. Zeeb 		 */
2204b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_select_core(devinfo, coreid);
2205b4c3e9b5SBjoern A. Zeeb 		sromctl = READCC32(devinfo, sromcontrol);
2206b4c3e9b5SBjoern A. Zeeb 
2207b4c3e9b5SBjoern A. Zeeb 		if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) {
2208b4c3e9b5SBjoern A. Zeeb 			/* Chip lacks OTP, try without it... */
2209b4c3e9b5SBjoern A. Zeeb 			brcmf_err(bus,
2210b4c3e9b5SBjoern A. Zeeb 				  "OTP unavailable, using default firmware\n");
2211b4c3e9b5SBjoern A. Zeeb 			return 0;
2212b4c3e9b5SBjoern A. Zeeb 		}
2213b4c3e9b5SBjoern A. Zeeb 
2214b4c3e9b5SBjoern A. Zeeb 		/* Map OTP to shadow area */
2215b4c3e9b5SBjoern A. Zeeb 		WRITECC32(devinfo, sromcontrol,
2216b4c3e9b5SBjoern A. Zeeb 			  sromctl | BCMA_CC_SROM_CONTROL_OTPSEL);
2217b4c3e9b5SBjoern A. Zeeb 	}
2218b4c3e9b5SBjoern A. Zeeb 
2219b4c3e9b5SBjoern A. Zeeb 	otp = kcalloc(words, sizeof(u16), GFP_KERNEL);
2220b4c3e9b5SBjoern A. Zeeb 	if (!otp)
2221b4c3e9b5SBjoern A. Zeeb 		return -ENOMEM;
2222b4c3e9b5SBjoern A. Zeeb 
2223b4c3e9b5SBjoern A. Zeeb 	/* Map bus window to SROM/OTP shadow area in core */
2224b4c3e9b5SBjoern A. Zeeb 	base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base);
2225b4c3e9b5SBjoern A. Zeeb 
2226b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "OTP data:\n");
2227b4c3e9b5SBjoern A. Zeeb 	for (idx = 0; idx < words; idx++) {
2228b4c3e9b5SBjoern A. Zeeb 		otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx);
2229b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]);
2230b4c3e9b5SBjoern A. Zeeb 	}
2231b4c3e9b5SBjoern A. Zeeb 
2232b4c3e9b5SBjoern A. Zeeb 	if (coreid == BCMA_CORE_CHIPCOMMON) {
2233b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_select_core(devinfo, coreid);
2234b4c3e9b5SBjoern A. Zeeb 		WRITECC32(devinfo, sromcontrol, sromctl);
2235b4c3e9b5SBjoern A. Zeeb 	}
2236b4c3e9b5SBjoern A. Zeeb 
2237b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words);
2238b4c3e9b5SBjoern A. Zeeb 	kfree(otp);
2239b4c3e9b5SBjoern A. Zeeb 
2240b4c3e9b5SBjoern A. Zeeb 	return ret;
2241b4c3e9b5SBjoern A. Zeeb }
2242b4c3e9b5SBjoern A. Zeeb 
2243b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FW_CODE	0
2244b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FW_NVRAM	1
2245b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FW_CLM	2
2246b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_FW_TXCAP	3
2247b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_setup(struct device * dev,int ret,struct brcmf_fw_request * fwreq)2248b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_setup(struct device *dev, int ret,
2249b4c3e9b5SBjoern A. Zeeb 			     struct brcmf_fw_request *fwreq)
2250b4c3e9b5SBjoern A. Zeeb {
2251b4c3e9b5SBjoern A. Zeeb 	const struct firmware *fw;
2252b4c3e9b5SBjoern A. Zeeb 	void *nvram;
2253b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus;
2254b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *pcie_bus_dev;
2255b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
2256b4c3e9b5SBjoern A. Zeeb 	struct brcmf_commonring **flowrings;
2257b4c3e9b5SBjoern A. Zeeb 	u32 i, nvram_len;
2258b4c3e9b5SBjoern A. Zeeb 
2259b4c3e9b5SBjoern A. Zeeb 	bus = dev_get_drvdata(dev);
2260b4c3e9b5SBjoern A. Zeeb 	pcie_bus_dev = bus->bus_priv.pcie;
2261b4c3e9b5SBjoern A. Zeeb 	devinfo = pcie_bus_dev->devinfo;
2262b4c3e9b5SBjoern A. Zeeb 
2263b4c3e9b5SBjoern A. Zeeb 	/* check firmware loading result */
2264b4c3e9b5SBjoern A. Zeeb 	if (ret)
2265b4c3e9b5SBjoern A. Zeeb 		goto fail;
2266b4c3e9b5SBjoern A. Zeeb 
2267b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_attach(devinfo);
2268b4c3e9b5SBjoern A. Zeeb 
2269b4c3e9b5SBjoern A. Zeeb 	fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
2270b4c3e9b5SBjoern A. Zeeb 	nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
2271b4c3e9b5SBjoern A. Zeeb 	nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
2272b4c3e9b5SBjoern A. Zeeb 	devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
2273b4c3e9b5SBjoern A. Zeeb 	devinfo->txcap_fw = fwreq->items[BRCMF_PCIE_FW_TXCAP].binary;
2274b4c3e9b5SBjoern A. Zeeb 	kfree(fwreq);
2275b4c3e9b5SBjoern A. Zeeb 
2276b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_chip_get_raminfo(devinfo->ci);
2277b4c3e9b5SBjoern A. Zeeb 	if (ret) {
2278b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Failed to get RAM info\n");
2279b4c3e9b5SBjoern A. Zeeb 		release_firmware(fw);
2280b4c3e9b5SBjoern A. Zeeb 		brcmf_fw_nvram_free(nvram);
2281b4c3e9b5SBjoern A. Zeeb 		goto fail;
2282b4c3e9b5SBjoern A. Zeeb 	}
2283b4c3e9b5SBjoern A. Zeeb 
2284b4c3e9b5SBjoern A. Zeeb 	/* Some of the firmwares have the size of the memory of the device
2285b4c3e9b5SBjoern A. Zeeb 	 * defined inside the firmware. This is because part of the memory in
2286b4c3e9b5SBjoern A. Zeeb 	 * the device is shared and the devision is determined by FW. Parse
2287b4c3e9b5SBjoern A. Zeeb 	 * the firmware and adjust the chip memory size now.
2288b4c3e9b5SBjoern A. Zeeb 	 */
2289*902136e0SBjoern A. Zeeb #if defined(__linux__)
2290b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size);
2291*902136e0SBjoern A. Zeeb #elif defined(__FreeBSD__)
2292*902136e0SBjoern A. Zeeb 	brcmf_pcie_adjust_ramsize(devinfo, fw->data, fw->size);
2293*902136e0SBjoern A. Zeeb #endif
2294b4c3e9b5SBjoern A. Zeeb 
2295b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
2296b4c3e9b5SBjoern A. Zeeb 	if (ret)
2297b4c3e9b5SBjoern A. Zeeb 		goto fail;
2298b4c3e9b5SBjoern A. Zeeb 
2299b4c3e9b5SBjoern A. Zeeb 	devinfo->state = BRCMFMAC_PCIE_STATE_UP;
2300b4c3e9b5SBjoern A. Zeeb 
2301b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_pcie_init_ringbuffers(devinfo);
2302b4c3e9b5SBjoern A. Zeeb 	if (ret)
2303b4c3e9b5SBjoern A. Zeeb 		goto fail;
2304b4c3e9b5SBjoern A. Zeeb 
2305b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_pcie_init_scratchbuffers(devinfo);
2306b4c3e9b5SBjoern A. Zeeb 	if (ret)
2307b4c3e9b5SBjoern A. Zeeb 		goto fail;
2308b4c3e9b5SBjoern A. Zeeb 
2309b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
2310b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_pcie_request_irq(devinfo);
2311b4c3e9b5SBjoern A. Zeeb 	if (ret)
2312b4c3e9b5SBjoern A. Zeeb 		goto fail;
2313b4c3e9b5SBjoern A. Zeeb 
2314b4c3e9b5SBjoern A. Zeeb 	/* hook the commonrings in the bus structure. */
2315b4c3e9b5SBjoern A. Zeeb 	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++)
2316b4c3e9b5SBjoern A. Zeeb 		bus->msgbuf->commonrings[i] =
2317b4c3e9b5SBjoern A. Zeeb 				&devinfo->shared.commonrings[i]->commonring;
2318b4c3e9b5SBjoern A. Zeeb 
2319b4c3e9b5SBjoern A. Zeeb 	flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings),
2320b4c3e9b5SBjoern A. Zeeb 			    GFP_KERNEL);
2321b4c3e9b5SBjoern A. Zeeb 	if (!flowrings)
2322b4c3e9b5SBjoern A. Zeeb 		goto fail;
2323b4c3e9b5SBjoern A. Zeeb 
2324b4c3e9b5SBjoern A. Zeeb 	for (i = 0; i < devinfo->shared.max_flowrings; i++)
2325b4c3e9b5SBjoern A. Zeeb 		flowrings[i] = &devinfo->shared.flowrings[i].commonring;
2326b4c3e9b5SBjoern A. Zeeb 	bus->msgbuf->flowrings = flowrings;
2327b4c3e9b5SBjoern A. Zeeb 
2328b4c3e9b5SBjoern A. Zeeb 	bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
2329b4c3e9b5SBjoern A. Zeeb 	bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
2330b4c3e9b5SBjoern A. Zeeb 	bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings;
2331b4c3e9b5SBjoern A. Zeeb 
2332b4c3e9b5SBjoern A. Zeeb 	init_waitqueue_head(&devinfo->mbdata_resp_wait);
2333b4c3e9b5SBjoern A. Zeeb 
2334b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_attach(&devinfo->pdev->dev);
2335b4c3e9b5SBjoern A. Zeeb 	if (ret)
2336b4c3e9b5SBjoern A. Zeeb 		goto fail;
2337b4c3e9b5SBjoern A. Zeeb 
2338b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, false);
2339b4c3e9b5SBjoern A. Zeeb 
2340b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_fwcon_timer(devinfo, true);
2341b4c3e9b5SBjoern A. Zeeb 
2342b4c3e9b5SBjoern A. Zeeb 	return;
2343b4c3e9b5SBjoern A. Zeeb 
2344b4c3e9b5SBjoern A. Zeeb fail:
2345b4c3e9b5SBjoern A. Zeeb 	brcmf_err(bus, "Dongle setup failed\n");
2346b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, true);
2347b4c3e9b5SBjoern A. Zeeb 	brcmf_fw_crashed(dev);
2348b4c3e9b5SBjoern A. Zeeb 	device_release_driver(dev);
2349b4c3e9b5SBjoern A. Zeeb }
2350b4c3e9b5SBjoern A. Zeeb 
2351b4c3e9b5SBjoern A. Zeeb static struct brcmf_fw_request *
brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info * devinfo)2352b4c3e9b5SBjoern A. Zeeb brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
2353b4c3e9b5SBjoern A. Zeeb {
2354b4c3e9b5SBjoern A. Zeeb 	struct brcmf_fw_request *fwreq;
2355b4c3e9b5SBjoern A. Zeeb 	struct brcmf_fw_name fwnames[] = {
2356b4c3e9b5SBjoern A. Zeeb 		{ ".bin", devinfo->fw_name },
2357b4c3e9b5SBjoern A. Zeeb 		{ ".txt", devinfo->nvram_name },
2358b4c3e9b5SBjoern A. Zeeb 		{ ".clm_blob", devinfo->clm_name },
2359b4c3e9b5SBjoern A. Zeeb 		{ ".txcap_blob", devinfo->txcap_name },
2360b4c3e9b5SBjoern A. Zeeb 	};
2361b4c3e9b5SBjoern A. Zeeb 
2362b4c3e9b5SBjoern A. Zeeb 	fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
2363b4c3e9b5SBjoern A. Zeeb 				       brcmf_pcie_fwnames,
2364b4c3e9b5SBjoern A. Zeeb 				       ARRAY_SIZE(brcmf_pcie_fwnames),
2365b4c3e9b5SBjoern A. Zeeb 				       fwnames, ARRAY_SIZE(fwnames));
2366b4c3e9b5SBjoern A. Zeeb 	if (!fwreq)
2367b4c3e9b5SBjoern A. Zeeb 		return NULL;
2368b4c3e9b5SBjoern A. Zeeb 
2369b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
2370b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
2371b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
2372b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
2373b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
2374b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_TXCAP].type = BRCMF_FW_TYPE_BINARY;
2375b4c3e9b5SBjoern A. Zeeb 	fwreq->items[BRCMF_PCIE_FW_TXCAP].flags = BRCMF_FW_REQF_OPTIONAL;
2376b4c3e9b5SBjoern A. Zeeb 	/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
2377b4c3e9b5SBjoern A. Zeeb 	fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
2378b4c3e9b5SBjoern A. Zeeb 	fwreq->bus_nr = devinfo->pdev->bus->number;
2379b4c3e9b5SBjoern A. Zeeb 
2380b4c3e9b5SBjoern A. Zeeb 	/* Apple platforms with fancy firmware/NVRAM selection */
2381b4c3e9b5SBjoern A. Zeeb 	if (devinfo->settings->board_type &&
2382b4c3e9b5SBjoern A. Zeeb 	    devinfo->settings->antenna_sku &&
2383b4c3e9b5SBjoern A. Zeeb 	    devinfo->otp.valid) {
2384b4c3e9b5SBjoern A. Zeeb 		const struct brcmf_otp_params *otp = &devinfo->otp;
2385b4c3e9b5SBjoern A. Zeeb 		struct device *dev = &devinfo->pdev->dev;
2386b4c3e9b5SBjoern A. Zeeb 		const char **bt = fwreq->board_types;
2387b4c3e9b5SBjoern A. Zeeb 
2388b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Apple board: %s\n",
2389b4c3e9b5SBjoern A. Zeeb 			  devinfo->settings->board_type);
2390b4c3e9b5SBjoern A. Zeeb 
2391b4c3e9b5SBjoern A. Zeeb 		/* Example: apple,shikoku-RASP-m-6.11-X3 */
2392b4c3e9b5SBjoern A. Zeeb 		bt[0] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s-%s",
2393b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->board_type,
2394b4c3e9b5SBjoern A. Zeeb 				       otp->module, otp->vendor, otp->version,
2395b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->antenna_sku);
2396b4c3e9b5SBjoern A. Zeeb 		bt[1] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s",
2397b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->board_type,
2398b4c3e9b5SBjoern A. Zeeb 				       otp->module, otp->vendor, otp->version);
2399b4c3e9b5SBjoern A. Zeeb 		bt[2] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s",
2400b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->board_type,
2401b4c3e9b5SBjoern A. Zeeb 				       otp->module, otp->vendor);
2402b4c3e9b5SBjoern A. Zeeb 		bt[3] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
2403b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->board_type,
2404b4c3e9b5SBjoern A. Zeeb 				       otp->module);
2405b4c3e9b5SBjoern A. Zeeb 		bt[4] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
2406b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->board_type,
2407b4c3e9b5SBjoern A. Zeeb 				       devinfo->settings->antenna_sku);
2408b4c3e9b5SBjoern A. Zeeb 		bt[5] = devinfo->settings->board_type;
2409b4c3e9b5SBjoern A. Zeeb 
2410b4c3e9b5SBjoern A. Zeeb 		if (!bt[0] || !bt[1] || !bt[2] || !bt[3] || !bt[4]) {
2411b4c3e9b5SBjoern A. Zeeb 			kfree(fwreq);
2412b4c3e9b5SBjoern A. Zeeb 			return NULL;
2413b4c3e9b5SBjoern A. Zeeb 		}
2414b4c3e9b5SBjoern A. Zeeb 	} else {
2415b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
2416b4c3e9b5SBjoern A. Zeeb 		fwreq->board_types[0] = devinfo->settings->board_type;
2417b4c3e9b5SBjoern A. Zeeb 	}
2418b4c3e9b5SBjoern A. Zeeb 
2419b4c3e9b5SBjoern A. Zeeb 	return fwreq;
2420b4c3e9b5SBjoern A. Zeeb }
2421b4c3e9b5SBjoern A. Zeeb 
2422b4c3e9b5SBjoern A. Zeeb #ifdef DEBUG
2423b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info * devinfo,bool active)2424b4c3e9b5SBjoern A. Zeeb brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active)
2425b4c3e9b5SBjoern A. Zeeb {
2426b4c3e9b5SBjoern A. Zeeb 	if (!active) {
2427b4c3e9b5SBjoern A. Zeeb 		if (devinfo->console_active) {
2428b4c3e9b5SBjoern A. Zeeb 			timer_delete_sync(&devinfo->timer);
2429b4c3e9b5SBjoern A. Zeeb 			devinfo->console_active = false;
2430b4c3e9b5SBjoern A. Zeeb 		}
2431b4c3e9b5SBjoern A. Zeeb 		return;
2432b4c3e9b5SBjoern A. Zeeb 	}
2433b4c3e9b5SBjoern A. Zeeb 
2434b4c3e9b5SBjoern A. Zeeb 	/* don't start the timer */
2435b4c3e9b5SBjoern A. Zeeb 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP ||
2436b4c3e9b5SBjoern A. Zeeb 	    !devinfo->console_interval || !BRCMF_FWCON_ON())
2437b4c3e9b5SBjoern A. Zeeb 		return;
2438b4c3e9b5SBjoern A. Zeeb 
2439b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->console_active) {
2440b4c3e9b5SBjoern A. Zeeb 		devinfo->timer.expires = jiffies + devinfo->console_interval;
2441b4c3e9b5SBjoern A. Zeeb 		add_timer(&devinfo->timer);
2442b4c3e9b5SBjoern A. Zeeb 		devinfo->console_active = true;
2443b4c3e9b5SBjoern A. Zeeb 	} else {
2444b4c3e9b5SBjoern A. Zeeb 		/* Reschedule the timer */
2445b4c3e9b5SBjoern A. Zeeb 		mod_timer(&devinfo->timer, jiffies + devinfo->console_interval);
2446b4c3e9b5SBjoern A. Zeeb 	}
2447b4c3e9b5SBjoern A. Zeeb }
2448b4c3e9b5SBjoern A. Zeeb 
2449b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_fwcon(struct timer_list * t)2450b4c3e9b5SBjoern A. Zeeb brcmf_pcie_fwcon(struct timer_list *t)
2451b4c3e9b5SBjoern A. Zeeb {
2452b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = timer_container_of(devinfo, t,
2453b4c3e9b5SBjoern A. Zeeb 								timer);
2454b4c3e9b5SBjoern A. Zeeb 
2455b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->console_active)
2456b4c3e9b5SBjoern A. Zeeb 		return;
2457b4c3e9b5SBjoern A. Zeeb 
2458b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, false);
2459b4c3e9b5SBjoern A. Zeeb 
2460b4c3e9b5SBjoern A. Zeeb 	/* Reschedule the timer if console interval is not zero */
2461b4c3e9b5SBjoern A. Zeeb 	mod_timer(&devinfo->timer, jiffies + devinfo->console_interval);
2462b4c3e9b5SBjoern A. Zeeb }
2463b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_console_interval_get(void * data,u64 * val)2464b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_console_interval_get(void *data, u64 *val)
2465b4c3e9b5SBjoern A. Zeeb {
2466b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = data;
2467b4c3e9b5SBjoern A. Zeeb 
2468b4c3e9b5SBjoern A. Zeeb 	*val = devinfo->console_interval;
2469b4c3e9b5SBjoern A. Zeeb 
2470b4c3e9b5SBjoern A. Zeeb 	return 0;
2471b4c3e9b5SBjoern A. Zeeb }
2472b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_console_interval_set(void * data,u64 val)2473b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_console_interval_set(void *data, u64 val)
2474b4c3e9b5SBjoern A. Zeeb {
2475b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = data;
2476b4c3e9b5SBjoern A. Zeeb 
2477b4c3e9b5SBjoern A. Zeeb 	if (val > MAX_CONSOLE_INTERVAL)
2478b4c3e9b5SBjoern A. Zeeb 		return -EINVAL;
2479b4c3e9b5SBjoern A. Zeeb 
2480b4c3e9b5SBjoern A. Zeeb 	devinfo->console_interval = val;
2481b4c3e9b5SBjoern A. Zeeb 
2482b4c3e9b5SBjoern A. Zeeb 	if (!val && devinfo->console_active)
2483b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_fwcon_timer(devinfo, false);
2484b4c3e9b5SBjoern A. Zeeb 	else if (val)
2485b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_fwcon_timer(devinfo, true);
2486b4c3e9b5SBjoern A. Zeeb 
2487b4c3e9b5SBjoern A. Zeeb 	return 0;
2488b4c3e9b5SBjoern A. Zeeb }
2489b4c3e9b5SBjoern A. Zeeb 
2490b4c3e9b5SBjoern A. Zeeb DEFINE_SIMPLE_ATTRIBUTE(brcmf_pcie_console_interval_fops,
2491b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_console_interval_get,
2492b4c3e9b5SBjoern A. Zeeb 			brcmf_pcie_console_interval_set,
2493b4c3e9b5SBjoern A. Zeeb 			"%llu\n");
2494b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_debugfs_create(struct device * dev)2495b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_debugfs_create(struct device *dev)
2496b4c3e9b5SBjoern A. Zeeb {
2497b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
2498b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pub *drvr = bus_if->drvr;
2499b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *pcie_bus_dev = bus_if->bus_priv.pcie;
2500b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
2501b4c3e9b5SBjoern A. Zeeb 	struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);
2502b4c3e9b5SBjoern A. Zeeb 
2503b4c3e9b5SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(dentry))
2504b4c3e9b5SBjoern A. Zeeb 		return;
2505b4c3e9b5SBjoern A. Zeeb 
2506b4c3e9b5SBjoern A. Zeeb 	devinfo->console_interval = BRCMF_CONSOLE;
2507b4c3e9b5SBjoern A. Zeeb 
2508b4c3e9b5SBjoern A. Zeeb 	debugfs_create_file("console_interval", 0644, dentry, devinfo,
2509b4c3e9b5SBjoern A. Zeeb 			    &brcmf_pcie_console_interval_fops);
2510b4c3e9b5SBjoern A. Zeeb }
2511b4c3e9b5SBjoern A. Zeeb 
2512b4c3e9b5SBjoern A. Zeeb #else
brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info * devinfo,bool active)2513b4c3e9b5SBjoern A. Zeeb void brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active)
2514b4c3e9b5SBjoern A. Zeeb {
2515b4c3e9b5SBjoern A. Zeeb }
2516b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_debugfs_create(struct device * dev)2517b4c3e9b5SBjoern A. Zeeb static void brcmf_pcie_debugfs_create(struct device *dev)
2518b4c3e9b5SBjoern A. Zeeb {
2519b4c3e9b5SBjoern A. Zeeb }
2520b4c3e9b5SBjoern A. Zeeb #endif
2521b4c3e9b5SBjoern A. Zeeb 
2522b4c3e9b5SBjoern A. Zeeb struct brcmf_pcie_drvdata {
2523b4c3e9b5SBjoern A. Zeeb 	enum brcmf_fwvendor vendor;
2524b4c3e9b5SBjoern A. Zeeb 	bool fw_seed;
2525b4c3e9b5SBjoern A. Zeeb };
2526b4c3e9b5SBjoern A. Zeeb 
2527b4c3e9b5SBjoern A. Zeeb enum {
2528b4c3e9b5SBjoern A. Zeeb 	BRCMF_DRVDATA_CYW,
2529b4c3e9b5SBjoern A. Zeeb 	BRCMF_DRVDATA_BCA,
2530b4c3e9b5SBjoern A. Zeeb 	BRCMF_DRVDATA_WCC,
2531b4c3e9b5SBjoern A. Zeeb 	BRCMF_DRVDATA_WCC_SEED,
2532b4c3e9b5SBjoern A. Zeeb };
2533b4c3e9b5SBjoern A. Zeeb 
2534b4c3e9b5SBjoern A. Zeeb static const struct brcmf_pcie_drvdata drvdata[] = {
2535b4c3e9b5SBjoern A. Zeeb 	[BRCMF_DRVDATA_CYW] = {
2536b4c3e9b5SBjoern A. Zeeb 		.vendor = BRCMF_FWVENDOR_CYW,
2537b4c3e9b5SBjoern A. Zeeb 		.fw_seed = false,
2538b4c3e9b5SBjoern A. Zeeb 	},
2539b4c3e9b5SBjoern A. Zeeb 	[BRCMF_DRVDATA_BCA] = {
2540b4c3e9b5SBjoern A. Zeeb 		.vendor = BRCMF_FWVENDOR_BCA,
2541b4c3e9b5SBjoern A. Zeeb 		.fw_seed = false,
2542b4c3e9b5SBjoern A. Zeeb 	},
2543b4c3e9b5SBjoern A. Zeeb 	[BRCMF_DRVDATA_WCC] = {
2544b4c3e9b5SBjoern A. Zeeb 		.vendor = BRCMF_FWVENDOR_WCC,
2545b4c3e9b5SBjoern A. Zeeb 		.fw_seed = false,
2546b4c3e9b5SBjoern A. Zeeb 	},
2547b4c3e9b5SBjoern A. Zeeb 	[BRCMF_DRVDATA_WCC_SEED] = {
2548b4c3e9b5SBjoern A. Zeeb 		.vendor = BRCMF_FWVENDOR_WCC,
2549b4c3e9b5SBjoern A. Zeeb 		.fw_seed = true,
2550b4c3e9b5SBjoern A. Zeeb 	},
2551b4c3e9b5SBjoern A. Zeeb };
2552b4c3e9b5SBjoern A. Zeeb 
2553b4c3e9b5SBjoern A. Zeeb /* Forward declaration for pci_match_id() call */
2554b4c3e9b5SBjoern A. Zeeb static const struct pci_device_id brcmf_pcie_devid_table[];
2555b4c3e9b5SBjoern A. Zeeb 
2556b4c3e9b5SBjoern A. Zeeb static int
brcmf_pcie_probe(struct pci_dev * pdev,const struct pci_device_id * id)2557b4c3e9b5SBjoern A. Zeeb brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2558b4c3e9b5SBjoern A. Zeeb {
2559b4c3e9b5SBjoern A. Zeeb 	int ret;
2560b4c3e9b5SBjoern A. Zeeb 	struct brcmf_fw_request *fwreq;
2561b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
2562b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev *pcie_bus_dev;
2563b4c3e9b5SBjoern A. Zeeb 	struct brcmf_core *core;
2564b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus;
2565b4c3e9b5SBjoern A. Zeeb 
2566b4c3e9b5SBjoern A. Zeeb 	if (!id) {
2567b4c3e9b5SBjoern A. Zeeb 		id = pci_match_id(brcmf_pcie_devid_table, pdev);
2568b4c3e9b5SBjoern A. Zeeb 		if (!id) {
2569b4c3e9b5SBjoern A. Zeeb 			pci_err(pdev, "Error could not find pci_device_id for %x:%x\n", pdev->vendor, pdev->device);
2570b4c3e9b5SBjoern A. Zeeb 			return -ENODEV;
2571b4c3e9b5SBjoern A. Zeeb 		}
2572b4c3e9b5SBjoern A. Zeeb 	}
2573b4c3e9b5SBjoern A. Zeeb 
2574b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
2575b4c3e9b5SBjoern A. Zeeb 
2576b4c3e9b5SBjoern A. Zeeb 	ret = -ENOMEM;
2577b4c3e9b5SBjoern A. Zeeb 	devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
2578b4c3e9b5SBjoern A. Zeeb 	if (devinfo == NULL)
2579b4c3e9b5SBjoern A. Zeeb 		return ret;
2580b4c3e9b5SBjoern A. Zeeb 
2581b4c3e9b5SBjoern A. Zeeb 	devinfo->pdev = pdev;
2582b4c3e9b5SBjoern A. Zeeb 	pcie_bus_dev = NULL;
2583b4c3e9b5SBjoern A. Zeeb 	devinfo->ci = brcmf_chip_attach(devinfo, pdev->device,
2584b4c3e9b5SBjoern A. Zeeb 					&brcmf_pcie_buscore_ops);
2585b4c3e9b5SBjoern A. Zeeb 	if (IS_ERR(devinfo->ci)) {
2586b4c3e9b5SBjoern A. Zeeb 		ret = PTR_ERR(devinfo->ci);
2587b4c3e9b5SBjoern A. Zeeb 		devinfo->ci = NULL;
2588b4c3e9b5SBjoern A. Zeeb 		goto fail;
2589b4c3e9b5SBjoern A. Zeeb 	}
2590b4c3e9b5SBjoern A. Zeeb 
2591b4c3e9b5SBjoern A. Zeeb 	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
2592b4c3e9b5SBjoern A. Zeeb 	if (core->rev >= 64)
2593b4c3e9b5SBjoern A. Zeeb 		devinfo->reginfo = &brcmf_reginfo_64;
2594b4c3e9b5SBjoern A. Zeeb 	else
2595b4c3e9b5SBjoern A. Zeeb 		devinfo->reginfo = &brcmf_reginfo_default;
2596b4c3e9b5SBjoern A. Zeeb 
2597b4c3e9b5SBjoern A. Zeeb 	pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
2598b4c3e9b5SBjoern A. Zeeb 	if (pcie_bus_dev == NULL) {
2599b4c3e9b5SBjoern A. Zeeb 		ret = -ENOMEM;
2600b4c3e9b5SBjoern A. Zeeb 		goto fail;
2601b4c3e9b5SBjoern A. Zeeb 	}
2602b4c3e9b5SBjoern A. Zeeb 
2603b4c3e9b5SBjoern A. Zeeb 	devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,
2604b4c3e9b5SBjoern A. Zeeb 						   BRCMF_BUSTYPE_PCIE,
2605b4c3e9b5SBjoern A. Zeeb 						   devinfo->ci->chip,
2606b4c3e9b5SBjoern A. Zeeb 						   devinfo->ci->chiprev);
2607b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->settings) {
2608b4c3e9b5SBjoern A. Zeeb 		ret = -ENOMEM;
2609b4c3e9b5SBjoern A. Zeeb 		goto fail;
2610b4c3e9b5SBjoern A. Zeeb 	}
2611b4c3e9b5SBjoern A. Zeeb 	ret = PTR_ERR_OR_ZERO(devinfo->settings);
2612b4c3e9b5SBjoern A. Zeeb 	if (ret < 0)
2613b4c3e9b5SBjoern A. Zeeb 		goto fail;
2614b4c3e9b5SBjoern A. Zeeb 
2615b4c3e9b5SBjoern A. Zeeb 	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
2616b4c3e9b5SBjoern A. Zeeb 	if (!bus) {
2617b4c3e9b5SBjoern A. Zeeb 		ret = -ENOMEM;
2618b4c3e9b5SBjoern A. Zeeb 		goto fail;
2619b4c3e9b5SBjoern A. Zeeb 	}
2620b4c3e9b5SBjoern A. Zeeb 	bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
2621b4c3e9b5SBjoern A. Zeeb 	if (!bus->msgbuf) {
2622b4c3e9b5SBjoern A. Zeeb 		ret = -ENOMEM;
2623b4c3e9b5SBjoern A. Zeeb 		kfree(bus);
2624b4c3e9b5SBjoern A. Zeeb 		goto fail;
2625b4c3e9b5SBjoern A. Zeeb 	}
2626b4c3e9b5SBjoern A. Zeeb 
2627b4c3e9b5SBjoern A. Zeeb 	/* hook it all together. */
2628b4c3e9b5SBjoern A. Zeeb 	pcie_bus_dev->devinfo = devinfo;
2629b4c3e9b5SBjoern A. Zeeb 	pcie_bus_dev->bus = bus;
2630b4c3e9b5SBjoern A. Zeeb 	bus->dev = &pdev->dev;
2631b4c3e9b5SBjoern A. Zeeb 	bus->bus_priv.pcie = pcie_bus_dev;
2632b4c3e9b5SBjoern A. Zeeb 	bus->ops = &brcmf_pcie_bus_ops;
2633b4c3e9b5SBjoern A. Zeeb 	bus->proto_type = BRCMF_PROTO_MSGBUF;
2634b4c3e9b5SBjoern A. Zeeb 	bus->chip = devinfo->coreid;
2635b4c3e9b5SBjoern A. Zeeb 	bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
2636b4c3e9b5SBjoern A. Zeeb 	bus->fwvid = drvdata[id->driver_data].vendor;
2637b4c3e9b5SBjoern A. Zeeb 	devinfo->fwseed = drvdata[id->driver_data].fw_seed;
2638b4c3e9b5SBjoern A. Zeeb 	dev_set_drvdata(&pdev->dev, bus);
2639b4c3e9b5SBjoern A. Zeeb 
2640b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_alloc(&devinfo->pdev->dev, devinfo->settings);
2641b4c3e9b5SBjoern A. Zeeb 	if (ret)
2642b4c3e9b5SBjoern A. Zeeb 		goto fail_bus;
2643b4c3e9b5SBjoern A. Zeeb 
2644b4c3e9b5SBjoern A. Zeeb 	/* otp read operation */
2645b4c3e9b5SBjoern A. Zeeb 	switch (bus->fwvid) {
2646b4c3e9b5SBjoern A. Zeeb 	case BRCMF_FWVENDOR_WCC:
2647b4c3e9b5SBjoern A. Zeeb 	case BRCMF_FWVENDOR_BCA:
2648b4c3e9b5SBjoern A. Zeeb 		ret = brcmf_pcie_read_otp(devinfo);
2649b4c3e9b5SBjoern A. Zeeb 		if (ret) {
2650b4c3e9b5SBjoern A. Zeeb 			brcmf_err(bus, "failed to parse OTP\n");
2651b4c3e9b5SBjoern A. Zeeb 			goto fail_brcmf;
2652b4c3e9b5SBjoern A. Zeeb 		}
2653b4c3e9b5SBjoern A. Zeeb 		break;
2654b4c3e9b5SBjoern A. Zeeb 	case BRCMF_FWVENDOR_CYW:
2655b4c3e9b5SBjoern A. Zeeb 	default:
2656b4c3e9b5SBjoern A. Zeeb 		break;
2657b4c3e9b5SBjoern A. Zeeb 	}
2658b4c3e9b5SBjoern A. Zeeb 
2659b4c3e9b5SBjoern A. Zeeb #ifdef DEBUG
2660b4c3e9b5SBjoern A. Zeeb 	/* Set up the fwcon timer */
2661b4c3e9b5SBjoern A. Zeeb 	timer_setup(&devinfo->timer, brcmf_pcie_fwcon, 0);
2662b4c3e9b5SBjoern A. Zeeb #endif
2663b4c3e9b5SBjoern A. Zeeb 
2664b4c3e9b5SBjoern A. Zeeb 	fwreq = brcmf_pcie_prepare_fw_request(devinfo);
2665b4c3e9b5SBjoern A. Zeeb 	if (!fwreq) {
2666b4c3e9b5SBjoern A. Zeeb 		ret = -ENOMEM;
2667b4c3e9b5SBjoern A. Zeeb 		goto fail_brcmf;
2668b4c3e9b5SBjoern A. Zeeb 	}
2669b4c3e9b5SBjoern A. Zeeb 
2670b4c3e9b5SBjoern A. Zeeb 	ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
2671b4c3e9b5SBjoern A. Zeeb 	if (ret < 0) {
2672b4c3e9b5SBjoern A. Zeeb 		kfree(fwreq);
2673b4c3e9b5SBjoern A. Zeeb 		goto fail_brcmf;
2674b4c3e9b5SBjoern A. Zeeb 	}
2675b4c3e9b5SBjoern A. Zeeb 	return 0;
2676b4c3e9b5SBjoern A. Zeeb 
2677b4c3e9b5SBjoern A. Zeeb fail_brcmf:
2678b4c3e9b5SBjoern A. Zeeb 	brcmf_free(&devinfo->pdev->dev);
2679b4c3e9b5SBjoern A. Zeeb fail_bus:
2680b4c3e9b5SBjoern A. Zeeb 	kfree(bus->msgbuf);
2681b4c3e9b5SBjoern A. Zeeb 	kfree(bus);
2682b4c3e9b5SBjoern A. Zeeb fail:
2683b4c3e9b5SBjoern A. Zeeb 	brcmf_err(NULL, "failed %x:%x\n", pdev->vendor, pdev->device);
2684b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_resource(devinfo);
2685b4c3e9b5SBjoern A. Zeeb 	if (devinfo->ci)
2686b4c3e9b5SBjoern A. Zeeb 		brcmf_chip_detach(devinfo->ci);
2687b4c3e9b5SBjoern A. Zeeb 	if (devinfo->settings)
2688b4c3e9b5SBjoern A. Zeeb 		brcmf_release_module_param(devinfo->settings);
2689b4c3e9b5SBjoern A. Zeeb 	kfree(pcie_bus_dev);
2690b4c3e9b5SBjoern A. Zeeb 	kfree(devinfo);
2691b4c3e9b5SBjoern A. Zeeb 	return ret;
2692b4c3e9b5SBjoern A. Zeeb }
2693b4c3e9b5SBjoern A. Zeeb 
2694b4c3e9b5SBjoern A. Zeeb 
2695b4c3e9b5SBjoern A. Zeeb static void
brcmf_pcie_remove(struct pci_dev * pdev)2696b4c3e9b5SBjoern A. Zeeb brcmf_pcie_remove(struct pci_dev *pdev)
2697b4c3e9b5SBjoern A. Zeeb {
2698b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
2699b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus;
2700b4c3e9b5SBjoern A. Zeeb 
2701b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
2702b4c3e9b5SBjoern A. Zeeb 
2703b4c3e9b5SBjoern A. Zeeb 	bus = dev_get_drvdata(&pdev->dev);
2704b4c3e9b5SBjoern A. Zeeb 	if (bus == NULL)
2705b4c3e9b5SBjoern A. Zeeb 		return;
2706b4c3e9b5SBjoern A. Zeeb 
2707b4c3e9b5SBjoern A. Zeeb 	devinfo = bus->bus_priv.pcie->devinfo;
2708b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_bus_console_read(devinfo, false);
2709b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_fwcon_timer(devinfo, false);
2710b4c3e9b5SBjoern A. Zeeb 
2711b4c3e9b5SBjoern A. Zeeb 	devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
2712b4c3e9b5SBjoern A. Zeeb 	if (devinfo->ci)
2713b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_intr_disable(devinfo);
2714b4c3e9b5SBjoern A. Zeeb 
2715b4c3e9b5SBjoern A. Zeeb 	brcmf_detach(&pdev->dev);
2716b4c3e9b5SBjoern A. Zeeb 	brcmf_free(&pdev->dev);
2717b4c3e9b5SBjoern A. Zeeb 
2718b4c3e9b5SBjoern A. Zeeb 	kfree(bus->bus_priv.pcie);
2719b4c3e9b5SBjoern A. Zeeb 	kfree(bus->msgbuf->flowrings);
2720b4c3e9b5SBjoern A. Zeeb 	kfree(bus->msgbuf);
2721b4c3e9b5SBjoern A. Zeeb 	kfree(bus);
2722b4c3e9b5SBjoern A. Zeeb 
2723b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_irq(devinfo);
2724b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_scratchbuffers(devinfo);
2725b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_ringbuffers(devinfo);
2726b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_reset_device(devinfo);
2727b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_release_resource(devinfo);
2728b4c3e9b5SBjoern A. Zeeb 	release_firmware(devinfo->clm_fw);
2729b4c3e9b5SBjoern A. Zeeb 	release_firmware(devinfo->txcap_fw);
2730b4c3e9b5SBjoern A. Zeeb 
2731b4c3e9b5SBjoern A. Zeeb 	if (devinfo->ci)
2732b4c3e9b5SBjoern A. Zeeb 		brcmf_chip_detach(devinfo->ci);
2733b4c3e9b5SBjoern A. Zeeb 	if (devinfo->settings)
2734b4c3e9b5SBjoern A. Zeeb 		brcmf_release_module_param(devinfo->settings);
2735b4c3e9b5SBjoern A. Zeeb 
2736b4c3e9b5SBjoern A. Zeeb 	kfree(devinfo);
2737b4c3e9b5SBjoern A. Zeeb 	dev_set_drvdata(&pdev->dev, NULL);
2738b4c3e9b5SBjoern A. Zeeb }
2739b4c3e9b5SBjoern A. Zeeb 
2740b4c3e9b5SBjoern A. Zeeb 
2741b4c3e9b5SBjoern A. Zeeb #ifdef CONFIG_PM
2742b4c3e9b5SBjoern A. Zeeb 
2743b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_pm_enter_D3(struct device * dev)2744b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_pm_enter_D3(struct device *dev)
2745b4c3e9b5SBjoern A. Zeeb {
2746b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
2747b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus;
2748b4c3e9b5SBjoern A. Zeeb 
2749b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
2750b4c3e9b5SBjoern A. Zeeb 
2751b4c3e9b5SBjoern A. Zeeb 	bus = dev_get_drvdata(dev);
2752b4c3e9b5SBjoern A. Zeeb 	devinfo = bus->bus_priv.pcie->devinfo;
2753b4c3e9b5SBjoern A. Zeeb 
2754b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_fwcon_timer(devinfo, false);
2755b4c3e9b5SBjoern A. Zeeb 	brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
2756b4c3e9b5SBjoern A. Zeeb 
2757b4c3e9b5SBjoern A. Zeeb 	devinfo->mbdata_completed = false;
2758b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
2759b4c3e9b5SBjoern A. Zeeb 
2760b4c3e9b5SBjoern A. Zeeb 	wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,
2761b4c3e9b5SBjoern A. Zeeb 			   BRCMF_PCIE_MBDATA_TIMEOUT);
2762b4c3e9b5SBjoern A. Zeeb 	if (!devinfo->mbdata_completed) {
2763b4c3e9b5SBjoern A. Zeeb 		brcmf_err(bus, "Timeout on response for entering D3 substate\n");
2764b4c3e9b5SBjoern A. Zeeb 		brcmf_bus_change_state(bus, BRCMF_BUS_UP);
2765b4c3e9b5SBjoern A. Zeeb 		return -EIO;
2766b4c3e9b5SBjoern A. Zeeb 	}
2767b4c3e9b5SBjoern A. Zeeb 
2768b4c3e9b5SBjoern A. Zeeb 	devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
2769b4c3e9b5SBjoern A. Zeeb 
2770b4c3e9b5SBjoern A. Zeeb 	return 0;
2771b4c3e9b5SBjoern A. Zeeb }
2772b4c3e9b5SBjoern A. Zeeb 
2773b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_pm_leave_D3(struct device * dev)2774b4c3e9b5SBjoern A. Zeeb static int brcmf_pcie_pm_leave_D3(struct device *dev)
2775b4c3e9b5SBjoern A. Zeeb {
2776b4c3e9b5SBjoern A. Zeeb 	struct brcmf_pciedev_info *devinfo;
2777b4c3e9b5SBjoern A. Zeeb 	struct brcmf_bus *bus;
2778b4c3e9b5SBjoern A. Zeeb 	struct pci_dev *pdev;
2779b4c3e9b5SBjoern A. Zeeb 	int err;
2780b4c3e9b5SBjoern A. Zeeb 
2781b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
2782b4c3e9b5SBjoern A. Zeeb 
2783b4c3e9b5SBjoern A. Zeeb 	bus = dev_get_drvdata(dev);
2784b4c3e9b5SBjoern A. Zeeb 	devinfo = bus->bus_priv.pcie->devinfo;
2785b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
2786b4c3e9b5SBjoern A. Zeeb 
2787b4c3e9b5SBjoern A. Zeeb 	/* Check if device is still up and running, if so we are ready */
2788b4c3e9b5SBjoern A. Zeeb 	if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
2789b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Try to wakeup device....\n");
2790b4c3e9b5SBjoern A. Zeeb 		if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
2791b4c3e9b5SBjoern A. Zeeb 			goto cleanup;
2792b4c3e9b5SBjoern A. Zeeb 		brcmf_dbg(PCIE, "Hot resume, continue....\n");
2793b4c3e9b5SBjoern A. Zeeb 		devinfo->state = BRCMFMAC_PCIE_STATE_UP;
2794b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
2795b4c3e9b5SBjoern A. Zeeb 		brcmf_bus_change_state(bus, BRCMF_BUS_UP);
2796b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_intr_enable(devinfo);
2797b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_hostready(devinfo);
2798b4c3e9b5SBjoern A. Zeeb 		brcmf_pcie_fwcon_timer(devinfo, true);
2799b4c3e9b5SBjoern A. Zeeb 		return 0;
2800b4c3e9b5SBjoern A. Zeeb 	}
2801b4c3e9b5SBjoern A. Zeeb 
2802b4c3e9b5SBjoern A. Zeeb cleanup:
2803b4c3e9b5SBjoern A. Zeeb 	brcmf_chip_detach(devinfo->ci);
2804b4c3e9b5SBjoern A. Zeeb 	devinfo->ci = NULL;
2805b4c3e9b5SBjoern A. Zeeb 	pdev = devinfo->pdev;
2806b4c3e9b5SBjoern A. Zeeb 	brcmf_pcie_remove(pdev);
2807b4c3e9b5SBjoern A. Zeeb 
2808b4c3e9b5SBjoern A. Zeeb 	err = brcmf_pcie_probe(pdev, NULL);
2809b4c3e9b5SBjoern A. Zeeb 	if (err)
2810b4c3e9b5SBjoern A. Zeeb 		__brcmf_err(NULL, __func__, "probe after resume failed, err=%d\n", err);
2811b4c3e9b5SBjoern A. Zeeb 
2812b4c3e9b5SBjoern A. Zeeb 	return err;
2813b4c3e9b5SBjoern A. Zeeb }
2814b4c3e9b5SBjoern A. Zeeb 
2815b4c3e9b5SBjoern A. Zeeb 
2816b4c3e9b5SBjoern A. Zeeb static const struct dev_pm_ops brcmf_pciedrvr_pm = {
2817b4c3e9b5SBjoern A. Zeeb 	.suspend = brcmf_pcie_pm_enter_D3,
2818b4c3e9b5SBjoern A. Zeeb 	.resume = brcmf_pcie_pm_leave_D3,
2819b4c3e9b5SBjoern A. Zeeb 	.freeze = brcmf_pcie_pm_enter_D3,
2820b4c3e9b5SBjoern A. Zeeb 	.restore = brcmf_pcie_pm_leave_D3,
2821b4c3e9b5SBjoern A. Zeeb };
2822b4c3e9b5SBjoern A. Zeeb 
2823b4c3e9b5SBjoern A. Zeeb 
2824b4c3e9b5SBjoern A. Zeeb #endif /* CONFIG_PM */
2825b4c3e9b5SBjoern A. Zeeb 
2826b4c3e9b5SBjoern A. Zeeb 
2827b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_DEVICE(dev_id, fw_vend) \
2828b4c3e9b5SBjoern A. Zeeb 	{ \
2829b4c3e9b5SBjoern A. Zeeb 		BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
2830b4c3e9b5SBjoern A. Zeeb 		PCI_ANY_ID, PCI_ANY_ID, \
2831b4c3e9b5SBjoern A. Zeeb 		PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
2832b4c3e9b5SBjoern A. Zeeb 		BRCMF_DRVDATA_ ## fw_vend \
2833b4c3e9b5SBjoern A. Zeeb 	}
2834b4c3e9b5SBjoern A. Zeeb #define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev, fw_vend) \
2835b4c3e9b5SBjoern A. Zeeb 	{ \
2836b4c3e9b5SBjoern A. Zeeb 		BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
2837b4c3e9b5SBjoern A. Zeeb 		(subvend), (subdev), \
2838b4c3e9b5SBjoern A. Zeeb 		PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
2839b4c3e9b5SBjoern A. Zeeb 		BRCMF_DRVDATA_ ## fw_vend \
2840b4c3e9b5SBjoern A. Zeeb 	}
2841b4c3e9b5SBjoern A. Zeeb 
2842b4c3e9b5SBjoern A. Zeeb static const struct pci_device_id brcmf_pcie_devid_table[] = {
2843b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC),
2844b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC),
2845b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC),
2846b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC_SEED),
2847b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC),
2848b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC),
2849b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC),
2850b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_RAW_DEVICE_ID, WCC),
2851b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID, WCC),
2852b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID, WCC),
2853b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID, WCC),
2854b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC),
2855b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC),
2856b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC),
2857b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC_SEED),
2858b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA),
2859b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA),
2860b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA),
2861b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365, BCA),
2862b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID, BCA),
2863b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID, BCA),
2864b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA),
2865b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC),
2866b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),
2867b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC_SEED),
2868b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC_SEED),
2869b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC_SEED),
2870b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC_SEED),
2871b4c3e9b5SBjoern A. Zeeb 	BRCMF_PCIE_DEVICE(CY_PCIE_54591_DEVICE_ID, CYW),
2872b4c3e9b5SBjoern A. Zeeb 	{ /* end: all zeroes */ }
2873b4c3e9b5SBjoern A. Zeeb };
2874b4c3e9b5SBjoern A. Zeeb 
2875b4c3e9b5SBjoern A. Zeeb 
2876b4c3e9b5SBjoern A. Zeeb MODULE_DEVICE_TABLE(pci, brcmf_pcie_devid_table);
2877b4c3e9b5SBjoern A. Zeeb 
2878b4c3e9b5SBjoern A. Zeeb 
2879b4c3e9b5SBjoern A. Zeeb static struct pci_driver brcmf_pciedrvr = {
2880b4c3e9b5SBjoern A. Zeeb 	.name = KBUILD_MODNAME,
2881b4c3e9b5SBjoern A. Zeeb 	.id_table = brcmf_pcie_devid_table,
2882b4c3e9b5SBjoern A. Zeeb 	.probe = brcmf_pcie_probe,
2883b4c3e9b5SBjoern A. Zeeb 	.remove = brcmf_pcie_remove,
2884b4c3e9b5SBjoern A. Zeeb #ifdef CONFIG_PM
2885b4c3e9b5SBjoern A. Zeeb 	.driver.pm = &brcmf_pciedrvr_pm,
2886b4c3e9b5SBjoern A. Zeeb #endif
2887b4c3e9b5SBjoern A. Zeeb 	.driver.coredump = brcmf_dev_coredump,
2888b4c3e9b5SBjoern A. Zeeb };
2889b4c3e9b5SBjoern A. Zeeb 
2890b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_register(void)2891b4c3e9b5SBjoern A. Zeeb int brcmf_pcie_register(void)
2892b4c3e9b5SBjoern A. Zeeb {
2893b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
2894b4c3e9b5SBjoern A. Zeeb 	return pci_register_driver(&brcmf_pciedrvr);
2895b4c3e9b5SBjoern A. Zeeb }
2896b4c3e9b5SBjoern A. Zeeb 
2897b4c3e9b5SBjoern A. Zeeb 
brcmf_pcie_exit(void)2898b4c3e9b5SBjoern A. Zeeb void brcmf_pcie_exit(void)
2899b4c3e9b5SBjoern A. Zeeb {
2900b4c3e9b5SBjoern A. Zeeb 	brcmf_dbg(PCIE, "Enter\n");
2901b4c3e9b5SBjoern A. Zeeb 	pci_unregister_driver(&brcmf_pciedrvr);
2902b4c3e9b5SBjoern A. Zeeb }
2903