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