1b4c3e9b5SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2b4c3e9b5SBjoern A. Zeeb /*
3b4c3e9b5SBjoern A. Zeeb * Copyright (c) 2014 Broadcom Corporation
4b4c3e9b5SBjoern A. Zeeb */
5b4c3e9b5SBjoern A. Zeeb #include <linux/kernel.h>
6b4c3e9b5SBjoern A. Zeeb #include <linux/delay.h>
7b4c3e9b5SBjoern A. Zeeb #include <linux/list.h>
8b4c3e9b5SBjoern A. Zeeb #include <linux/ssb/ssb_regs.h>
9b4c3e9b5SBjoern A. Zeeb #include <linux/bcma/bcma.h>
10b4c3e9b5SBjoern A. Zeeb #include <linux/bcma/bcma_regs.h>
11b4c3e9b5SBjoern A. Zeeb
12b4c3e9b5SBjoern A. Zeeb #include <defs.h>
13b4c3e9b5SBjoern A. Zeeb #include <soc.h>
14b4c3e9b5SBjoern A. Zeeb #include <brcm_hw_ids.h>
15b4c3e9b5SBjoern A. Zeeb #include <brcmu_utils.h>
16b4c3e9b5SBjoern A. Zeeb #include <chipcommon.h>
17b4c3e9b5SBjoern A. Zeeb #include "debug.h"
18b4c3e9b5SBjoern A. Zeeb #include "chip.h"
19b4c3e9b5SBjoern A. Zeeb
20b4c3e9b5SBjoern A. Zeeb /* SOC Interconnect types (aka chip types) */
21b4c3e9b5SBjoern A. Zeeb #define SOCI_SB 0
22b4c3e9b5SBjoern A. Zeeb #define SOCI_AI 1
23b4c3e9b5SBjoern A. Zeeb
24b4c3e9b5SBjoern A. Zeeb /* PL-368 DMP definitions */
25b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_TYPE_MSK 0x0000000F
26b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_EMPTY 0x00000000
27b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_VALID 0x00000001
28b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_COMPONENT 0x00000001
29b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_MASTER_PORT 0x00000003
30b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_ADDRESS 0x00000005
31b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_ADDRSIZE_GT32 0x00000008
32b4c3e9b5SBjoern A. Zeeb #define DMP_DESC_EOT 0x0000000F
33b4c3e9b5SBjoern A. Zeeb
34b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_DESIGNER 0xFFF00000
35b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_DESIGNER_S 20
36b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_PARTNUM 0x000FFF00
37b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_PARTNUM_S 8
38b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_CLASS 0x000000F0
39b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_CLASS_S 4
40b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_REVISION 0xFF000000
41b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_REVISION_S 24
42b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_SWRAP 0x00F80000
43b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_SWRAP_S 19
44b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_MWRAP 0x0007C000
45b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_MWRAP_S 14
46b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_SPORT 0x00003E00
47b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_SPORT_S 9
48b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_MPORT 0x000001F0
49b4c3e9b5SBjoern A. Zeeb #define DMP_COMP_NUM_MPORT_S 4
50b4c3e9b5SBjoern A. Zeeb
51b4c3e9b5SBjoern A. Zeeb #define DMP_MASTER_PORT_UID 0x0000FF00
52b4c3e9b5SBjoern A. Zeeb #define DMP_MASTER_PORT_UID_S 8
53b4c3e9b5SBjoern A. Zeeb #define DMP_MASTER_PORT_NUM 0x000000F0
54b4c3e9b5SBjoern A. Zeeb #define DMP_MASTER_PORT_NUM_S 4
55b4c3e9b5SBjoern A. Zeeb
56b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_ADDR_BASE 0xFFFFF000
57b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_ADDR_BASE_S 12
58b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_PORT_NUM 0x00000F00
59b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_PORT_NUM_S 8
60b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE 0x000000C0
61b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE_S 6
62b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE_SLAVE 0
63b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE_BRIDGE 1
64b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE_SWRAP 2
65b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_TYPE_MWRAP 3
66b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_TYPE 0x00000030
67b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_TYPE_S 4
68b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_4K 0
69b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_8K 1
70b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_16K 2
71b4c3e9b5SBjoern A. Zeeb #define DMP_SLAVE_SIZE_DESC 3
72b4c3e9b5SBjoern A. Zeeb
73b4c3e9b5SBjoern A. Zeeb /* EROM CompIdentB */
74b4c3e9b5SBjoern A. Zeeb #define CIB_REV_MASK 0xff000000
75b4c3e9b5SBjoern A. Zeeb #define CIB_REV_SHIFT 24
76b4c3e9b5SBjoern A. Zeeb
77b4c3e9b5SBjoern A. Zeeb /* ARM CR4 core specific control flag bits */
78b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
79b4c3e9b5SBjoern A. Zeeb
80b4c3e9b5SBjoern A. Zeeb /* D11 core specific control flag bits */
81b4c3e9b5SBjoern A. Zeeb #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
82b4c3e9b5SBjoern A. Zeeb #define D11_BCMA_IOCTL_PHYRESET 0x0008
83b4c3e9b5SBjoern A. Zeeb
84b4c3e9b5SBjoern A. Zeeb /* chip core base & ramsize */
85b4c3e9b5SBjoern A. Zeeb /* bcm4329 */
86b4c3e9b5SBjoern A. Zeeb /* SDIO device core, ID 0x829 */
87b4c3e9b5SBjoern A. Zeeb #define BCM4329_CORE_BUS_BASE 0x18011000
88b4c3e9b5SBjoern A. Zeeb /* internal memory core, ID 0x80e */
89b4c3e9b5SBjoern A. Zeeb #define BCM4329_CORE_SOCRAM_BASE 0x18003000
90b4c3e9b5SBjoern A. Zeeb /* ARM Cortex M3 core, ID 0x82a */
91b4c3e9b5SBjoern A. Zeeb #define BCM4329_CORE_ARM_BASE 0x18002000
92b4c3e9b5SBjoern A. Zeeb
93b4c3e9b5SBjoern A. Zeeb /* Max possibly supported memory size (limited by IO mapped memory) */
94b4c3e9b5SBjoern A. Zeeb #define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024)
95b4c3e9b5SBjoern A. Zeeb
96b4c3e9b5SBjoern A. Zeeb #define CORE_SB(base, field) \
97b4c3e9b5SBjoern A. Zeeb (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
98b4c3e9b5SBjoern A. Zeeb #define SBCOREREV(sbidh) \
99b4c3e9b5SBjoern A. Zeeb ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
100b4c3e9b5SBjoern A. Zeeb ((sbidh) & SSB_IDHIGH_RCLO))
101b4c3e9b5SBjoern A. Zeeb
102b4c3e9b5SBjoern A. Zeeb struct sbconfig {
103b4c3e9b5SBjoern A. Zeeb u32 PAD[2];
104b4c3e9b5SBjoern A. Zeeb u32 sbipsflag; /* initiator port ocp slave flag */
105b4c3e9b5SBjoern A. Zeeb u32 PAD[3];
106b4c3e9b5SBjoern A. Zeeb u32 sbtpsflag; /* target port ocp slave flag */
107b4c3e9b5SBjoern A. Zeeb u32 PAD[11];
108b4c3e9b5SBjoern A. Zeeb u32 sbtmerrloga; /* (sonics >= 2.3) */
109b4c3e9b5SBjoern A. Zeeb u32 PAD;
110b4c3e9b5SBjoern A. Zeeb u32 sbtmerrlog; /* (sonics >= 2.3) */
111b4c3e9b5SBjoern A. Zeeb u32 PAD[3];
112b4c3e9b5SBjoern A. Zeeb u32 sbadmatch3; /* address match3 */
113b4c3e9b5SBjoern A. Zeeb u32 PAD;
114b4c3e9b5SBjoern A. Zeeb u32 sbadmatch2; /* address match2 */
115b4c3e9b5SBjoern A. Zeeb u32 PAD;
116b4c3e9b5SBjoern A. Zeeb u32 sbadmatch1; /* address match1 */
117b4c3e9b5SBjoern A. Zeeb u32 PAD[7];
118b4c3e9b5SBjoern A. Zeeb u32 sbimstate; /* initiator agent state */
119b4c3e9b5SBjoern A. Zeeb u32 sbintvec; /* interrupt mask */
120b4c3e9b5SBjoern A. Zeeb u32 sbtmstatelow; /* target state */
121b4c3e9b5SBjoern A. Zeeb u32 sbtmstatehigh; /* target state */
122b4c3e9b5SBjoern A. Zeeb u32 sbbwa0; /* bandwidth allocation table0 */
123b4c3e9b5SBjoern A. Zeeb u32 PAD;
124b4c3e9b5SBjoern A. Zeeb u32 sbimconfiglow; /* initiator configuration */
125b4c3e9b5SBjoern A. Zeeb u32 sbimconfighigh; /* initiator configuration */
126b4c3e9b5SBjoern A. Zeeb u32 sbadmatch0; /* address match0 */
127b4c3e9b5SBjoern A. Zeeb u32 PAD;
128b4c3e9b5SBjoern A. Zeeb u32 sbtmconfiglow; /* target configuration */
129b4c3e9b5SBjoern A. Zeeb u32 sbtmconfighigh; /* target configuration */
130b4c3e9b5SBjoern A. Zeeb u32 sbbconfig; /* broadcast configuration */
131b4c3e9b5SBjoern A. Zeeb u32 PAD;
132b4c3e9b5SBjoern A. Zeeb u32 sbbstate; /* broadcast state */
133b4c3e9b5SBjoern A. Zeeb u32 PAD[3];
134b4c3e9b5SBjoern A. Zeeb u32 sbactcnfg; /* activate configuration */
135b4c3e9b5SBjoern A. Zeeb u32 PAD[3];
136b4c3e9b5SBjoern A. Zeeb u32 sbflagst; /* current sbflags */
137b4c3e9b5SBjoern A. Zeeb u32 PAD[3];
138b4c3e9b5SBjoern A. Zeeb u32 sbidlow; /* identification */
139b4c3e9b5SBjoern A. Zeeb u32 sbidhigh; /* identification */
140b4c3e9b5SBjoern A. Zeeb };
141b4c3e9b5SBjoern A. Zeeb
142b4c3e9b5SBjoern A. Zeeb #define INVALID_RAMBASE ((u32)(~0))
143b4c3e9b5SBjoern A. Zeeb
144b4c3e9b5SBjoern A. Zeeb /* bankidx and bankinfo reg defines corerev >= 8 */
145b4c3e9b5SBjoern A. Zeeb #define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000
146b4c3e9b5SBjoern A. Zeeb #define SOCRAM_BANKINFO_SZMASK 0x0000007f
147b4c3e9b5SBjoern A. Zeeb #define SOCRAM_BANKIDX_ROM_MASK 0x00000100
148b4c3e9b5SBjoern A. Zeeb
149b4c3e9b5SBjoern A. Zeeb #define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8
150b4c3e9b5SBjoern A. Zeeb /* socram bankinfo memtype */
151b4c3e9b5SBjoern A. Zeeb #define SOCRAM_MEMTYPE_RAM 0
152b4c3e9b5SBjoern A. Zeeb #define SOCRAM_MEMTYPE_R0M 1
153b4c3e9b5SBjoern A. Zeeb #define SOCRAM_MEMTYPE_DEVRAM 2
154b4c3e9b5SBjoern A. Zeeb
155b4c3e9b5SBjoern A. Zeeb #define SOCRAM_BANKINFO_SZBASE 8192
156b4c3e9b5SBjoern A. Zeeb #define SRCI_LSS_MASK 0x00f00000
157b4c3e9b5SBjoern A. Zeeb #define SRCI_LSS_SHIFT 20
158b4c3e9b5SBjoern A. Zeeb #define SRCI_SRNB_MASK 0xf0
159b4c3e9b5SBjoern A. Zeeb #define SRCI_SRNB_MASK_EXT 0x100
160b4c3e9b5SBjoern A. Zeeb #define SRCI_SRNB_SHIFT 4
161b4c3e9b5SBjoern A. Zeeb #define SRCI_SRBSZ_MASK 0xf
162b4c3e9b5SBjoern A. Zeeb #define SRCI_SRBSZ_SHIFT 0
163b4c3e9b5SBjoern A. Zeeb #define SR_BSZ_BASE 14
164b4c3e9b5SBjoern A. Zeeb
165b4c3e9b5SBjoern A. Zeeb struct sbsocramregs {
166b4c3e9b5SBjoern A. Zeeb u32 coreinfo;
167b4c3e9b5SBjoern A. Zeeb u32 bwalloc;
168b4c3e9b5SBjoern A. Zeeb u32 extracoreinfo;
169b4c3e9b5SBjoern A. Zeeb u32 biststat;
170b4c3e9b5SBjoern A. Zeeb u32 bankidx;
171b4c3e9b5SBjoern A. Zeeb u32 standbyctrl;
172b4c3e9b5SBjoern A. Zeeb
173b4c3e9b5SBjoern A. Zeeb u32 errlogstatus; /* rev 6 */
174b4c3e9b5SBjoern A. Zeeb u32 errlogaddr; /* rev 6 */
175b4c3e9b5SBjoern A. Zeeb /* used for patching rev 3 & 5 */
176b4c3e9b5SBjoern A. Zeeb u32 cambankidx;
177b4c3e9b5SBjoern A. Zeeb u32 cambankstandbyctrl;
178b4c3e9b5SBjoern A. Zeeb u32 cambankpatchctrl;
179b4c3e9b5SBjoern A. Zeeb u32 cambankpatchtblbaseaddr;
180b4c3e9b5SBjoern A. Zeeb u32 cambankcmdreg;
181b4c3e9b5SBjoern A. Zeeb u32 cambankdatareg;
182b4c3e9b5SBjoern A. Zeeb u32 cambankmaskreg;
183b4c3e9b5SBjoern A. Zeeb u32 PAD[1];
184b4c3e9b5SBjoern A. Zeeb u32 bankinfo; /* corev 8 */
185b4c3e9b5SBjoern A. Zeeb u32 bankpda;
186b4c3e9b5SBjoern A. Zeeb u32 PAD[14];
187b4c3e9b5SBjoern A. Zeeb u32 extmemconfig;
188b4c3e9b5SBjoern A. Zeeb u32 extmemparitycsr;
189b4c3e9b5SBjoern A. Zeeb u32 extmemparityerrdata;
190b4c3e9b5SBjoern A. Zeeb u32 extmemparityerrcnt;
191b4c3e9b5SBjoern A. Zeeb u32 extmemwrctrlandsize;
192b4c3e9b5SBjoern A. Zeeb u32 PAD[84];
193b4c3e9b5SBjoern A. Zeeb u32 workaround;
194b4c3e9b5SBjoern A. Zeeb u32 pwrctl; /* corerev >= 2 */
195b4c3e9b5SBjoern A. Zeeb u32 PAD[133];
196b4c3e9b5SBjoern A. Zeeb u32 sr_control; /* corerev >= 15 */
197b4c3e9b5SBjoern A. Zeeb u32 sr_status; /* corerev >= 15 */
198b4c3e9b5SBjoern A. Zeeb u32 sr_address; /* corerev >= 15 */
199b4c3e9b5SBjoern A. Zeeb u32 sr_data; /* corerev >= 15 */
200b4c3e9b5SBjoern A. Zeeb };
201b4c3e9b5SBjoern A. Zeeb
202b4c3e9b5SBjoern A. Zeeb #define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f)
203b4c3e9b5SBjoern A. Zeeb #define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f)
204b4c3e9b5SBjoern A. Zeeb
205b4c3e9b5SBjoern A. Zeeb #define ARMCR4_CAP (0x04)
206b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BANKIDX (0x40)
207b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BANKINFO (0x44)
208b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BANKPDA (0x4C)
209b4c3e9b5SBjoern A. Zeeb
210b4c3e9b5SBjoern A. Zeeb #define ARMCR4_TCBBNB_MASK 0xf0
211b4c3e9b5SBjoern A. Zeeb #define ARMCR4_TCBBNB_SHIFT 4
212b4c3e9b5SBjoern A. Zeeb #define ARMCR4_TCBANB_MASK 0xf
213b4c3e9b5SBjoern A. Zeeb #define ARMCR4_TCBANB_SHIFT 0
214b4c3e9b5SBjoern A. Zeeb
215b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BSZ_MASK 0x7f
216b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BSZ_MULT 8192
217b4c3e9b5SBjoern A. Zeeb #define ARMCR4_BLK_1K_MASK 0x200
218b4c3e9b5SBjoern A. Zeeb
219b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv {
220b4c3e9b5SBjoern A. Zeeb struct brcmf_core pub;
221b4c3e9b5SBjoern A. Zeeb u32 wrapbase;
222b4c3e9b5SBjoern A. Zeeb struct list_head list;
223b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
224b4c3e9b5SBjoern A. Zeeb };
225b4c3e9b5SBjoern A. Zeeb
226b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv {
227b4c3e9b5SBjoern A. Zeeb struct brcmf_chip pub;
228b4c3e9b5SBjoern A. Zeeb const struct brcmf_buscore_ops *ops;
229b4c3e9b5SBjoern A. Zeeb void *ctx;
230b4c3e9b5SBjoern A. Zeeb /* assured first core is chipcommon, second core is buscore */
231b4c3e9b5SBjoern A. Zeeb struct list_head cores;
232b4c3e9b5SBjoern A. Zeeb u16 num_cores;
233b4c3e9b5SBjoern A. Zeeb
234b4c3e9b5SBjoern A. Zeeb bool (*iscoreup)(struct brcmf_core_priv *core);
235b4c3e9b5SBjoern A. Zeeb void (*coredisable)(struct brcmf_core_priv *core, u32 prereset,
236b4c3e9b5SBjoern A. Zeeb u32 reset);
237b4c3e9b5SBjoern A. Zeeb void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset,
238b4c3e9b5SBjoern A. Zeeb u32 postreset);
239b4c3e9b5SBjoern A. Zeeb };
240b4c3e9b5SBjoern A. Zeeb
brcmf_chip_sb_corerev(struct brcmf_chip_priv * ci,struct brcmf_core * core)241b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci,
242b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core)
243b4c3e9b5SBjoern A. Zeeb {
244b4c3e9b5SBjoern A. Zeeb u32 regdata;
245b4c3e9b5SBjoern A. Zeeb
246b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh));
247b4c3e9b5SBjoern A. Zeeb core->rev = SBCOREREV(regdata);
248b4c3e9b5SBjoern A. Zeeb }
249b4c3e9b5SBjoern A. Zeeb
brcmf_chip_sb_iscoreup(struct brcmf_core_priv * core)250b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core)
251b4c3e9b5SBjoern A. Zeeb {
252b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
253b4c3e9b5SBjoern A. Zeeb u32 regdata;
254b4c3e9b5SBjoern A. Zeeb u32 address;
255b4c3e9b5SBjoern A. Zeeb
256b4c3e9b5SBjoern A. Zeeb ci = core->chip;
257b4c3e9b5SBjoern A. Zeeb address = CORE_SB(core->pub.base, sbtmstatelow);
258b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, address);
259b4c3e9b5SBjoern A. Zeeb regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
260b4c3e9b5SBjoern A. Zeeb SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
261b4c3e9b5SBjoern A. Zeeb return SSB_TMSLOW_CLOCK == regdata;
262b4c3e9b5SBjoern A. Zeeb }
263b4c3e9b5SBjoern A. Zeeb
brcmf_chip_ai_iscoreup(struct brcmf_core_priv * core)264b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core)
265b4c3e9b5SBjoern A. Zeeb {
266b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
267b4c3e9b5SBjoern A. Zeeb u32 regdata;
268b4c3e9b5SBjoern A. Zeeb bool ret;
269b4c3e9b5SBjoern A. Zeeb
270b4c3e9b5SBjoern A. Zeeb ci = core->chip;
271b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
272b4c3e9b5SBjoern A. Zeeb ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
273b4c3e9b5SBjoern A. Zeeb
274b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
275b4c3e9b5SBjoern A. Zeeb ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
276b4c3e9b5SBjoern A. Zeeb
277b4c3e9b5SBjoern A. Zeeb return ret;
278b4c3e9b5SBjoern A. Zeeb }
279b4c3e9b5SBjoern A. Zeeb
brcmf_chip_sb_coredisable(struct brcmf_core_priv * core,u32 prereset,u32 reset)280b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core,
281b4c3e9b5SBjoern A. Zeeb u32 prereset, u32 reset)
282b4c3e9b5SBjoern A. Zeeb {
283b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
284b4c3e9b5SBjoern A. Zeeb u32 val, base;
285b4c3e9b5SBjoern A. Zeeb
286b4c3e9b5SBjoern A. Zeeb ci = core->chip;
287b4c3e9b5SBjoern A. Zeeb base = core->pub.base;
288b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
289b4c3e9b5SBjoern A. Zeeb if (val & SSB_TMSLOW_RESET)
290b4c3e9b5SBjoern A. Zeeb return;
291b4c3e9b5SBjoern A. Zeeb
292b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
293b4c3e9b5SBjoern A. Zeeb if ((val & SSB_TMSLOW_CLOCK) != 0) {
294b4c3e9b5SBjoern A. Zeeb /*
295b4c3e9b5SBjoern A. Zeeb * set target reject and spin until busy is clear
296b4c3e9b5SBjoern A. Zeeb * (preserve core-specific bits)
297b4c3e9b5SBjoern A. Zeeb */
298b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
299b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
300b4c3e9b5SBjoern A. Zeeb val | SSB_TMSLOW_REJECT);
301b4c3e9b5SBjoern A. Zeeb
302b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
303b4c3e9b5SBjoern A. Zeeb udelay(1);
304b4c3e9b5SBjoern A. Zeeb SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh))
305b4c3e9b5SBjoern A. Zeeb & SSB_TMSHIGH_BUSY), 100000);
306b4c3e9b5SBjoern A. Zeeb
307b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
308b4c3e9b5SBjoern A. Zeeb if (val & SSB_TMSHIGH_BUSY)
309b4c3e9b5SBjoern A. Zeeb brcmf_err("core state still busy\n");
310b4c3e9b5SBjoern A. Zeeb
311b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
312b4c3e9b5SBjoern A. Zeeb if (val & SSB_IDLOW_INITIATOR) {
313b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx,
314b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate));
315b4c3e9b5SBjoern A. Zeeb val |= SSB_IMSTATE_REJECT;
316b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx,
317b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate), val);
318b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx,
319b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate));
320b4c3e9b5SBjoern A. Zeeb udelay(1);
321b4c3e9b5SBjoern A. Zeeb SPINWAIT((ci->ops->read32(ci->ctx,
322b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate)) &
323b4c3e9b5SBjoern A. Zeeb SSB_IMSTATE_BUSY), 100000);
324b4c3e9b5SBjoern A. Zeeb }
325b4c3e9b5SBjoern A. Zeeb
326b4c3e9b5SBjoern A. Zeeb /* set reset and reject while enabling the clocks */
327b4c3e9b5SBjoern A. Zeeb val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
328b4c3e9b5SBjoern A. Zeeb SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
329b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);
330b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
331b4c3e9b5SBjoern A. Zeeb udelay(10);
332b4c3e9b5SBjoern A. Zeeb
333b4c3e9b5SBjoern A. Zeeb /* clear the initiator reject bit */
334b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
335b4c3e9b5SBjoern A. Zeeb if (val & SSB_IDLOW_INITIATOR) {
336b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx,
337b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate));
338b4c3e9b5SBjoern A. Zeeb val &= ~SSB_IMSTATE_REJECT;
339b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx,
340b4c3e9b5SBjoern A. Zeeb CORE_SB(base, sbimstate), val);
341b4c3e9b5SBjoern A. Zeeb }
342b4c3e9b5SBjoern A. Zeeb }
343b4c3e9b5SBjoern A. Zeeb
344b4c3e9b5SBjoern A. Zeeb /* leave reset and reject asserted */
345b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
346b4c3e9b5SBjoern A. Zeeb (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
347b4c3e9b5SBjoern A. Zeeb udelay(1);
348b4c3e9b5SBjoern A. Zeeb }
349b4c3e9b5SBjoern A. Zeeb
brcmf_chip_ai_coredisable(struct brcmf_core_priv * core,u32 prereset,u32 reset)350b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
351b4c3e9b5SBjoern A. Zeeb u32 prereset, u32 reset)
352b4c3e9b5SBjoern A. Zeeb {
353b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
354b4c3e9b5SBjoern A. Zeeb u32 regdata;
355b4c3e9b5SBjoern A. Zeeb
356b4c3e9b5SBjoern A. Zeeb ci = core->chip;
357b4c3e9b5SBjoern A. Zeeb
358b4c3e9b5SBjoern A. Zeeb /* if core is already in reset, skip reset */
359b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
360b4c3e9b5SBjoern A. Zeeb if ((regdata & BCMA_RESET_CTL_RESET) != 0)
361b4c3e9b5SBjoern A. Zeeb goto in_reset_configure;
362b4c3e9b5SBjoern A. Zeeb
363b4c3e9b5SBjoern A. Zeeb /* configure reset */
364b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
365b4c3e9b5SBjoern A. Zeeb prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
366b4c3e9b5SBjoern A. Zeeb ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
367b4c3e9b5SBjoern A. Zeeb
368b4c3e9b5SBjoern A. Zeeb /* put in reset */
369b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL,
370b4c3e9b5SBjoern A. Zeeb BCMA_RESET_CTL_RESET);
371b4c3e9b5SBjoern A. Zeeb usleep_range(10, 20);
372b4c3e9b5SBjoern A. Zeeb
373b4c3e9b5SBjoern A. Zeeb /* wait till reset is 1 */
374b4c3e9b5SBjoern A. Zeeb SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
375b4c3e9b5SBjoern A. Zeeb BCMA_RESET_CTL_RESET, 300);
376b4c3e9b5SBjoern A. Zeeb
377b4c3e9b5SBjoern A. Zeeb in_reset_configure:
378b4c3e9b5SBjoern A. Zeeb /* in-reset configure */
379b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
380b4c3e9b5SBjoern A. Zeeb reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
381b4c3e9b5SBjoern A. Zeeb ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
382b4c3e9b5SBjoern A. Zeeb }
383b4c3e9b5SBjoern A. Zeeb
brcmf_chip_sb_resetcore(struct brcmf_core_priv * core,u32 prereset,u32 reset,u32 postreset)384b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset,
385b4c3e9b5SBjoern A. Zeeb u32 reset, u32 postreset)
386b4c3e9b5SBjoern A. Zeeb {
387b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
388b4c3e9b5SBjoern A. Zeeb u32 regdata;
389b4c3e9b5SBjoern A. Zeeb u32 base;
390b4c3e9b5SBjoern A. Zeeb
391b4c3e9b5SBjoern A. Zeeb ci = core->chip;
392b4c3e9b5SBjoern A. Zeeb base = core->pub.base;
393b4c3e9b5SBjoern A. Zeeb /*
394b4c3e9b5SBjoern A. Zeeb * Must do the disable sequence first to work for
395b4c3e9b5SBjoern A. Zeeb * arbitrary current core state.
396b4c3e9b5SBjoern A. Zeeb */
397b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_coredisable(core, 0, 0);
398b4c3e9b5SBjoern A. Zeeb
399b4c3e9b5SBjoern A. Zeeb /*
400b4c3e9b5SBjoern A. Zeeb * Now do the initialization sequence.
401b4c3e9b5SBjoern A. Zeeb * set reset while enabling the clock and
402b4c3e9b5SBjoern A. Zeeb * forcing them on throughout the core
403b4c3e9b5SBjoern A. Zeeb */
404b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
405b4c3e9b5SBjoern A. Zeeb SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
406b4c3e9b5SBjoern A. Zeeb SSB_TMSLOW_RESET);
407b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
408b4c3e9b5SBjoern A. Zeeb udelay(1);
409b4c3e9b5SBjoern A. Zeeb
410b4c3e9b5SBjoern A. Zeeb /* clear any serror */
411b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
412b4c3e9b5SBjoern A. Zeeb if (regdata & SSB_TMSHIGH_SERR)
413b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);
414b4c3e9b5SBjoern A. Zeeb
415b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate));
416b4c3e9b5SBjoern A. Zeeb if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
417b4c3e9b5SBjoern A. Zeeb regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
418b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata);
419b4c3e9b5SBjoern A. Zeeb }
420b4c3e9b5SBjoern A. Zeeb
421b4c3e9b5SBjoern A. Zeeb /* clear reset and allow it to propagate throughout the core */
422b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
423b4c3e9b5SBjoern A. Zeeb SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
424b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
425b4c3e9b5SBjoern A. Zeeb udelay(1);
426b4c3e9b5SBjoern A. Zeeb
427b4c3e9b5SBjoern A. Zeeb /* leave clock enabled */
428b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
429b4c3e9b5SBjoern A. Zeeb SSB_TMSLOW_CLOCK);
430b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
431b4c3e9b5SBjoern A. Zeeb udelay(1);
432b4c3e9b5SBjoern A. Zeeb }
433b4c3e9b5SBjoern A. Zeeb
brcmf_chip_ai_resetcore(struct brcmf_core_priv * core,u32 prereset,u32 reset,u32 postreset)434b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset,
435b4c3e9b5SBjoern A. Zeeb u32 reset, u32 postreset)
436b4c3e9b5SBjoern A. Zeeb {
437b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci;
438b4c3e9b5SBjoern A. Zeeb int count;
439b4c3e9b5SBjoern A. Zeeb struct brcmf_core *d11core2 = NULL;
440b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *d11priv2 = NULL;
441b4c3e9b5SBjoern A. Zeeb
442b4c3e9b5SBjoern A. Zeeb ci = core->chip;
443b4c3e9b5SBjoern A. Zeeb
444b4c3e9b5SBjoern A. Zeeb /* special handle two D11 cores reset */
445b4c3e9b5SBjoern A. Zeeb if (core->pub.id == BCMA_CORE_80211) {
446b4c3e9b5SBjoern A. Zeeb d11core2 = brcmf_chip_get_d11core(&ci->pub, 1);
447b4c3e9b5SBjoern A. Zeeb if (d11core2) {
448b4c3e9b5SBjoern A. Zeeb brcmf_dbg(INFO, "found two d11 cores, reset both\n");
449b4c3e9b5SBjoern A. Zeeb d11priv2 = container_of(d11core2,
450b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv, pub);
451b4c3e9b5SBjoern A. Zeeb }
452b4c3e9b5SBjoern A. Zeeb }
453b4c3e9b5SBjoern A. Zeeb
454b4c3e9b5SBjoern A. Zeeb /* must disable first to work for arbitrary current core state */
455b4c3e9b5SBjoern A. Zeeb brcmf_chip_ai_coredisable(core, prereset, reset);
456b4c3e9b5SBjoern A. Zeeb if (d11priv2)
457b4c3e9b5SBjoern A. Zeeb brcmf_chip_ai_coredisable(d11priv2, prereset, reset);
458b4c3e9b5SBjoern A. Zeeb
459b4c3e9b5SBjoern A. Zeeb count = 0;
460b4c3e9b5SBjoern A. Zeeb while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) &
461b4c3e9b5SBjoern A. Zeeb BCMA_RESET_CTL_RESET) {
462b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0);
463b4c3e9b5SBjoern A. Zeeb count++;
464b4c3e9b5SBjoern A. Zeeb if (count > 50)
465b4c3e9b5SBjoern A. Zeeb break;
466b4c3e9b5SBjoern A. Zeeb usleep_range(40, 60);
467b4c3e9b5SBjoern A. Zeeb }
468b4c3e9b5SBjoern A. Zeeb
469b4c3e9b5SBjoern A. Zeeb if (d11priv2) {
470b4c3e9b5SBjoern A. Zeeb count = 0;
471b4c3e9b5SBjoern A. Zeeb while (ci->ops->read32(ci->ctx,
472b4c3e9b5SBjoern A. Zeeb d11priv2->wrapbase + BCMA_RESET_CTL) &
473b4c3e9b5SBjoern A. Zeeb BCMA_RESET_CTL_RESET) {
474b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx,
475b4c3e9b5SBjoern A. Zeeb d11priv2->wrapbase + BCMA_RESET_CTL,
476b4c3e9b5SBjoern A. Zeeb 0);
477b4c3e9b5SBjoern A. Zeeb count++;
478b4c3e9b5SBjoern A. Zeeb if (count > 50)
479b4c3e9b5SBjoern A. Zeeb break;
480b4c3e9b5SBjoern A. Zeeb usleep_range(40, 60);
481b4c3e9b5SBjoern A. Zeeb }
482b4c3e9b5SBjoern A. Zeeb }
483b4c3e9b5SBjoern A. Zeeb
484b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
485b4c3e9b5SBjoern A. Zeeb postreset | BCMA_IOCTL_CLK);
486b4c3e9b5SBjoern A. Zeeb ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
487b4c3e9b5SBjoern A. Zeeb
488b4c3e9b5SBjoern A. Zeeb if (d11priv2) {
489b4c3e9b5SBjoern A. Zeeb ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL,
490b4c3e9b5SBjoern A. Zeeb postreset | BCMA_IOCTL_CLK);
491b4c3e9b5SBjoern A. Zeeb ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL);
492b4c3e9b5SBjoern A. Zeeb }
493b4c3e9b5SBjoern A. Zeeb }
494b4c3e9b5SBjoern A. Zeeb
brcmf_chip_name(u32 id,u32 rev,char * buf,uint len)495b4c3e9b5SBjoern A. Zeeb char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)
496b4c3e9b5SBjoern A. Zeeb {
497b4c3e9b5SBjoern A. Zeeb const char *fmt;
498b4c3e9b5SBjoern A. Zeeb
499b4c3e9b5SBjoern A. Zeeb fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u";
500b4c3e9b5SBjoern A. Zeeb snprintf(buf, len, fmt, id, rev);
501b4c3e9b5SBjoern A. Zeeb return buf;
502b4c3e9b5SBjoern A. Zeeb }
503b4c3e9b5SBjoern A. Zeeb
brcmf_chip_add_core(struct brcmf_chip_priv * ci,u16 coreid,u32 base,u32 wrapbase)504b4c3e9b5SBjoern A. Zeeb static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
505b4c3e9b5SBjoern A. Zeeb u16 coreid, u32 base,
506b4c3e9b5SBjoern A. Zeeb u32 wrapbase)
507b4c3e9b5SBjoern A. Zeeb {
508b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
509b4c3e9b5SBjoern A. Zeeb
510b4c3e9b5SBjoern A. Zeeb core = kzalloc(sizeof(*core), GFP_KERNEL);
511b4c3e9b5SBjoern A. Zeeb if (!core)
512b4c3e9b5SBjoern A. Zeeb return ERR_PTR(-ENOMEM);
513b4c3e9b5SBjoern A. Zeeb
514b4c3e9b5SBjoern A. Zeeb core->pub.id = coreid;
515b4c3e9b5SBjoern A. Zeeb core->pub.base = base;
516b4c3e9b5SBjoern A. Zeeb core->chip = ci;
517b4c3e9b5SBjoern A. Zeeb core->wrapbase = wrapbase;
518b4c3e9b5SBjoern A. Zeeb
519b4c3e9b5SBjoern A. Zeeb list_add_tail(&core->list, &ci->cores);
520b4c3e9b5SBjoern A. Zeeb return &core->pub;
521b4c3e9b5SBjoern A. Zeeb }
522b4c3e9b5SBjoern A. Zeeb
523b4c3e9b5SBjoern A. Zeeb /* safety check for chipinfo */
brcmf_chip_cores_check(struct brcmf_chip_priv * ci)524b4c3e9b5SBjoern A. Zeeb static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
525b4c3e9b5SBjoern A. Zeeb {
526b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
527b4c3e9b5SBjoern A. Zeeb bool need_socram = false;
528b4c3e9b5SBjoern A. Zeeb bool has_socram = false;
529b4c3e9b5SBjoern A. Zeeb bool cpu_found = false;
530b4c3e9b5SBjoern A. Zeeb int idx = 1;
531b4c3e9b5SBjoern A. Zeeb
532b4c3e9b5SBjoern A. Zeeb list_for_each_entry(core, &ci->cores, list) {
533b4c3e9b5SBjoern A. Zeeb brcmf_dbg(INFO, " [%-2d] core 0x%x:%-3d base 0x%08x wrap 0x%08x\n",
534b4c3e9b5SBjoern A. Zeeb idx++, core->pub.id, core->pub.rev, core->pub.base,
535b4c3e9b5SBjoern A. Zeeb core->wrapbase);
536b4c3e9b5SBjoern A. Zeeb
537b4c3e9b5SBjoern A. Zeeb switch (core->pub.id) {
538b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CM3:
539b4c3e9b5SBjoern A. Zeeb cpu_found = true;
540b4c3e9b5SBjoern A. Zeeb need_socram = true;
541b4c3e9b5SBjoern A. Zeeb break;
542b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_INTERNAL_MEM:
543b4c3e9b5SBjoern A. Zeeb has_socram = true;
544b4c3e9b5SBjoern A. Zeeb break;
545b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CR4:
546b4c3e9b5SBjoern A. Zeeb cpu_found = true;
547b4c3e9b5SBjoern A. Zeeb break;
548b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CA7:
549b4c3e9b5SBjoern A. Zeeb cpu_found = true;
550b4c3e9b5SBjoern A. Zeeb break;
551b4c3e9b5SBjoern A. Zeeb default:
552b4c3e9b5SBjoern A. Zeeb break;
553b4c3e9b5SBjoern A. Zeeb }
554b4c3e9b5SBjoern A. Zeeb }
555b4c3e9b5SBjoern A. Zeeb
556b4c3e9b5SBjoern A. Zeeb if (!cpu_found) {
557b4c3e9b5SBjoern A. Zeeb brcmf_err("CPU core not detected\n");
558b4c3e9b5SBjoern A. Zeeb return -ENXIO;
559b4c3e9b5SBjoern A. Zeeb }
560b4c3e9b5SBjoern A. Zeeb /* check RAM core presence for ARM CM3 core */
561b4c3e9b5SBjoern A. Zeeb if (need_socram && !has_socram) {
562b4c3e9b5SBjoern A. Zeeb brcmf_err("RAM core not provided with ARM CM3 core\n");
563b4c3e9b5SBjoern A. Zeeb return -ENODEV;
564b4c3e9b5SBjoern A. Zeeb }
565b4c3e9b5SBjoern A. Zeeb return 0;
566b4c3e9b5SBjoern A. Zeeb }
567b4c3e9b5SBjoern A. Zeeb
brcmf_chip_core_read32(struct brcmf_core_priv * core,u16 reg)568b4c3e9b5SBjoern A. Zeeb static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg)
569b4c3e9b5SBjoern A. Zeeb {
570b4c3e9b5SBjoern A. Zeeb return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg);
571b4c3e9b5SBjoern A. Zeeb }
572b4c3e9b5SBjoern A. Zeeb
brcmf_chip_core_write32(struct brcmf_core_priv * core,u16 reg,u32 val)573b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_core_write32(struct brcmf_core_priv *core,
574b4c3e9b5SBjoern A. Zeeb u16 reg, u32 val)
575b4c3e9b5SBjoern A. Zeeb {
576b4c3e9b5SBjoern A. Zeeb core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val);
577b4c3e9b5SBjoern A. Zeeb }
578b4c3e9b5SBjoern A. Zeeb
brcmf_chip_socram_banksize(struct brcmf_core_priv * core,u8 idx,u32 * banksize)579b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx,
580b4c3e9b5SBjoern A. Zeeb u32 *banksize)
581b4c3e9b5SBjoern A. Zeeb {
582b4c3e9b5SBjoern A. Zeeb u32 bankinfo;
583b4c3e9b5SBjoern A. Zeeb u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
584b4c3e9b5SBjoern A. Zeeb
585b4c3e9b5SBjoern A. Zeeb bankidx |= idx;
586b4c3e9b5SBjoern A. Zeeb brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx);
587b4c3e9b5SBjoern A. Zeeb bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo));
588b4c3e9b5SBjoern A. Zeeb *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1;
589b4c3e9b5SBjoern A. Zeeb *banksize *= SOCRAM_BANKINFO_SZBASE;
590b4c3e9b5SBjoern A. Zeeb return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK);
591b4c3e9b5SBjoern A. Zeeb }
592b4c3e9b5SBjoern A. Zeeb
brcmf_chip_socram_ramsize(struct brcmf_core_priv * sr,u32 * ramsize,u32 * srsize)593b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
594b4c3e9b5SBjoern A. Zeeb u32 *srsize)
595b4c3e9b5SBjoern A. Zeeb {
596b4c3e9b5SBjoern A. Zeeb u32 coreinfo;
597b4c3e9b5SBjoern A. Zeeb uint nb, banksize, lss;
598b4c3e9b5SBjoern A. Zeeb bool retent;
599b4c3e9b5SBjoern A. Zeeb int i;
600b4c3e9b5SBjoern A. Zeeb
601b4c3e9b5SBjoern A. Zeeb *ramsize = 0;
602b4c3e9b5SBjoern A. Zeeb *srsize = 0;
603b4c3e9b5SBjoern A. Zeeb
604b4c3e9b5SBjoern A. Zeeb if (WARN_ON(sr->pub.rev < 4))
605b4c3e9b5SBjoern A. Zeeb return;
606b4c3e9b5SBjoern A. Zeeb
607b4c3e9b5SBjoern A. Zeeb if (!brcmf_chip_iscoreup(&sr->pub))
608b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(&sr->pub, 0, 0, 0);
609b4c3e9b5SBjoern A. Zeeb
610b4c3e9b5SBjoern A. Zeeb /* Get info for determining size */
611b4c3e9b5SBjoern A. Zeeb coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));
612b4c3e9b5SBjoern A. Zeeb nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
613b4c3e9b5SBjoern A. Zeeb
614b4c3e9b5SBjoern A. Zeeb if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {
615b4c3e9b5SBjoern A. Zeeb banksize = (coreinfo & SRCI_SRBSZ_MASK);
616b4c3e9b5SBjoern A. Zeeb lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
617b4c3e9b5SBjoern A. Zeeb if (lss != 0)
618b4c3e9b5SBjoern A. Zeeb nb--;
619b4c3e9b5SBjoern A. Zeeb *ramsize = nb * (1 << (banksize + SR_BSZ_BASE));
620b4c3e9b5SBjoern A. Zeeb if (lss != 0)
621b4c3e9b5SBjoern A. Zeeb *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
622b4c3e9b5SBjoern A. Zeeb } else {
623b4c3e9b5SBjoern A. Zeeb /* length of SRAM Banks increased for corerev greater than 23 */
624b4c3e9b5SBjoern A. Zeeb if (sr->pub.rev >= 23) {
625b4c3e9b5SBjoern A. Zeeb nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT))
626b4c3e9b5SBjoern A. Zeeb >> SRCI_SRNB_SHIFT;
627b4c3e9b5SBjoern A. Zeeb } else {
628b4c3e9b5SBjoern A. Zeeb nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
629b4c3e9b5SBjoern A. Zeeb }
630b4c3e9b5SBjoern A. Zeeb for (i = 0; i < nb; i++) {
631b4c3e9b5SBjoern A. Zeeb retent = brcmf_chip_socram_banksize(sr, i, &banksize);
632b4c3e9b5SBjoern A. Zeeb *ramsize += banksize;
633b4c3e9b5SBjoern A. Zeeb if (retent)
634b4c3e9b5SBjoern A. Zeeb *srsize += banksize;
635b4c3e9b5SBjoern A. Zeeb }
636b4c3e9b5SBjoern A. Zeeb }
637b4c3e9b5SBjoern A. Zeeb
638b4c3e9b5SBjoern A. Zeeb /* hardcoded save&restore memory sizes */
639b4c3e9b5SBjoern A. Zeeb switch (sr->chip->pub.chip) {
640b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4334_CHIP_ID:
641b4c3e9b5SBjoern A. Zeeb if (sr->chip->pub.chiprev < 2)
642b4c3e9b5SBjoern A. Zeeb *srsize = (32 * 1024);
643b4c3e9b5SBjoern A. Zeeb break;
644b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43430_CHIP_ID:
645b4c3e9b5SBjoern A. Zeeb case CY_CC_43439_CHIP_ID:
646b4c3e9b5SBjoern A. Zeeb /* assume sr for now as we can not check
647b4c3e9b5SBjoern A. Zeeb * firmware sr capability at this point.
648b4c3e9b5SBjoern A. Zeeb */
649b4c3e9b5SBjoern A. Zeeb *srsize = (64 * 1024);
650b4c3e9b5SBjoern A. Zeeb break;
651b4c3e9b5SBjoern A. Zeeb default:
652b4c3e9b5SBjoern A. Zeeb break;
653b4c3e9b5SBjoern A. Zeeb }
654b4c3e9b5SBjoern A. Zeeb }
655b4c3e9b5SBjoern A. Zeeb
656b4c3e9b5SBjoern A. Zeeb /** Return the SYS MEM size */
brcmf_chip_sysmem_ramsize(struct brcmf_core_priv * sysmem)657b4c3e9b5SBjoern A. Zeeb static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem)
658b4c3e9b5SBjoern A. Zeeb {
659b4c3e9b5SBjoern A. Zeeb u32 memsize = 0;
660b4c3e9b5SBjoern A. Zeeb u32 coreinfo;
661b4c3e9b5SBjoern A. Zeeb u32 idx;
662b4c3e9b5SBjoern A. Zeeb u32 nb;
663b4c3e9b5SBjoern A. Zeeb u32 banksize;
664b4c3e9b5SBjoern A. Zeeb
665b4c3e9b5SBjoern A. Zeeb if (!brcmf_chip_iscoreup(&sysmem->pub))
666b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0);
667b4c3e9b5SBjoern A. Zeeb
668b4c3e9b5SBjoern A. Zeeb coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo));
669b4c3e9b5SBjoern A. Zeeb nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
670b4c3e9b5SBjoern A. Zeeb
671b4c3e9b5SBjoern A. Zeeb for (idx = 0; idx < nb; idx++) {
672b4c3e9b5SBjoern A. Zeeb brcmf_chip_socram_banksize(sysmem, idx, &banksize);
673b4c3e9b5SBjoern A. Zeeb memsize += banksize;
674b4c3e9b5SBjoern A. Zeeb }
675b4c3e9b5SBjoern A. Zeeb
676b4c3e9b5SBjoern A. Zeeb return memsize;
677b4c3e9b5SBjoern A. Zeeb }
678b4c3e9b5SBjoern A. Zeeb
679b4c3e9b5SBjoern A. Zeeb /** Return the TCM-RAM size of the ARMCR4 core. */
brcmf_chip_tcm_ramsize(struct brcmf_core_priv * cr4)680b4c3e9b5SBjoern A. Zeeb static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
681b4c3e9b5SBjoern A. Zeeb {
682b4c3e9b5SBjoern A. Zeeb u32 corecap;
683b4c3e9b5SBjoern A. Zeeb u32 memsize = 0;
684b4c3e9b5SBjoern A. Zeeb u32 nab;
685b4c3e9b5SBjoern A. Zeeb u32 nbb;
686b4c3e9b5SBjoern A. Zeeb u32 totb;
687b4c3e9b5SBjoern A. Zeeb u32 bxinfo;
688b4c3e9b5SBjoern A. Zeeb u32 blksize;
689b4c3e9b5SBjoern A. Zeeb u32 idx;
690b4c3e9b5SBjoern A. Zeeb
691b4c3e9b5SBjoern A. Zeeb corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
692b4c3e9b5SBjoern A. Zeeb
693b4c3e9b5SBjoern A. Zeeb nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
694b4c3e9b5SBjoern A. Zeeb nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
695b4c3e9b5SBjoern A. Zeeb totb = nab + nbb;
696b4c3e9b5SBjoern A. Zeeb
697b4c3e9b5SBjoern A. Zeeb for (idx = 0; idx < totb; idx++) {
698b4c3e9b5SBjoern A. Zeeb brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
699b4c3e9b5SBjoern A. Zeeb bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
700b4c3e9b5SBjoern A. Zeeb blksize = ARMCR4_BSZ_MULT;
701b4c3e9b5SBjoern A. Zeeb if (bxinfo & ARMCR4_BLK_1K_MASK)
702b4c3e9b5SBjoern A. Zeeb blksize >>= 3;
703b4c3e9b5SBjoern A. Zeeb
704b4c3e9b5SBjoern A. Zeeb memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize;
705b4c3e9b5SBjoern A. Zeeb }
706b4c3e9b5SBjoern A. Zeeb
707b4c3e9b5SBjoern A. Zeeb return memsize;
708b4c3e9b5SBjoern A. Zeeb }
709b4c3e9b5SBjoern A. Zeeb
brcmf_chip_tcm_rambase(struct brcmf_chip_priv * ci)710b4c3e9b5SBjoern A. Zeeb static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
711b4c3e9b5SBjoern A. Zeeb {
712b4c3e9b5SBjoern A. Zeeb switch (ci->pub.chip) {
713b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4345_CHIP_ID:
714b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43454_CHIP_ID:
715b4c3e9b5SBjoern A. Zeeb return 0x198000;
716b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4335_CHIP_ID:
717b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4339_CHIP_ID:
718b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4350_CHIP_ID:
719b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4354_CHIP_ID:
720b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4356_CHIP_ID:
721b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43567_CHIP_ID:
722b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43569_CHIP_ID:
723b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43570_CHIP_ID:
724b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4358_CHIP_ID:
725b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43602_CHIP_ID:
726b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4371_CHIP_ID:
727b4c3e9b5SBjoern A. Zeeb return 0x180000;
728b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43465_CHIP_ID:
729b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43525_CHIP_ID:
730b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4365_CHIP_ID:
731b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4366_CHIP_ID:
732b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43664_CHIP_ID:
733b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43666_CHIP_ID:
734b4c3e9b5SBjoern A. Zeeb return 0x200000;
735b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4355_CHIP_ID:
736b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4359_CHIP_ID:
737b4c3e9b5SBjoern A. Zeeb return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000;
738b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4364_CHIP_ID:
739b4c3e9b5SBjoern A. Zeeb case CY_CC_4373_CHIP_ID:
740b4c3e9b5SBjoern A. Zeeb return 0x160000;
741b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43751_CHIP_ID:
742*9375e11fSBjoern A. Zeeb case BRCM_CC_43752_CHIP_ID:
743b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4377_CHIP_ID:
744b4c3e9b5SBjoern A. Zeeb return 0x170000;
745b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4378_CHIP_ID:
746b4c3e9b5SBjoern A. Zeeb return 0x352000;
747b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4387_CHIP_ID:
748b4c3e9b5SBjoern A. Zeeb return 0x740000;
749b4c3e9b5SBjoern A. Zeeb default:
750b4c3e9b5SBjoern A. Zeeb brcmf_err("unknown chip: %s\n", ci->pub.name);
751b4c3e9b5SBjoern A. Zeeb break;
752b4c3e9b5SBjoern A. Zeeb }
753b4c3e9b5SBjoern A. Zeeb return INVALID_RAMBASE;
754b4c3e9b5SBjoern A. Zeeb }
755b4c3e9b5SBjoern A. Zeeb
brcmf_chip_get_raminfo(struct brcmf_chip * pub)756b4c3e9b5SBjoern A. Zeeb int brcmf_chip_get_raminfo(struct brcmf_chip *pub)
757b4c3e9b5SBjoern A. Zeeb {
758b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv,
759b4c3e9b5SBjoern A. Zeeb pub);
760b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *mem_core;
761b4c3e9b5SBjoern A. Zeeb struct brcmf_core *mem;
762b4c3e9b5SBjoern A. Zeeb
763b4c3e9b5SBjoern A. Zeeb mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4);
764b4c3e9b5SBjoern A. Zeeb if (mem) {
765b4c3e9b5SBjoern A. Zeeb mem_core = container_of(mem, struct brcmf_core_priv, pub);
766b4c3e9b5SBjoern A. Zeeb ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
767b4c3e9b5SBjoern A. Zeeb ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
768b4c3e9b5SBjoern A. Zeeb if (ci->pub.rambase == INVALID_RAMBASE) {
769b4c3e9b5SBjoern A. Zeeb brcmf_err("RAM base not provided with ARM CR4 core\n");
770b4c3e9b5SBjoern A. Zeeb return -EINVAL;
771b4c3e9b5SBjoern A. Zeeb }
772b4c3e9b5SBjoern A. Zeeb } else {
773b4c3e9b5SBjoern A. Zeeb mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM);
774b4c3e9b5SBjoern A. Zeeb if (mem) {
775b4c3e9b5SBjoern A. Zeeb mem_core = container_of(mem, struct brcmf_core_priv,
776b4c3e9b5SBjoern A. Zeeb pub);
777b4c3e9b5SBjoern A. Zeeb ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core);
778b4c3e9b5SBjoern A. Zeeb ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
779b4c3e9b5SBjoern A. Zeeb if (ci->pub.rambase == INVALID_RAMBASE) {
780b4c3e9b5SBjoern A. Zeeb brcmf_err("RAM base not provided with ARM CA7 core\n");
781b4c3e9b5SBjoern A. Zeeb return -EINVAL;
782b4c3e9b5SBjoern A. Zeeb }
783b4c3e9b5SBjoern A. Zeeb } else {
784b4c3e9b5SBjoern A. Zeeb mem = brcmf_chip_get_core(&ci->pub,
785b4c3e9b5SBjoern A. Zeeb BCMA_CORE_INTERNAL_MEM);
786b4c3e9b5SBjoern A. Zeeb if (!mem) {
787b4c3e9b5SBjoern A. Zeeb brcmf_err("No memory cores found\n");
788b4c3e9b5SBjoern A. Zeeb return -ENOMEM;
789b4c3e9b5SBjoern A. Zeeb }
790b4c3e9b5SBjoern A. Zeeb mem_core = container_of(mem, struct brcmf_core_priv,
791b4c3e9b5SBjoern A. Zeeb pub);
792b4c3e9b5SBjoern A. Zeeb brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
793b4c3e9b5SBjoern A. Zeeb &ci->pub.srsize);
794b4c3e9b5SBjoern A. Zeeb }
795b4c3e9b5SBjoern A. Zeeb }
796b4c3e9b5SBjoern A. Zeeb brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
797b4c3e9b5SBjoern A. Zeeb ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
798b4c3e9b5SBjoern A. Zeeb ci->pub.srsize, ci->pub.srsize);
799b4c3e9b5SBjoern A. Zeeb
800b4c3e9b5SBjoern A. Zeeb if (!ci->pub.ramsize) {
801b4c3e9b5SBjoern A. Zeeb brcmf_err("RAM size is undetermined\n");
802b4c3e9b5SBjoern A. Zeeb return -ENOMEM;
803b4c3e9b5SBjoern A. Zeeb }
804b4c3e9b5SBjoern A. Zeeb
805b4c3e9b5SBjoern A. Zeeb if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
806b4c3e9b5SBjoern A. Zeeb brcmf_err("RAM size is incorrect\n");
807b4c3e9b5SBjoern A. Zeeb return -ENOMEM;
808b4c3e9b5SBjoern A. Zeeb }
809b4c3e9b5SBjoern A. Zeeb
810b4c3e9b5SBjoern A. Zeeb return 0;
811b4c3e9b5SBjoern A. Zeeb }
812b4c3e9b5SBjoern A. Zeeb
brcmf_chip_dmp_get_desc(struct brcmf_chip_priv * ci,u32 * eromaddr,u8 * type)813b4c3e9b5SBjoern A. Zeeb static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
814b4c3e9b5SBjoern A. Zeeb u8 *type)
815b4c3e9b5SBjoern A. Zeeb {
816b4c3e9b5SBjoern A. Zeeb u32 val;
817b4c3e9b5SBjoern A. Zeeb
818b4c3e9b5SBjoern A. Zeeb /* read next descriptor */
819b4c3e9b5SBjoern A. Zeeb val = ci->ops->read32(ci->ctx, *eromaddr);
820b4c3e9b5SBjoern A. Zeeb *eromaddr += 4;
821b4c3e9b5SBjoern A. Zeeb
822b4c3e9b5SBjoern A. Zeeb if (!type)
823b4c3e9b5SBjoern A. Zeeb return val;
824b4c3e9b5SBjoern A. Zeeb
825b4c3e9b5SBjoern A. Zeeb /* determine descriptor type */
826b4c3e9b5SBjoern A. Zeeb *type = (val & DMP_DESC_TYPE_MSK);
827b4c3e9b5SBjoern A. Zeeb if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)
828b4c3e9b5SBjoern A. Zeeb *type = DMP_DESC_ADDRESS;
829b4c3e9b5SBjoern A. Zeeb
830b4c3e9b5SBjoern A. Zeeb return val;
831b4c3e9b5SBjoern A. Zeeb }
832b4c3e9b5SBjoern A. Zeeb
brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv * ci,u32 * eromaddr,u32 * regbase,u32 * wrapbase)833b4c3e9b5SBjoern A. Zeeb static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,
834b4c3e9b5SBjoern A. Zeeb u32 *regbase, u32 *wrapbase)
835b4c3e9b5SBjoern A. Zeeb {
836b4c3e9b5SBjoern A. Zeeb u8 desc;
837b4c3e9b5SBjoern A. Zeeb u32 val, szdesc;
838b4c3e9b5SBjoern A. Zeeb u8 stype, sztype, wraptype;
839b4c3e9b5SBjoern A. Zeeb
840b4c3e9b5SBjoern A. Zeeb *regbase = 0;
841b4c3e9b5SBjoern A. Zeeb *wrapbase = 0;
842b4c3e9b5SBjoern A. Zeeb
843b4c3e9b5SBjoern A. Zeeb val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
844b4c3e9b5SBjoern A. Zeeb if (desc == DMP_DESC_MASTER_PORT) {
845b4c3e9b5SBjoern A. Zeeb wraptype = DMP_SLAVE_TYPE_MWRAP;
846b4c3e9b5SBjoern A. Zeeb } else if (desc == DMP_DESC_ADDRESS) {
847b4c3e9b5SBjoern A. Zeeb /* revert erom address */
848b4c3e9b5SBjoern A. Zeeb *eromaddr -= 4;
849b4c3e9b5SBjoern A. Zeeb wraptype = DMP_SLAVE_TYPE_SWRAP;
850b4c3e9b5SBjoern A. Zeeb } else {
851b4c3e9b5SBjoern A. Zeeb *eromaddr -= 4;
852b4c3e9b5SBjoern A. Zeeb return -EILSEQ;
853b4c3e9b5SBjoern A. Zeeb }
854b4c3e9b5SBjoern A. Zeeb
855b4c3e9b5SBjoern A. Zeeb do {
856b4c3e9b5SBjoern A. Zeeb /* locate address descriptor */
857b4c3e9b5SBjoern A. Zeeb do {
858b4c3e9b5SBjoern A. Zeeb val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
859b4c3e9b5SBjoern A. Zeeb /* unexpected table end */
860b4c3e9b5SBjoern A. Zeeb if (desc == DMP_DESC_EOT) {
861b4c3e9b5SBjoern A. Zeeb *eromaddr -= 4;
862b4c3e9b5SBjoern A. Zeeb return -EFAULT;
863b4c3e9b5SBjoern A. Zeeb }
864b4c3e9b5SBjoern A. Zeeb } while (desc != DMP_DESC_ADDRESS &&
865b4c3e9b5SBjoern A. Zeeb desc != DMP_DESC_COMPONENT);
866b4c3e9b5SBjoern A. Zeeb
867b4c3e9b5SBjoern A. Zeeb /* stop if we crossed current component border */
868b4c3e9b5SBjoern A. Zeeb if (desc == DMP_DESC_COMPONENT) {
869b4c3e9b5SBjoern A. Zeeb *eromaddr -= 4;
870b4c3e9b5SBjoern A. Zeeb return 0;
871b4c3e9b5SBjoern A. Zeeb }
872b4c3e9b5SBjoern A. Zeeb
873b4c3e9b5SBjoern A. Zeeb /* skip upper 32-bit address descriptor */
874b4c3e9b5SBjoern A. Zeeb if (val & DMP_DESC_ADDRSIZE_GT32)
875b4c3e9b5SBjoern A. Zeeb brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
876b4c3e9b5SBjoern A. Zeeb
877b4c3e9b5SBjoern A. Zeeb sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;
878b4c3e9b5SBjoern A. Zeeb
879b4c3e9b5SBjoern A. Zeeb /* next size descriptor can be skipped */
880b4c3e9b5SBjoern A. Zeeb if (sztype == DMP_SLAVE_SIZE_DESC) {
881b4c3e9b5SBjoern A. Zeeb szdesc = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
882b4c3e9b5SBjoern A. Zeeb /* skip upper size descriptor if present */
883b4c3e9b5SBjoern A. Zeeb if (szdesc & DMP_DESC_ADDRSIZE_GT32)
884b4c3e9b5SBjoern A. Zeeb brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
885b4c3e9b5SBjoern A. Zeeb }
886b4c3e9b5SBjoern A. Zeeb
887b4c3e9b5SBjoern A. Zeeb /* look for 4K or 8K register regions */
888b4c3e9b5SBjoern A. Zeeb if (sztype != DMP_SLAVE_SIZE_4K &&
889b4c3e9b5SBjoern A. Zeeb sztype != DMP_SLAVE_SIZE_8K)
890b4c3e9b5SBjoern A. Zeeb continue;
891b4c3e9b5SBjoern A. Zeeb
892b4c3e9b5SBjoern A. Zeeb stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;
893b4c3e9b5SBjoern A. Zeeb
894b4c3e9b5SBjoern A. Zeeb /* only regular slave and wrapper */
895b4c3e9b5SBjoern A. Zeeb if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)
896b4c3e9b5SBjoern A. Zeeb *regbase = val & DMP_SLAVE_ADDR_BASE;
897b4c3e9b5SBjoern A. Zeeb if (*wrapbase == 0 && stype == wraptype)
898b4c3e9b5SBjoern A. Zeeb *wrapbase = val & DMP_SLAVE_ADDR_BASE;
899b4c3e9b5SBjoern A. Zeeb } while (*regbase == 0 || *wrapbase == 0);
900b4c3e9b5SBjoern A. Zeeb
901b4c3e9b5SBjoern A. Zeeb return 0;
902b4c3e9b5SBjoern A. Zeeb }
903b4c3e9b5SBjoern A. Zeeb
904b4c3e9b5SBjoern A. Zeeb static
brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv * ci)905b4c3e9b5SBjoern A. Zeeb int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
906b4c3e9b5SBjoern A. Zeeb {
907b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
908b4c3e9b5SBjoern A. Zeeb u32 eromaddr;
909b4c3e9b5SBjoern A. Zeeb u8 desc_type = 0;
910b4c3e9b5SBjoern A. Zeeb u32 val;
911b4c3e9b5SBjoern A. Zeeb u16 id;
912b4c3e9b5SBjoern A. Zeeb u8 nmw, nsw, rev;
913b4c3e9b5SBjoern A. Zeeb u32 base, wrap;
914b4c3e9b5SBjoern A. Zeeb int err;
915b4c3e9b5SBjoern A. Zeeb
916b4c3e9b5SBjoern A. Zeeb eromaddr = ci->ops->read32(ci->ctx,
917b4c3e9b5SBjoern A. Zeeb CORE_CC_REG(ci->pub.enum_base, eromptr));
918b4c3e9b5SBjoern A. Zeeb
919b4c3e9b5SBjoern A. Zeeb while (desc_type != DMP_DESC_EOT) {
920b4c3e9b5SBjoern A. Zeeb val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
921b4c3e9b5SBjoern A. Zeeb if (!(val & DMP_DESC_VALID))
922b4c3e9b5SBjoern A. Zeeb continue;
923b4c3e9b5SBjoern A. Zeeb
924b4c3e9b5SBjoern A. Zeeb if (desc_type == DMP_DESC_EMPTY)
925b4c3e9b5SBjoern A. Zeeb continue;
926b4c3e9b5SBjoern A. Zeeb
927b4c3e9b5SBjoern A. Zeeb /* need a component descriptor */
928b4c3e9b5SBjoern A. Zeeb if (desc_type != DMP_DESC_COMPONENT)
929b4c3e9b5SBjoern A. Zeeb continue;
930b4c3e9b5SBjoern A. Zeeb
931b4c3e9b5SBjoern A. Zeeb id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;
932b4c3e9b5SBjoern A. Zeeb
933b4c3e9b5SBjoern A. Zeeb /* next descriptor must be component as well */
934b4c3e9b5SBjoern A. Zeeb val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
935b4c3e9b5SBjoern A. Zeeb if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))
936b4c3e9b5SBjoern A. Zeeb return -EFAULT;
937b4c3e9b5SBjoern A. Zeeb
938b4c3e9b5SBjoern A. Zeeb /* only look at cores with master port(s) */
939b4c3e9b5SBjoern A. Zeeb nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
940b4c3e9b5SBjoern A. Zeeb nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
941b4c3e9b5SBjoern A. Zeeb rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
942b4c3e9b5SBjoern A. Zeeb
943b4c3e9b5SBjoern A. Zeeb /* need core with ports */
944b4c3e9b5SBjoern A. Zeeb if (nmw + nsw == 0 &&
945b4c3e9b5SBjoern A. Zeeb id != BCMA_CORE_PMU &&
946b4c3e9b5SBjoern A. Zeeb id != BCMA_CORE_GCI)
947b4c3e9b5SBjoern A. Zeeb continue;
948b4c3e9b5SBjoern A. Zeeb
949b4c3e9b5SBjoern A. Zeeb /* try to obtain register address info */
950b4c3e9b5SBjoern A. Zeeb err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);
951b4c3e9b5SBjoern A. Zeeb if (err)
952b4c3e9b5SBjoern A. Zeeb continue;
953b4c3e9b5SBjoern A. Zeeb
954b4c3e9b5SBjoern A. Zeeb /* finally a core to be added */
955b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, id, base, wrap);
956b4c3e9b5SBjoern A. Zeeb if (IS_ERR(core))
957b4c3e9b5SBjoern A. Zeeb return PTR_ERR(core);
958b4c3e9b5SBjoern A. Zeeb
959b4c3e9b5SBjoern A. Zeeb core->rev = rev;
960b4c3e9b5SBjoern A. Zeeb }
961b4c3e9b5SBjoern A. Zeeb
962b4c3e9b5SBjoern A. Zeeb return 0;
963b4c3e9b5SBjoern A. Zeeb }
964b4c3e9b5SBjoern A. Zeeb
brcmf_chip_enum_base(u16 devid)965b4c3e9b5SBjoern A. Zeeb u32 brcmf_chip_enum_base(u16 devid)
966b4c3e9b5SBjoern A. Zeeb {
967b4c3e9b5SBjoern A. Zeeb return SI_ENUM_BASE_DEFAULT;
968b4c3e9b5SBjoern A. Zeeb }
969b4c3e9b5SBjoern A. Zeeb
brcmf_chip_recognition(struct brcmf_chip_priv * ci)970b4c3e9b5SBjoern A. Zeeb static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
971b4c3e9b5SBjoern A. Zeeb {
972b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
973b4c3e9b5SBjoern A. Zeeb u32 regdata;
974b4c3e9b5SBjoern A. Zeeb u32 socitype;
975b4c3e9b5SBjoern A. Zeeb int ret;
976b4c3e9b5SBjoern A. Zeeb const u32 READ_FAILED = 0xFFFFFFFF;
977b4c3e9b5SBjoern A. Zeeb
978b4c3e9b5SBjoern A. Zeeb /* Get CC core rev
979b4c3e9b5SBjoern A. Zeeb * Chipid is assume to be at offset 0 from SI_ENUM_BASE
980b4c3e9b5SBjoern A. Zeeb * For different chiptypes or old sdio hosts w/o chipcommon,
981b4c3e9b5SBjoern A. Zeeb * other ways of recognition should be added here.
982b4c3e9b5SBjoern A. Zeeb */
983b4c3e9b5SBjoern A. Zeeb regdata = ci->ops->read32(ci->ctx,
984b4c3e9b5SBjoern A. Zeeb CORE_CC_REG(ci->pub.enum_base, chipid));
985b4c3e9b5SBjoern A. Zeeb if (regdata == READ_FAILED) {
986b4c3e9b5SBjoern A. Zeeb brcmf_err("MMIO read failed: 0x%08x\n", regdata);
987b4c3e9b5SBjoern A. Zeeb return -ENODEV;
988b4c3e9b5SBjoern A. Zeeb }
989b4c3e9b5SBjoern A. Zeeb
990b4c3e9b5SBjoern A. Zeeb ci->pub.chip = regdata & CID_ID_MASK;
991b4c3e9b5SBjoern A. Zeeb ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
992b4c3e9b5SBjoern A. Zeeb socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
993b4c3e9b5SBjoern A. Zeeb
994b4c3e9b5SBjoern A. Zeeb brcmf_chip_name(ci->pub.chip, ci->pub.chiprev,
995b4c3e9b5SBjoern A. Zeeb ci->pub.name, sizeof(ci->pub.name));
996b4c3e9b5SBjoern A. Zeeb brcmf_dbg(INFO, "found %s chip: %s\n",
997b4c3e9b5SBjoern A. Zeeb socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name);
998b4c3e9b5SBjoern A. Zeeb
999b4c3e9b5SBjoern A. Zeeb if (socitype == SOCI_SB) {
1000b4c3e9b5SBjoern A. Zeeb if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
1001b4c3e9b5SBjoern A. Zeeb brcmf_err("SB chip is not supported\n");
1002b4c3e9b5SBjoern A. Zeeb return -ENODEV;
1003b4c3e9b5SBjoern A. Zeeb }
1004b4c3e9b5SBjoern A. Zeeb ci->iscoreup = brcmf_chip_sb_iscoreup;
1005b4c3e9b5SBjoern A. Zeeb ci->coredisable = brcmf_chip_sb_coredisable;
1006b4c3e9b5SBjoern A. Zeeb ci->resetcore = brcmf_chip_sb_resetcore;
1007b4c3e9b5SBjoern A. Zeeb
1008b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
1009b4c3e9b5SBjoern A. Zeeb SI_ENUM_BASE_DEFAULT, 0);
1010b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_corerev(ci, core);
1011b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
1012b4c3e9b5SBjoern A. Zeeb BCM4329_CORE_BUS_BASE, 0);
1013b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_corerev(ci, core);
1014b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
1015b4c3e9b5SBjoern A. Zeeb BCM4329_CORE_SOCRAM_BASE, 0);
1016b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_corerev(ci, core);
1017b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
1018b4c3e9b5SBjoern A. Zeeb BCM4329_CORE_ARM_BASE, 0);
1019b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_corerev(ci, core);
1020b4c3e9b5SBjoern A. Zeeb
1021b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
1022b4c3e9b5SBjoern A. Zeeb brcmf_chip_sb_corerev(ci, core);
1023b4c3e9b5SBjoern A. Zeeb } else if (socitype == SOCI_AI) {
1024b4c3e9b5SBjoern A. Zeeb ci->iscoreup = brcmf_chip_ai_iscoreup;
1025b4c3e9b5SBjoern A. Zeeb ci->coredisable = brcmf_chip_ai_coredisable;
1026b4c3e9b5SBjoern A. Zeeb ci->resetcore = brcmf_chip_ai_resetcore;
1027b4c3e9b5SBjoern A. Zeeb
1028b4c3e9b5SBjoern A. Zeeb brcmf_chip_dmp_erom_scan(ci);
1029b4c3e9b5SBjoern A. Zeeb } else {
1030b4c3e9b5SBjoern A. Zeeb brcmf_err("chip backplane type %u is not supported\n",
1031b4c3e9b5SBjoern A. Zeeb socitype);
1032b4c3e9b5SBjoern A. Zeeb return -ENODEV;
1033b4c3e9b5SBjoern A. Zeeb }
1034b4c3e9b5SBjoern A. Zeeb
1035b4c3e9b5SBjoern A. Zeeb ret = brcmf_chip_cores_check(ci);
1036b4c3e9b5SBjoern A. Zeeb if (ret)
1037b4c3e9b5SBjoern A. Zeeb return ret;
1038b4c3e9b5SBjoern A. Zeeb
1039b4c3e9b5SBjoern A. Zeeb /* assure chip is passive for core access */
1040b4c3e9b5SBjoern A. Zeeb brcmf_chip_set_passive(&ci->pub);
1041b4c3e9b5SBjoern A. Zeeb
1042b4c3e9b5SBjoern A. Zeeb /* Call bus specific reset function now. Cores have been determined
1043b4c3e9b5SBjoern A. Zeeb * but further access may require a chip specific reset at this point.
1044b4c3e9b5SBjoern A. Zeeb */
1045b4c3e9b5SBjoern A. Zeeb if (ci->ops->reset) {
1046b4c3e9b5SBjoern A. Zeeb ci->ops->reset(ci->ctx, &ci->pub);
1047b4c3e9b5SBjoern A. Zeeb brcmf_chip_set_passive(&ci->pub);
1048b4c3e9b5SBjoern A. Zeeb }
1049b4c3e9b5SBjoern A. Zeeb
1050b4c3e9b5SBjoern A. Zeeb return brcmf_chip_get_raminfo(&ci->pub);
1051b4c3e9b5SBjoern A. Zeeb }
1052b4c3e9b5SBjoern A. Zeeb
brcmf_chip_disable_arm(struct brcmf_chip_priv * chip,u16 id)1053b4c3e9b5SBjoern A. Zeeb static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
1054b4c3e9b5SBjoern A. Zeeb {
1055b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1056b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *cpu;
1057b4c3e9b5SBjoern A. Zeeb u32 val;
1058b4c3e9b5SBjoern A. Zeeb
1059b4c3e9b5SBjoern A. Zeeb
1060b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, id);
1061b4c3e9b5SBjoern A. Zeeb if (!core)
1062b4c3e9b5SBjoern A. Zeeb return;
1063b4c3e9b5SBjoern A. Zeeb
1064b4c3e9b5SBjoern A. Zeeb switch (id) {
1065b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CM3:
1066b4c3e9b5SBjoern A. Zeeb brcmf_chip_coredisable(core, 0, 0);
1067b4c3e9b5SBjoern A. Zeeb break;
1068b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CR4:
1069b4c3e9b5SBjoern A. Zeeb case BCMA_CORE_ARM_CA7:
1070b4c3e9b5SBjoern A. Zeeb cpu = container_of(core, struct brcmf_core_priv, pub);
1071b4c3e9b5SBjoern A. Zeeb
1072b4c3e9b5SBjoern A. Zeeb /* clear all IOCTL bits except HALT bit */
1073b4c3e9b5SBjoern A. Zeeb val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);
1074b4c3e9b5SBjoern A. Zeeb val &= ARMCR4_BCMA_IOCTL_CPUHALT;
1075b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
1076b4c3e9b5SBjoern A. Zeeb ARMCR4_BCMA_IOCTL_CPUHALT);
1077b4c3e9b5SBjoern A. Zeeb break;
1078b4c3e9b5SBjoern A. Zeeb default:
1079b4c3e9b5SBjoern A. Zeeb brcmf_err("unknown id: %u\n", id);
1080b4c3e9b5SBjoern A. Zeeb break;
1081b4c3e9b5SBjoern A. Zeeb }
1082b4c3e9b5SBjoern A. Zeeb }
1083b4c3e9b5SBjoern A. Zeeb
brcmf_chip_setup(struct brcmf_chip_priv * chip)1084b4c3e9b5SBjoern A. Zeeb static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
1085b4c3e9b5SBjoern A. Zeeb {
1086b4c3e9b5SBjoern A. Zeeb struct brcmf_chip *pub;
1087b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *cc;
1088b4c3e9b5SBjoern A. Zeeb struct brcmf_core *pmu;
1089b4c3e9b5SBjoern A. Zeeb u32 base;
1090b4c3e9b5SBjoern A. Zeeb u32 val;
1091b4c3e9b5SBjoern A. Zeeb int ret = 0;
1092b4c3e9b5SBjoern A. Zeeb
1093b4c3e9b5SBjoern A. Zeeb pub = &chip->pub;
1094b4c3e9b5SBjoern A. Zeeb cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
1095b4c3e9b5SBjoern A. Zeeb base = cc->pub.base;
1096b4c3e9b5SBjoern A. Zeeb
1097b4c3e9b5SBjoern A. Zeeb /* get chipcommon capabilites */
1098b4c3e9b5SBjoern A. Zeeb pub->cc_caps = chip->ops->read32(chip->ctx,
1099b4c3e9b5SBjoern A. Zeeb CORE_CC_REG(base, capabilities));
1100b4c3e9b5SBjoern A. Zeeb pub->cc_caps_ext = chip->ops->read32(chip->ctx,
1101b4c3e9b5SBjoern A. Zeeb CORE_CC_REG(base,
1102b4c3e9b5SBjoern A. Zeeb capabilities_ext));
1103b4c3e9b5SBjoern A. Zeeb
1104b4c3e9b5SBjoern A. Zeeb /* get pmu caps & rev */
1105b4c3e9b5SBjoern A. Zeeb pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */
1106b4c3e9b5SBjoern A. Zeeb if (pub->cc_caps & CC_CAP_PMU) {
1107b4c3e9b5SBjoern A. Zeeb val = chip->ops->read32(chip->ctx,
1108b4c3e9b5SBjoern A. Zeeb CORE_CC_REG(pmu->base, pmucapabilities));
1109b4c3e9b5SBjoern A. Zeeb pub->pmurev = val & PCAP_REV_MASK;
1110b4c3e9b5SBjoern A. Zeeb pub->pmucaps = val;
1111b4c3e9b5SBjoern A. Zeeb }
1112b4c3e9b5SBjoern A. Zeeb
1113b4c3e9b5SBjoern A. Zeeb brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",
1114b4c3e9b5SBjoern A. Zeeb cc->pub.rev, pub->pmurev, pub->pmucaps);
1115b4c3e9b5SBjoern A. Zeeb
1116b4c3e9b5SBjoern A. Zeeb /* execute bus core specific setup */
1117b4c3e9b5SBjoern A. Zeeb if (chip->ops->setup)
1118b4c3e9b5SBjoern A. Zeeb ret = chip->ops->setup(chip->ctx, pub);
1119b4c3e9b5SBjoern A. Zeeb
1120b4c3e9b5SBjoern A. Zeeb return ret;
1121b4c3e9b5SBjoern A. Zeeb }
1122b4c3e9b5SBjoern A. Zeeb
brcmf_chip_attach(void * ctx,u16 devid,const struct brcmf_buscore_ops * ops)1123b4c3e9b5SBjoern A. Zeeb struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
1124b4c3e9b5SBjoern A. Zeeb const struct brcmf_buscore_ops *ops)
1125b4c3e9b5SBjoern A. Zeeb {
1126b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1127b4c3e9b5SBjoern A. Zeeb int err = 0;
1128b4c3e9b5SBjoern A. Zeeb
1129b4c3e9b5SBjoern A. Zeeb if (WARN_ON(!ops->read32))
1130b4c3e9b5SBjoern A. Zeeb err = -EINVAL;
1131b4c3e9b5SBjoern A. Zeeb if (WARN_ON(!ops->write32))
1132b4c3e9b5SBjoern A. Zeeb err = -EINVAL;
1133b4c3e9b5SBjoern A. Zeeb if (WARN_ON(!ops->prepare))
1134b4c3e9b5SBjoern A. Zeeb err = -EINVAL;
1135b4c3e9b5SBjoern A. Zeeb if (WARN_ON(!ops->activate))
1136b4c3e9b5SBjoern A. Zeeb err = -EINVAL;
1137b4c3e9b5SBjoern A. Zeeb if (err < 0)
1138b4c3e9b5SBjoern A. Zeeb return ERR_PTR(-EINVAL);
1139b4c3e9b5SBjoern A. Zeeb
1140b4c3e9b5SBjoern A. Zeeb chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1141b4c3e9b5SBjoern A. Zeeb if (!chip)
1142b4c3e9b5SBjoern A. Zeeb return ERR_PTR(-ENOMEM);
1143b4c3e9b5SBjoern A. Zeeb
1144b4c3e9b5SBjoern A. Zeeb INIT_LIST_HEAD(&chip->cores);
1145b4c3e9b5SBjoern A. Zeeb chip->num_cores = 0;
1146b4c3e9b5SBjoern A. Zeeb chip->ops = ops;
1147b4c3e9b5SBjoern A. Zeeb chip->ctx = ctx;
1148b4c3e9b5SBjoern A. Zeeb chip->pub.enum_base = brcmf_chip_enum_base(devid);
1149b4c3e9b5SBjoern A. Zeeb
1150b4c3e9b5SBjoern A. Zeeb err = ops->prepare(ctx);
1151b4c3e9b5SBjoern A. Zeeb if (err < 0)
1152b4c3e9b5SBjoern A. Zeeb goto fail;
1153b4c3e9b5SBjoern A. Zeeb
1154b4c3e9b5SBjoern A. Zeeb err = brcmf_chip_recognition(chip);
1155b4c3e9b5SBjoern A. Zeeb if (err < 0)
1156b4c3e9b5SBjoern A. Zeeb goto fail;
1157b4c3e9b5SBjoern A. Zeeb
1158b4c3e9b5SBjoern A. Zeeb err = brcmf_chip_setup(chip);
1159b4c3e9b5SBjoern A. Zeeb if (err < 0)
1160b4c3e9b5SBjoern A. Zeeb goto fail;
1161b4c3e9b5SBjoern A. Zeeb
1162b4c3e9b5SBjoern A. Zeeb return &chip->pub;
1163b4c3e9b5SBjoern A. Zeeb
1164b4c3e9b5SBjoern A. Zeeb fail:
1165b4c3e9b5SBjoern A. Zeeb brcmf_chip_detach(&chip->pub);
1166b4c3e9b5SBjoern A. Zeeb return ERR_PTR(err);
1167b4c3e9b5SBjoern A. Zeeb }
1168b4c3e9b5SBjoern A. Zeeb
brcmf_chip_detach(struct brcmf_chip * pub)1169b4c3e9b5SBjoern A. Zeeb void brcmf_chip_detach(struct brcmf_chip *pub)
1170b4c3e9b5SBjoern A. Zeeb {
1171b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1172b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1173b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *tmp;
1174b4c3e9b5SBjoern A. Zeeb
1175b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1176b4c3e9b5SBjoern A. Zeeb list_for_each_entry_safe(core, tmp, &chip->cores, list) {
1177b4c3e9b5SBjoern A. Zeeb list_del(&core->list);
1178b4c3e9b5SBjoern A. Zeeb kfree(core);
1179b4c3e9b5SBjoern A. Zeeb }
1180b4c3e9b5SBjoern A. Zeeb kfree(chip);
1181b4c3e9b5SBjoern A. Zeeb }
1182b4c3e9b5SBjoern A. Zeeb
brcmf_chip_get_d11core(struct brcmf_chip * pub,u8 unit)1183b4c3e9b5SBjoern A. Zeeb struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit)
1184b4c3e9b5SBjoern A. Zeeb {
1185b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1186b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1187b4c3e9b5SBjoern A. Zeeb
1188b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1189b4c3e9b5SBjoern A. Zeeb list_for_each_entry(core, &chip->cores, list) {
1190b4c3e9b5SBjoern A. Zeeb if (core->pub.id == BCMA_CORE_80211) {
1191b4c3e9b5SBjoern A. Zeeb if (unit-- == 0)
1192b4c3e9b5SBjoern A. Zeeb return &core->pub;
1193b4c3e9b5SBjoern A. Zeeb }
1194b4c3e9b5SBjoern A. Zeeb }
1195b4c3e9b5SBjoern A. Zeeb return NULL;
1196b4c3e9b5SBjoern A. Zeeb }
1197b4c3e9b5SBjoern A. Zeeb
brcmf_chip_get_core(struct brcmf_chip * pub,u16 coreid)1198b4c3e9b5SBjoern A. Zeeb struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid)
1199b4c3e9b5SBjoern A. Zeeb {
1200b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1201b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1202b4c3e9b5SBjoern A. Zeeb
1203b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1204b4c3e9b5SBjoern A. Zeeb list_for_each_entry(core, &chip->cores, list)
1205b4c3e9b5SBjoern A. Zeeb if (core->pub.id == coreid)
1206b4c3e9b5SBjoern A. Zeeb return &core->pub;
1207b4c3e9b5SBjoern A. Zeeb
1208b4c3e9b5SBjoern A. Zeeb return NULL;
1209b4c3e9b5SBjoern A. Zeeb }
1210b4c3e9b5SBjoern A. Zeeb
brcmf_chip_get_chipcommon(struct brcmf_chip * pub)1211b4c3e9b5SBjoern A. Zeeb struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub)
1212b4c3e9b5SBjoern A. Zeeb {
1213b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1214b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *cc;
1215b4c3e9b5SBjoern A. Zeeb
1216b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1217b4c3e9b5SBjoern A. Zeeb cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
1218b4c3e9b5SBjoern A. Zeeb if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON))
1219b4c3e9b5SBjoern A. Zeeb return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON);
1220b4c3e9b5SBjoern A. Zeeb return &cc->pub;
1221b4c3e9b5SBjoern A. Zeeb }
1222b4c3e9b5SBjoern A. Zeeb
brcmf_chip_get_pmu(struct brcmf_chip * pub)1223b4c3e9b5SBjoern A. Zeeb struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)
1224b4c3e9b5SBjoern A. Zeeb {
1225b4c3e9b5SBjoern A. Zeeb struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);
1226b4c3e9b5SBjoern A. Zeeb struct brcmf_core *pmu;
1227b4c3e9b5SBjoern A. Zeeb
1228b4c3e9b5SBjoern A. Zeeb /* See if there is separated PMU core available */
1229b4c3e9b5SBjoern A. Zeeb if (cc->rev >= 35 &&
1230b4c3e9b5SBjoern A. Zeeb pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
1231b4c3e9b5SBjoern A. Zeeb pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);
1232b4c3e9b5SBjoern A. Zeeb if (pmu)
1233b4c3e9b5SBjoern A. Zeeb return pmu;
1234b4c3e9b5SBjoern A. Zeeb }
1235b4c3e9b5SBjoern A. Zeeb
1236b4c3e9b5SBjoern A. Zeeb /* Fallback to ChipCommon core for older hardware */
1237b4c3e9b5SBjoern A. Zeeb return cc;
1238b4c3e9b5SBjoern A. Zeeb }
1239b4c3e9b5SBjoern A. Zeeb
brcmf_chip_iscoreup(struct brcmf_core * pub)1240b4c3e9b5SBjoern A. Zeeb bool brcmf_chip_iscoreup(struct brcmf_core *pub)
1241b4c3e9b5SBjoern A. Zeeb {
1242b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1243b4c3e9b5SBjoern A. Zeeb
1244b4c3e9b5SBjoern A. Zeeb core = container_of(pub, struct brcmf_core_priv, pub);
1245b4c3e9b5SBjoern A. Zeeb return core->chip->iscoreup(core);
1246b4c3e9b5SBjoern A. Zeeb }
1247b4c3e9b5SBjoern A. Zeeb
brcmf_chip_coredisable(struct brcmf_core * pub,u32 prereset,u32 reset)1248b4c3e9b5SBjoern A. Zeeb void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset)
1249b4c3e9b5SBjoern A. Zeeb {
1250b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1251b4c3e9b5SBjoern A. Zeeb
1252b4c3e9b5SBjoern A. Zeeb core = container_of(pub, struct brcmf_core_priv, pub);
1253b4c3e9b5SBjoern A. Zeeb core->chip->coredisable(core, prereset, reset);
1254b4c3e9b5SBjoern A. Zeeb }
1255b4c3e9b5SBjoern A. Zeeb
brcmf_chip_resetcore(struct brcmf_core * pub,u32 prereset,u32 reset,u32 postreset)1256b4c3e9b5SBjoern A. Zeeb void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset,
1257b4c3e9b5SBjoern A. Zeeb u32 postreset)
1258b4c3e9b5SBjoern A. Zeeb {
1259b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *core;
1260b4c3e9b5SBjoern A. Zeeb
1261b4c3e9b5SBjoern A. Zeeb core = container_of(pub, struct brcmf_core_priv, pub);
1262b4c3e9b5SBjoern A. Zeeb core->chip->resetcore(core, prereset, reset, postreset);
1263b4c3e9b5SBjoern A. Zeeb }
1264b4c3e9b5SBjoern A. Zeeb
1265b4c3e9b5SBjoern A. Zeeb static void
brcmf_chip_cm3_set_passive(struct brcmf_chip_priv * chip)1266b4c3e9b5SBjoern A. Zeeb brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)
1267b4c3e9b5SBjoern A. Zeeb {
1268b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1269b4c3e9b5SBjoern A. Zeeb struct brcmf_core_priv *sr;
1270b4c3e9b5SBjoern A. Zeeb
1271b4c3e9b5SBjoern A. Zeeb brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
1272b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
1273b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
1274b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN,
1275b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN,
1276b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN);
1277b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
1278b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, 0, 0, 0);
1279b4c3e9b5SBjoern A. Zeeb
1280b4c3e9b5SBjoern A. Zeeb /* disable bank #3 remap for this device */
1281b4c3e9b5SBjoern A. Zeeb if (chip->pub.chip == BRCM_CC_43430_CHIP_ID ||
1282b4c3e9b5SBjoern A. Zeeb chip->pub.chip == CY_CC_43439_CHIP_ID) {
1283b4c3e9b5SBjoern A. Zeeb sr = container_of(core, struct brcmf_core_priv, pub);
1284b4c3e9b5SBjoern A. Zeeb brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3);
1285b4c3e9b5SBjoern A. Zeeb brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0);
1286b4c3e9b5SBjoern A. Zeeb }
1287b4c3e9b5SBjoern A. Zeeb }
1288b4c3e9b5SBjoern A. Zeeb
brcmf_chip_cm3_set_active(struct brcmf_chip_priv * chip)1289b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
1290b4c3e9b5SBjoern A. Zeeb {
1291b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1292b4c3e9b5SBjoern A. Zeeb
1293b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
1294b4c3e9b5SBjoern A. Zeeb if (!brcmf_chip_iscoreup(core)) {
1295b4c3e9b5SBjoern A. Zeeb brcmf_err("SOCRAM core is down after reset?\n");
1296b4c3e9b5SBjoern A. Zeeb return false;
1297b4c3e9b5SBjoern A. Zeeb }
1298b4c3e9b5SBjoern A. Zeeb
1299b4c3e9b5SBjoern A. Zeeb chip->ops->activate(chip->ctx, &chip->pub, 0);
1300b4c3e9b5SBjoern A. Zeeb
1301b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);
1302b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, 0, 0, 0);
1303b4c3e9b5SBjoern A. Zeeb
1304b4c3e9b5SBjoern A. Zeeb return true;
1305b4c3e9b5SBjoern A. Zeeb }
1306b4c3e9b5SBjoern A. Zeeb
1307b4c3e9b5SBjoern A. Zeeb static inline void
brcmf_chip_cr4_set_passive(struct brcmf_chip_priv * chip)1308b4c3e9b5SBjoern A. Zeeb brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
1309b4c3e9b5SBjoern A. Zeeb {
1310b4c3e9b5SBjoern A. Zeeb int i;
1311b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1312b4c3e9b5SBjoern A. Zeeb
1313b4c3e9b5SBjoern A. Zeeb brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
1314b4c3e9b5SBjoern A. Zeeb
1315b4c3e9b5SBjoern A. Zeeb /* Disable the cores only and let the firmware enable them.
1316b4c3e9b5SBjoern A. Zeeb * Releasing reset ourselves breaks BCM4387 in weird ways.
1317b4c3e9b5SBjoern A. Zeeb */
1318b4c3e9b5SBjoern A. Zeeb for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++)
1319b4c3e9b5SBjoern A. Zeeb brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET |
1320b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN,
1321b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN);
1322b4c3e9b5SBjoern A. Zeeb }
1323b4c3e9b5SBjoern A. Zeeb
brcmf_chip_cr4_set_active(struct brcmf_chip_priv * chip,u32 rstvec)1324b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
1325b4c3e9b5SBjoern A. Zeeb {
1326b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1327b4c3e9b5SBjoern A. Zeeb
1328b4c3e9b5SBjoern A. Zeeb chip->ops->activate(chip->ctx, &chip->pub, rstvec);
1329b4c3e9b5SBjoern A. Zeeb
1330b4c3e9b5SBjoern A. Zeeb /* restore ARM */
1331b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);
1332b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
1333b4c3e9b5SBjoern A. Zeeb
1334b4c3e9b5SBjoern A. Zeeb return true;
1335b4c3e9b5SBjoern A. Zeeb }
1336b4c3e9b5SBjoern A. Zeeb
1337b4c3e9b5SBjoern A. Zeeb static inline void
brcmf_chip_ca7_set_passive(struct brcmf_chip_priv * chip)1338b4c3e9b5SBjoern A. Zeeb brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip)
1339b4c3e9b5SBjoern A. Zeeb {
1340b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1341b4c3e9b5SBjoern A. Zeeb
1342b4c3e9b5SBjoern A. Zeeb brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7);
1343b4c3e9b5SBjoern A. Zeeb
1344b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
1345b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
1346b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN,
1347b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN,
1348b4c3e9b5SBjoern A. Zeeb D11_BCMA_IOCTL_PHYCLOCKEN);
1349b4c3e9b5SBjoern A. Zeeb }
1350b4c3e9b5SBjoern A. Zeeb
brcmf_chip_ca7_set_active(struct brcmf_chip_priv * chip,u32 rstvec)1351b4c3e9b5SBjoern A. Zeeb static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
1352b4c3e9b5SBjoern A. Zeeb {
1353b4c3e9b5SBjoern A. Zeeb struct brcmf_core *core;
1354b4c3e9b5SBjoern A. Zeeb
1355b4c3e9b5SBjoern A. Zeeb chip->ops->activate(chip->ctx, &chip->pub, rstvec);
1356b4c3e9b5SBjoern A. Zeeb
1357b4c3e9b5SBjoern A. Zeeb /* restore ARM */
1358b4c3e9b5SBjoern A. Zeeb core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7);
1359b4c3e9b5SBjoern A. Zeeb brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
1360b4c3e9b5SBjoern A. Zeeb
1361b4c3e9b5SBjoern A. Zeeb return true;
1362b4c3e9b5SBjoern A. Zeeb }
1363b4c3e9b5SBjoern A. Zeeb
brcmf_chip_set_passive(struct brcmf_chip * pub)1364b4c3e9b5SBjoern A. Zeeb void brcmf_chip_set_passive(struct brcmf_chip *pub)
1365b4c3e9b5SBjoern A. Zeeb {
1366b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1367b4c3e9b5SBjoern A. Zeeb struct brcmf_core *arm;
1368b4c3e9b5SBjoern A. Zeeb
1369b4c3e9b5SBjoern A. Zeeb brcmf_dbg(TRACE, "Enter\n");
1370b4c3e9b5SBjoern A. Zeeb
1371b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1372b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
1373b4c3e9b5SBjoern A. Zeeb if (arm) {
1374b4c3e9b5SBjoern A. Zeeb brcmf_chip_cr4_set_passive(chip);
1375b4c3e9b5SBjoern A. Zeeb return;
1376b4c3e9b5SBjoern A. Zeeb }
1377b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
1378b4c3e9b5SBjoern A. Zeeb if (arm) {
1379b4c3e9b5SBjoern A. Zeeb brcmf_chip_ca7_set_passive(chip);
1380b4c3e9b5SBjoern A. Zeeb return;
1381b4c3e9b5SBjoern A. Zeeb }
1382b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
1383b4c3e9b5SBjoern A. Zeeb if (arm) {
1384b4c3e9b5SBjoern A. Zeeb brcmf_chip_cm3_set_passive(chip);
1385b4c3e9b5SBjoern A. Zeeb return;
1386b4c3e9b5SBjoern A. Zeeb }
1387b4c3e9b5SBjoern A. Zeeb }
1388b4c3e9b5SBjoern A. Zeeb
brcmf_chip_set_active(struct brcmf_chip * pub,u32 rstvec)1389b4c3e9b5SBjoern A. Zeeb bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
1390b4c3e9b5SBjoern A. Zeeb {
1391b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1392b4c3e9b5SBjoern A. Zeeb struct brcmf_core *arm;
1393b4c3e9b5SBjoern A. Zeeb
1394b4c3e9b5SBjoern A. Zeeb brcmf_dbg(TRACE, "Enter\n");
1395b4c3e9b5SBjoern A. Zeeb
1396b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1397b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
1398b4c3e9b5SBjoern A. Zeeb if (arm)
1399b4c3e9b5SBjoern A. Zeeb return brcmf_chip_cr4_set_active(chip, rstvec);
1400b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
1401b4c3e9b5SBjoern A. Zeeb if (arm)
1402b4c3e9b5SBjoern A. Zeeb return brcmf_chip_ca7_set_active(chip, rstvec);
1403b4c3e9b5SBjoern A. Zeeb arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
1404b4c3e9b5SBjoern A. Zeeb if (arm)
1405b4c3e9b5SBjoern A. Zeeb return brcmf_chip_cm3_set_active(chip);
1406b4c3e9b5SBjoern A. Zeeb
1407b4c3e9b5SBjoern A. Zeeb return false;
1408b4c3e9b5SBjoern A. Zeeb }
1409b4c3e9b5SBjoern A. Zeeb
brcmf_chip_sr_capable(struct brcmf_chip * pub)1410b4c3e9b5SBjoern A. Zeeb bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
1411b4c3e9b5SBjoern A. Zeeb {
1412b4c3e9b5SBjoern A. Zeeb u32 base, addr, reg, pmu_cc3_mask = ~0;
1413b4c3e9b5SBjoern A. Zeeb struct brcmf_chip_priv *chip;
1414b4c3e9b5SBjoern A. Zeeb struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);
1415b4c3e9b5SBjoern A. Zeeb
1416b4c3e9b5SBjoern A. Zeeb brcmf_dbg(TRACE, "Enter\n");
1417b4c3e9b5SBjoern A. Zeeb
1418b4c3e9b5SBjoern A. Zeeb /* old chips with PMU version less than 17 don't support save restore */
1419b4c3e9b5SBjoern A. Zeeb if (pub->pmurev < 17)
1420b4c3e9b5SBjoern A. Zeeb return false;
1421b4c3e9b5SBjoern A. Zeeb
1422b4c3e9b5SBjoern A. Zeeb base = brcmf_chip_get_chipcommon(pub)->base;
1423b4c3e9b5SBjoern A. Zeeb chip = container_of(pub, struct brcmf_chip_priv, pub);
1424b4c3e9b5SBjoern A. Zeeb
1425b4c3e9b5SBjoern A. Zeeb switch (pub->chip) {
1426b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4354_CHIP_ID:
1427b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4356_CHIP_ID:
1428b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4345_CHIP_ID:
1429b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43454_CHIP_ID:
1430b4c3e9b5SBjoern A. Zeeb /* explicitly check SR engine enable bit */
1431b4c3e9b5SBjoern A. Zeeb pmu_cc3_mask = BIT(2);
1432b4c3e9b5SBjoern A. Zeeb fallthrough;
1433b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43241_CHIP_ID:
1434b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4335_CHIP_ID:
1435b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4339_CHIP_ID:
1436b4c3e9b5SBjoern A. Zeeb /* read PMU chipcontrol register 3 */
1437b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
1438b4c3e9b5SBjoern A. Zeeb chip->ops->write32(chip->ctx, addr, 3);
1439b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(pmu->base, chipcontrol_data);
1440b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1441b4c3e9b5SBjoern A. Zeeb return (reg & pmu_cc3_mask) != 0;
1442b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43430_CHIP_ID:
1443b4c3e9b5SBjoern A. Zeeb case CY_CC_43439_CHIP_ID:
1444b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(base, sr_control1);
1445b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1446b4c3e9b5SBjoern A. Zeeb return reg != 0;
1447b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4355_CHIP_ID:
1448b4c3e9b5SBjoern A. Zeeb case CY_CC_4373_CHIP_ID:
1449b4c3e9b5SBjoern A. Zeeb /* explicitly check SR engine enable bit */
1450b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(base, sr_control0);
1451b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1452b4c3e9b5SBjoern A. Zeeb return (reg & CC_SR_CTL0_ENABLE_MASK) != 0;
1453b4c3e9b5SBjoern A. Zeeb case BRCM_CC_4359_CHIP_ID:
1454b4c3e9b5SBjoern A. Zeeb case BRCM_CC_43751_CHIP_ID:
1455*9375e11fSBjoern A. Zeeb case BRCM_CC_43752_CHIP_ID:
1456b4c3e9b5SBjoern A. Zeeb case CY_CC_43012_CHIP_ID:
1457b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(pmu->base, retention_ctl);
1458b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1459b4c3e9b5SBjoern A. Zeeb return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
1460b4c3e9b5SBjoern A. Zeeb PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
1461b4c3e9b5SBjoern A. Zeeb default:
1462b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
1463b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1464b4c3e9b5SBjoern A. Zeeb if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
1465b4c3e9b5SBjoern A. Zeeb return false;
1466b4c3e9b5SBjoern A. Zeeb
1467b4c3e9b5SBjoern A. Zeeb addr = CORE_CC_REG(pmu->base, retention_ctl);
1468b4c3e9b5SBjoern A. Zeeb reg = chip->ops->read32(chip->ctx, addr);
1469b4c3e9b5SBjoern A. Zeeb return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
1470b4c3e9b5SBjoern A. Zeeb PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
1471b4c3e9b5SBjoern A. Zeeb }
1472b4c3e9b5SBjoern A. Zeeb }
1473