xref: /freebsd/sys/contrib/dev/broadcom/brcm80211/brcmfmac/chip.c (revision 9375e11f079d725d42c5b431de33044088ad14f7)
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