Commit | Line | Data |
---|---|---|
5b435de0 AS |
1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | * | |
16 | * File contents: support functions for PCI/PCIe | |
17 | */ | |
18 | ||
8505a7e6 JP |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | ||
5b435de0 | 21 | #include <linux/delay.h> |
5b435de0 AS |
22 | |
23 | #include <defs.h> | |
24 | #include <chipcommon.h> | |
25 | #include <brcmu_utils.h> | |
26 | #include <brcm_hw_ids.h> | |
27 | #include <soc.h> | |
28 | #include "types.h" | |
29 | #include "pub.h" | |
30 | #include "pmu.h" | |
5b435de0 AS |
31 | #include "aiutils.h" |
32 | ||
33 | /* slow_clk_ctl */ | |
34 | /* slow clock source mask */ | |
35 | #define SCC_SS_MASK 0x00000007 | |
36 | /* source of slow clock is LPO */ | |
37 | #define SCC_SS_LPO 0x00000000 | |
38 | /* source of slow clock is crystal */ | |
39 | #define SCC_SS_XTAL 0x00000001 | |
40 | /* source of slow clock is PCI */ | |
41 | #define SCC_SS_PCI 0x00000002 | |
42 | /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ | |
43 | #define SCC_LF 0x00000200 | |
44 | /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ | |
45 | #define SCC_LP 0x00000400 | |
46 | /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ | |
47 | #define SCC_FS 0x00000800 | |
48 | /* IgnorePllOffReq, 1/0: | |
49 | * power logic ignores/honors PLL clock disable requests from core | |
50 | */ | |
51 | #define SCC_IP 0x00001000 | |
52 | /* XtalControlEn, 1/0: | |
53 | * power logic does/doesn't disable crystal when appropriate | |
54 | */ | |
55 | #define SCC_XC 0x00002000 | |
56 | /* XtalPU (RO), 1/0: crystal running/disabled */ | |
57 | #define SCC_XP 0x00004000 | |
58 | /* ClockDivider (SlowClk = 1/(4+divisor)) */ | |
59 | #define SCC_CD_MASK 0xffff0000 | |
60 | #define SCC_CD_SHIFT 16 | |
61 | ||
62 | /* system_clk_ctl */ | |
63 | /* ILPen: Enable Idle Low Power */ | |
64 | #define SYCC_IE 0x00000001 | |
65 | /* ALPen: Enable Active Low Power */ | |
66 | #define SYCC_AE 0x00000002 | |
67 | /* ForcePLLOn */ | |
68 | #define SYCC_FP 0x00000004 | |
69 | /* Force ALP (or HT if ALPen is not set */ | |
70 | #define SYCC_AR 0x00000008 | |
71 | /* Force HT */ | |
72 | #define SYCC_HR 0x00000010 | |
73 | /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ | |
74 | #define SYCC_CD_MASK 0xffff0000 | |
75 | #define SYCC_CD_SHIFT 16 | |
76 | ||
77 | #define CST4329_SPROM_OTP_SEL_MASK 0x00000003 | |
78 | /* OTP is powered up, use def. CIS, no SPROM */ | |
79 | #define CST4329_DEFCIS_SEL 0 | |
80 | /* OTP is powered up, SPROM is present */ | |
81 | #define CST4329_SPROM_SEL 1 | |
82 | /* OTP is powered up, no SPROM */ | |
83 | #define CST4329_OTP_SEL 2 | |
84 | /* OTP is powered down, SPROM is present */ | |
85 | #define CST4329_OTP_PWRDN 3 | |
86 | ||
87 | #define CST4329_SPI_SDIO_MODE_MASK 0x00000004 | |
88 | #define CST4329_SPI_SDIO_MODE_SHIFT 2 | |
89 | ||
90 | /* 43224 chip-specific ChipControl register bits */ | |
91 | #define CCTRL43224_GPIO_TOGGLE 0x8000 | |
92 | /* 12 mA drive strength */ | |
93 | #define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 | |
94 | /* 12 mA drive strength for later 43224s */ | |
95 | #define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 | |
96 | ||
97 | /* 43236 Chip specific ChipStatus register bits */ | |
98 | #define CST43236_SFLASH_MASK 0x00000040 | |
99 | #define CST43236_OTP_MASK 0x00000080 | |
100 | #define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ | |
101 | #define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ | |
102 | #define CST43236_BOOT_MASK 0x00001800 | |
103 | #define CST43236_BOOT_SHIFT 11 | |
104 | #define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ | |
105 | #define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ | |
106 | #define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ | |
107 | #define CST43236_BOOT_FROM_INVALID 3 | |
108 | ||
109 | /* 4331 chip-specific ChipControl register bits */ | |
110 | /* 0 disable */ | |
111 | #define CCTRL4331_BT_COEXIST (1<<0) | |
112 | /* 0 SECI is disabled (JTAG functional) */ | |
113 | #define CCTRL4331_SECI (1<<1) | |
114 | /* 0 disable */ | |
115 | #define CCTRL4331_EXT_LNA (1<<2) | |
116 | /* sprom/gpio13-15 mux */ | |
117 | #define CCTRL4331_SPROM_GPIO13_15 (1<<3) | |
118 | /* 0 ext pa disable, 1 ext pa enabled */ | |
119 | #define CCTRL4331_EXTPA_EN (1<<4) | |
120 | /* set drive out GPIO_CLK on sprom_cs pin */ | |
121 | #define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) | |
122 | /* use sprom_cs pin as PCIE mdio interface */ | |
123 | #define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) | |
124 | /* aband extpa will be at gpio2/5 and sprom_dout */ | |
125 | #define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) | |
126 | /* override core control on pipe_AuxClkEnable */ | |
127 | #define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) | |
128 | /* override core control on pipe_AuxPowerDown */ | |
129 | #define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) | |
130 | /* pcie_auxclkenable */ | |
131 | #define CCTRL4331_PCIE_AUXCLKEN (1<<10) | |
132 | /* pcie_pipe_pllpowerdown */ | |
133 | #define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) | |
134 | /* enable bt_shd0 at gpio4 */ | |
135 | #define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) | |
136 | /* enable bt_shd1 at gpio5 */ | |
137 | #define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) | |
138 | ||
139 | /* 4331 Chip specific ChipStatus register bits */ | |
140 | /* crystal frequency 20/40Mhz */ | |
141 | #define CST4331_XTAL_FREQ 0x00000001 | |
142 | #define CST4331_SPROM_PRESENT 0x00000002 | |
143 | #define CST4331_OTP_PRESENT 0x00000004 | |
144 | #define CST4331_LDO_RF 0x00000008 | |
145 | #define CST4331_LDO_PAR 0x00000010 | |
146 | ||
147 | /* 4319 chip-specific ChipStatus register bits */ | |
148 | #define CST4319_SPI_CPULESSUSB 0x00000001 | |
149 | #define CST4319_SPI_CLK_POL 0x00000002 | |
150 | #define CST4319_SPI_CLK_PH 0x00000008 | |
151 | /* gpio [7:6], SDIO CIS selection */ | |
152 | #define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 | |
153 | #define CST4319_SPROM_OTP_SEL_SHIFT 6 | |
154 | /* use default CIS, OTP is powered up */ | |
155 | #define CST4319_DEFCIS_SEL 0x00000000 | |
156 | /* use SPROM, OTP is powered up */ | |
157 | #define CST4319_SPROM_SEL 0x00000040 | |
158 | /* use OTP, OTP is powered up */ | |
159 | #define CST4319_OTP_SEL 0x00000080 | |
160 | /* use SPROM, OTP is powered down */ | |
161 | #define CST4319_OTP_PWRDN 0x000000c0 | |
162 | /* gpio [8], sdio/usb mode */ | |
163 | #define CST4319_SDIO_USB_MODE 0x00000100 | |
164 | #define CST4319_REMAP_SEL_MASK 0x00000600 | |
165 | #define CST4319_ILPDIV_EN 0x00000800 | |
166 | #define CST4319_XTAL_PD_POL 0x00001000 | |
167 | #define CST4319_LPO_SEL 0x00002000 | |
168 | #define CST4319_RES_INIT_MODE 0x0000c000 | |
169 | /* PALDO is configured with external PNP */ | |
170 | #define CST4319_PALDO_EXTPNP 0x00010000 | |
171 | #define CST4319_CBUCK_MODE_MASK 0x00060000 | |
172 | #define CST4319_CBUCK_MODE_BURST 0x00020000 | |
173 | #define CST4319_CBUCK_MODE_LPBURST 0x00060000 | |
174 | #define CST4319_RCAL_VALID 0x01000000 | |
175 | #define CST4319_RCAL_VALUE_MASK 0x3e000000 | |
176 | #define CST4319_RCAL_VALUE_SHIFT 25 | |
177 | ||
178 | /* 4336 chip-specific ChipStatus register bits */ | |
179 | #define CST4336_SPI_MODE_MASK 0x00000001 | |
180 | #define CST4336_SPROM_PRESENT 0x00000002 | |
181 | #define CST4336_OTP_PRESENT 0x00000004 | |
182 | #define CST4336_ARMREMAP_0 0x00000008 | |
183 | #define CST4336_ILPDIV_EN_MASK 0x00000010 | |
184 | #define CST4336_ILPDIV_EN_SHIFT 4 | |
185 | #define CST4336_XTAL_PD_POL_MASK 0x00000020 | |
186 | #define CST4336_XTAL_PD_POL_SHIFT 5 | |
187 | #define CST4336_LPO_SEL_MASK 0x00000040 | |
188 | #define CST4336_LPO_SEL_SHIFT 6 | |
189 | #define CST4336_RES_INIT_MODE_MASK 0x00000180 | |
190 | #define CST4336_RES_INIT_MODE_SHIFT 7 | |
191 | #define CST4336_CBUCK_MODE_MASK 0x00000600 | |
192 | #define CST4336_CBUCK_MODE_SHIFT 9 | |
193 | ||
194 | /* 4313 chip-specific ChipStatus register bits */ | |
195 | #define CST4313_SPROM_PRESENT 1 | |
196 | #define CST4313_OTP_PRESENT 2 | |
197 | #define CST4313_SPROM_OTP_SEL_MASK 0x00000002 | |
198 | #define CST4313_SPROM_OTP_SEL_SHIFT 0 | |
199 | ||
200 | /* 4313 Chip specific ChipControl register bits */ | |
201 | /* 12 mA drive strengh for later 4313 */ | |
202 | #define CCTRL_4313_12MA_LED_DRIVE 0x00000007 | |
203 | ||
204 | /* Manufacturer Ids */ | |
205 | #define MFGID_ARM 0x43b | |
206 | #define MFGID_BRCM 0x4bf | |
207 | #define MFGID_MIPS 0x4a7 | |
208 | ||
209 | /* Enumeration ROM registers */ | |
210 | #define ER_EROMENTRY 0x000 | |
211 | #define ER_REMAPCONTROL 0xe00 | |
212 | #define ER_REMAPSELECT 0xe04 | |
213 | #define ER_MASTERSELECT 0xe10 | |
214 | #define ER_ITCR 0xf00 | |
215 | #define ER_ITIP 0xf04 | |
216 | ||
217 | /* Erom entries */ | |
218 | #define ER_TAG 0xe | |
219 | #define ER_TAG1 0x6 | |
220 | #define ER_VALID 1 | |
221 | #define ER_CI 0 | |
222 | #define ER_MP 2 | |
223 | #define ER_ADD 4 | |
224 | #define ER_END 0xe | |
225 | #define ER_BAD 0xffffffff | |
226 | ||
227 | /* EROM CompIdentA */ | |
228 | #define CIA_MFG_MASK 0xfff00000 | |
229 | #define CIA_MFG_SHIFT 20 | |
230 | #define CIA_CID_MASK 0x000fff00 | |
231 | #define CIA_CID_SHIFT 8 | |
232 | #define CIA_CCL_MASK 0x000000f0 | |
233 | #define CIA_CCL_SHIFT 4 | |
234 | ||
235 | /* EROM CompIdentB */ | |
236 | #define CIB_REV_MASK 0xff000000 | |
237 | #define CIB_REV_SHIFT 24 | |
238 | #define CIB_NSW_MASK 0x00f80000 | |
239 | #define CIB_NSW_SHIFT 19 | |
240 | #define CIB_NMW_MASK 0x0007c000 | |
241 | #define CIB_NMW_SHIFT 14 | |
242 | #define CIB_NSP_MASK 0x00003e00 | |
243 | #define CIB_NSP_SHIFT 9 | |
244 | #define CIB_NMP_MASK 0x000001f0 | |
245 | #define CIB_NMP_SHIFT 4 | |
246 | ||
247 | /* EROM AddrDesc */ | |
248 | #define AD_ADDR_MASK 0xfffff000 | |
249 | #define AD_SP_MASK 0x00000f00 | |
250 | #define AD_SP_SHIFT 8 | |
251 | #define AD_ST_MASK 0x000000c0 | |
252 | #define AD_ST_SHIFT 6 | |
253 | #define AD_ST_SLAVE 0x00000000 | |
254 | #define AD_ST_BRIDGE 0x00000040 | |
255 | #define AD_ST_SWRAP 0x00000080 | |
256 | #define AD_ST_MWRAP 0x000000c0 | |
257 | #define AD_SZ_MASK 0x00000030 | |
258 | #define AD_SZ_SHIFT 4 | |
259 | #define AD_SZ_4K 0x00000000 | |
260 | #define AD_SZ_8K 0x00000010 | |
261 | #define AD_SZ_16K 0x00000020 | |
262 | #define AD_SZ_SZD 0x00000030 | |
263 | #define AD_AG32 0x00000008 | |
264 | #define AD_ADDR_ALIGN 0x00000fff | |
265 | #define AD_SZ_BASE 0x00001000 /* 4KB */ | |
266 | ||
267 | /* EROM SizeDesc */ | |
268 | #define SD_SZ_MASK 0xfffff000 | |
269 | #define SD_SG32 0x00000008 | |
270 | #define SD_SZ_ALIGN 0x00000fff | |
271 | ||
272 | /* PCI config space bit 4 for 4306c0 slow clock source */ | |
273 | #define PCI_CFG_GPIO_SCS 0x10 | |
274 | /* PCI config space GPIO 14 for Xtal power-up */ | |
275 | #define PCI_CFG_GPIO_XTAL 0x40 | |
276 | /* PCI config space GPIO 15 for PLL power-down */ | |
277 | #define PCI_CFG_GPIO_PLL 0x80 | |
278 | ||
279 | /* power control defines */ | |
280 | #define PLL_DELAY 150 /* us pll on delay */ | |
281 | #define FREF_DELAY 200 /* us fref change delay */ | |
282 | #define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ | |
283 | ||
284 | /* resetctrl */ | |
285 | #define AIRC_RESET 1 | |
286 | ||
287 | #define NOREV -1 /* Invalid rev */ | |
288 | ||
289 | /* GPIO Based LED powersave defines */ | |
290 | #define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ | |
291 | #define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ | |
292 | ||
293 | /* When Srom support present, fields in sromcontrol */ | |
294 | #define SRC_START 0x80000000 | |
295 | #define SRC_BUSY 0x80000000 | |
296 | #define SRC_OPCODE 0x60000000 | |
297 | #define SRC_OP_READ 0x00000000 | |
298 | #define SRC_OP_WRITE 0x20000000 | |
299 | #define SRC_OP_WRDIS 0x40000000 | |
300 | #define SRC_OP_WREN 0x60000000 | |
301 | #define SRC_OTPSEL 0x00000010 | |
302 | #define SRC_LOCK 0x00000008 | |
303 | #define SRC_SIZE_MASK 0x00000006 | |
304 | #define SRC_SIZE_1K 0x00000000 | |
305 | #define SRC_SIZE_4K 0x00000002 | |
306 | #define SRC_SIZE_16K 0x00000004 | |
307 | #define SRC_SIZE_SHIFT 1 | |
308 | #define SRC_PRESENT 0x00000001 | |
309 | ||
310 | /* External PA enable mask */ | |
311 | #define GPIO_CTRL_EPA_EN_MASK 0x40 | |
312 | ||
313 | #define DEFAULT_GPIOTIMERVAL \ | |
314 | ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) | |
315 | ||
316 | #define BADIDX (SI_MAXCORES + 1) | |
317 | ||
5b435de0 AS |
318 | #define IS_SIM(chippkg) \ |
319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | |
320 | ||
5b435de0 AS |
321 | #define GOODCOREADDR(x, b) \ |
322 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ | |
323 | IS_ALIGNED((x), SI_CORE_SIZE)) | |
324 | ||
5b435de0 AS |
325 | struct aidmp { |
326 | u32 oobselina30; /* 0x000 */ | |
327 | u32 oobselina74; /* 0x004 */ | |
328 | u32 PAD[6]; | |
329 | u32 oobselinb30; /* 0x020 */ | |
330 | u32 oobselinb74; /* 0x024 */ | |
331 | u32 PAD[6]; | |
332 | u32 oobselinc30; /* 0x040 */ | |
333 | u32 oobselinc74; /* 0x044 */ | |
334 | u32 PAD[6]; | |
335 | u32 oobselind30; /* 0x060 */ | |
336 | u32 oobselind74; /* 0x064 */ | |
337 | u32 PAD[38]; | |
338 | u32 oobselouta30; /* 0x100 */ | |
339 | u32 oobselouta74; /* 0x104 */ | |
340 | u32 PAD[6]; | |
341 | u32 oobseloutb30; /* 0x120 */ | |
342 | u32 oobseloutb74; /* 0x124 */ | |
343 | u32 PAD[6]; | |
344 | u32 oobseloutc30; /* 0x140 */ | |
345 | u32 oobseloutc74; /* 0x144 */ | |
346 | u32 PAD[6]; | |
347 | u32 oobseloutd30; /* 0x160 */ | |
348 | u32 oobseloutd74; /* 0x164 */ | |
349 | u32 PAD[38]; | |
350 | u32 oobsynca; /* 0x200 */ | |
351 | u32 oobseloutaen; /* 0x204 */ | |
352 | u32 PAD[6]; | |
353 | u32 oobsyncb; /* 0x220 */ | |
354 | u32 oobseloutben; /* 0x224 */ | |
355 | u32 PAD[6]; | |
356 | u32 oobsyncc; /* 0x240 */ | |
357 | u32 oobseloutcen; /* 0x244 */ | |
358 | u32 PAD[6]; | |
359 | u32 oobsyncd; /* 0x260 */ | |
360 | u32 oobseloutden; /* 0x264 */ | |
361 | u32 PAD[38]; | |
362 | u32 oobaextwidth; /* 0x300 */ | |
363 | u32 oobainwidth; /* 0x304 */ | |
364 | u32 oobaoutwidth; /* 0x308 */ | |
365 | u32 PAD[5]; | |
366 | u32 oobbextwidth; /* 0x320 */ | |
367 | u32 oobbinwidth; /* 0x324 */ | |
368 | u32 oobboutwidth; /* 0x328 */ | |
369 | u32 PAD[5]; | |
370 | u32 oobcextwidth; /* 0x340 */ | |
371 | u32 oobcinwidth; /* 0x344 */ | |
372 | u32 oobcoutwidth; /* 0x348 */ | |
373 | u32 PAD[5]; | |
374 | u32 oobdextwidth; /* 0x360 */ | |
375 | u32 oobdinwidth; /* 0x364 */ | |
376 | u32 oobdoutwidth; /* 0x368 */ | |
377 | u32 PAD[37]; | |
378 | u32 ioctrlset; /* 0x400 */ | |
379 | u32 ioctrlclear; /* 0x404 */ | |
380 | u32 ioctrl; /* 0x408 */ | |
381 | u32 PAD[61]; | |
382 | u32 iostatus; /* 0x500 */ | |
383 | u32 PAD[127]; | |
384 | u32 ioctrlwidth; /* 0x700 */ | |
385 | u32 iostatuswidth; /* 0x704 */ | |
386 | u32 PAD[62]; | |
387 | u32 resetctrl; /* 0x800 */ | |
388 | u32 resetstatus; /* 0x804 */ | |
389 | u32 resetreadid; /* 0x808 */ | |
390 | u32 resetwriteid; /* 0x80c */ | |
391 | u32 PAD[60]; | |
392 | u32 errlogctrl; /* 0x900 */ | |
393 | u32 errlogdone; /* 0x904 */ | |
394 | u32 errlogstatus; /* 0x908 */ | |
395 | u32 errlogaddrlo; /* 0x90c */ | |
396 | u32 errlogaddrhi; /* 0x910 */ | |
397 | u32 errlogid; /* 0x914 */ | |
398 | u32 errloguser; /* 0x918 */ | |
399 | u32 errlogflags; /* 0x91c */ | |
400 | u32 PAD[56]; | |
401 | u32 intstatus; /* 0xa00 */ | |
402 | u32 PAD[127]; | |
403 | u32 config; /* 0xe00 */ | |
404 | u32 PAD[63]; | |
405 | u32 itcr; /* 0xf00 */ | |
406 | u32 PAD[3]; | |
407 | u32 itipooba; /* 0xf10 */ | |
408 | u32 itipoobb; /* 0xf14 */ | |
409 | u32 itipoobc; /* 0xf18 */ | |
410 | u32 itipoobd; /* 0xf1c */ | |
411 | u32 PAD[4]; | |
412 | u32 itipoobaout; /* 0xf30 */ | |
413 | u32 itipoobbout; /* 0xf34 */ | |
414 | u32 itipoobcout; /* 0xf38 */ | |
415 | u32 itipoobdout; /* 0xf3c */ | |
416 | u32 PAD[4]; | |
417 | u32 itopooba; /* 0xf50 */ | |
418 | u32 itopoobb; /* 0xf54 */ | |
419 | u32 itopoobc; /* 0xf58 */ | |
420 | u32 itopoobd; /* 0xf5c */ | |
421 | u32 PAD[4]; | |
422 | u32 itopoobain; /* 0xf70 */ | |
423 | u32 itopoobbin; /* 0xf74 */ | |
424 | u32 itopoobcin; /* 0xf78 */ | |
425 | u32 itopoobdin; /* 0xf7c */ | |
426 | u32 PAD[4]; | |
427 | u32 itopreset; /* 0xf90 */ | |
428 | u32 PAD[15]; | |
429 | u32 peripherialid4; /* 0xfd0 */ | |
430 | u32 peripherialid5; /* 0xfd4 */ | |
431 | u32 peripherialid6; /* 0xfd8 */ | |
432 | u32 peripherialid7; /* 0xfdc */ | |
433 | u32 peripherialid0; /* 0xfe0 */ | |
434 | u32 peripherialid1; /* 0xfe4 */ | |
435 | u32 peripherialid2; /* 0xfe8 */ | |
436 | u32 peripherialid3; /* 0xfec */ | |
437 | u32 componentid0; /* 0xff0 */ | |
438 | u32 componentid1; /* 0xff4 */ | |
439 | u32 componentid2; /* 0xff8 */ | |
440 | u32 componentid3; /* 0xffc */ | |
441 | }; | |
442 | ||
5b435de0 | 443 | static bool |
c8086745 | 444 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) |
5b435de0 | 445 | { |
99559f13 AS |
446 | /* no cores found, bail out */ |
447 | if (cc->bus->nr_cores == 0) | |
448 | return false; | |
449 | ||
5b435de0 | 450 | /* get chipcommon rev */ |
c8086745 | 451 | sii->pub.ccrev = cc->id.rev; |
5b435de0 AS |
452 | |
453 | /* get chipcommon chipstatus */ | |
d43c1c52 | 454 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); |
5b435de0 AS |
455 | |
456 | /* get chipcommon capabilites */ | |
c8086745 | 457 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); |
5b435de0 AS |
458 | |
459 | /* get pmu rev and caps */ | |
b2ffec46 | 460 | if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) { |
c8086745 AS |
461 | sii->pub.pmucaps = bcma_read32(cc, |
462 | CHIPCREGOFFS(pmucapabilities)); | |
5b435de0 AS |
463 | sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; |
464 | } | |
465 | ||
5b435de0 AS |
466 | return true; |
467 | } | |
468 | ||
5b435de0 | 469 | static struct si_info *ai_doattach(struct si_info *sii, |
28a53442 | 470 | struct bcma_bus *pbus) |
5b435de0 AS |
471 | { |
472 | struct si_pub *sih = &sii->pub; | |
c8086745 | 473 | struct bcma_device *cc; |
5b435de0 | 474 | |
28a53442 | 475 | sii->icbus = pbus; |
28a53442 | 476 | sii->pcibus = pbus->host_pci; |
5b435de0 | 477 | |
16d2812e | 478 | /* switch to Chipcommon core */ |
c8086745 | 479 | cc = pbus->drv_cc.core; |
5b435de0 | 480 | |
1928ad71 HM |
481 | sih->chip = pbus->chipinfo.id; |
482 | sih->chiprev = pbus->chipinfo.rev; | |
483 | sih->chippkg = pbus->chipinfo.pkg; | |
484 | sih->boardvendor = pbus->boardinfo.vendor; | |
485 | sih->boardtype = pbus->boardinfo.type; | |
5b435de0 | 486 | |
c8086745 | 487 | if (!ai_buscore_setup(sii, cc)) |
5b435de0 AS |
488 | goto exit; |
489 | ||
5b435de0 | 490 | /* === NVRAM, clock is ready === */ |
c8086745 AS |
491 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); |
492 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); | |
5b435de0 AS |
493 | |
494 | /* PMU specific initializations */ | |
b2ffec46 | 495 | if (ai_get_cccaps(sih) & CC_CAP_PMU) { |
291ed3dc | 496 | (void)si_pmu_measure_alpclk(sih); |
5b435de0 AS |
497 | } |
498 | ||
5b435de0 AS |
499 | return sii; |
500 | ||
501 | exit: | |
5b435de0 AS |
502 | |
503 | return NULL; | |
504 | } | |
505 | ||
506 | /* | |
28a53442 | 507 | * Allocate a si handle and do the attach. |
5b435de0 AS |
508 | */ |
509 | struct si_pub * | |
28a53442 | 510 | ai_attach(struct bcma_bus *pbus) |
5b435de0 AS |
511 | { |
512 | struct si_info *sii; | |
513 | ||
514 | /* alloc struct si_info */ | |
00d2ec0c | 515 | sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC); |
5b435de0 AS |
516 | if (sii == NULL) |
517 | return NULL; | |
518 | ||
28a53442 | 519 | if (ai_doattach(sii, pbus) == NULL) { |
5b435de0 AS |
520 | kfree(sii); |
521 | return NULL; | |
522 | } | |
523 | ||
524 | return (struct si_pub *) sii; | |
525 | } | |
526 | ||
527 | /* may be called with core in reset */ | |
528 | void ai_detach(struct si_pub *sih) | |
529 | { | |
530 | struct si_info *sii; | |
531 | ||
ed1dd814 | 532 | sii = container_of(sih, struct si_info, pub); |
5b435de0 AS |
533 | |
534 | if (sii == NULL) | |
535 | return; | |
536 | ||
5b435de0 AS |
537 | kfree(sii); |
538 | } | |
539 | ||
5b435de0 | 540 | /* |
3b758a68 | 541 | * read/modify chipcommon core register. |
5b435de0 | 542 | */ |
7d8e18e4 | 543 | uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) |
5b435de0 | 544 | { |
7d8e18e4 | 545 | struct bcma_device *cc; |
7d8e18e4 | 546 | u32 w; |
5b435de0 AS |
547 | struct si_info *sii; |
548 | ||
ed1dd814 | 549 | sii = container_of(sih, struct si_info, pub); |
7d8e18e4 | 550 | cc = sii->icbus->drv_cc.core; |
5b435de0 | 551 | |
5b435de0 | 552 | /* mask and set */ |
2b0446c4 | 553 | if (mask || val) |
7d8e18e4 | 554 | bcma_maskset32(cc, regoff, ~mask, val); |
5b435de0 AS |
555 | |
556 | /* readback */ | |
7d8e18e4 | 557 | w = bcma_read32(cc, regoff); |
5b435de0 | 558 | |
5b435de0 AS |
559 | return w; |
560 | } | |
561 | ||
5b435de0 | 562 | /* return the slow clock source - LPO, XTAL, or PCI */ |
c8086745 | 563 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) |
5b435de0 | 564 | { |
d43c1c52 | 565 | return SCC_SS_XTAL; |
5b435de0 AS |
566 | } |
567 | ||
568 | /* | |
569 | * return the ILP (slowclock) min or max frequency | |
570 | * precondition: we've established the chip has dynamic clk control | |
571 | */ | |
c8086745 AS |
572 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, |
573 | struct bcma_device *cc) | |
5b435de0 | 574 | { |
5b435de0 AS |
575 | uint div; |
576 | ||
d43c1c52 HM |
577 | /* Chipc rev 10 is InstaClock */ |
578 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); | |
579 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); | |
580 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); | |
5b435de0 AS |
581 | } |
582 | ||
583 | static void | |
c8086745 | 584 | ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) |
5b435de0 AS |
585 | { |
586 | uint slowmaxfreq, pll_delay, slowclk; | |
587 | uint pll_on_delay, fref_sel_delay; | |
588 | ||
589 | pll_delay = PLL_DELAY; | |
590 | ||
591 | /* | |
592 | * If the slow clock is not sourced by the xtal then | |
593 | * add the xtal_on_delay since the xtal will also be | |
594 | * powered down by dynamic clk control logic. | |
595 | */ | |
596 | ||
c8086745 | 597 | slowclk = ai_slowclk_src(sih, cc); |
5b435de0 AS |
598 | if (slowclk != SCC_SS_XTAL) |
599 | pll_delay += XTAL_ON_DELAY; | |
600 | ||
601 | /* Starting with 4318 it is ILP that is used for the delays */ | |
602 | slowmaxfreq = | |
d43c1c52 | 603 | ai_slowclk_freq(sih, false, cc); |
5b435de0 AS |
604 | |
605 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; | |
606 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; | |
607 | ||
c8086745 AS |
608 | bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay); |
609 | bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay); | |
5b435de0 AS |
610 | } |
611 | ||
612 | /* initialize power control delay registers */ | |
613 | void ai_clkctl_init(struct si_pub *sih) | |
614 | { | |
40bd94ce | 615 | struct si_info *sii = container_of(sih, struct si_info, pub); |
c8086745 | 616 | struct bcma_device *cc; |
5b435de0 | 617 | |
b2ffec46 | 618 | if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) |
5b435de0 AS |
619 | return; |
620 | ||
40bd94ce | 621 | cc = sii->icbus->drv_cc.core; |
ad5db131 AS |
622 | if (cc == NULL) |
623 | return; | |
5b435de0 AS |
624 | |
625 | /* set all Instaclk chip ILP to 1 MHz */ | |
d43c1c52 HM |
626 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, |
627 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); | |
5b435de0 | 628 | |
c8086745 | 629 | ai_clkctl_setdelay(sih, cc); |
5b435de0 AS |
630 | } |
631 | ||
632 | /* | |
633 | * return the value suitable for writing to the | |
634 | * dot11 core FAST_PWRUP_DELAY register | |
635 | */ | |
636 | u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) | |
637 | { | |
638 | struct si_info *sii; | |
c8086745 | 639 | struct bcma_device *cc; |
5b435de0 AS |
640 | uint slowminfreq; |
641 | u16 fpdelay; | |
5b435de0 | 642 | |
ed1dd814 | 643 | sii = container_of(sih, struct si_info, pub); |
b2ffec46 | 644 | if (ai_get_cccaps(sih) & CC_CAP_PMU) { |
5b435de0 | 645 | fpdelay = si_pmu_fast_pwrup_delay(sih); |
5b435de0 AS |
646 | return fpdelay; |
647 | } | |
648 | ||
b2ffec46 | 649 | if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) |
5b435de0 AS |
650 | return 0; |
651 | ||
5b435de0 | 652 | fpdelay = 0; |
40bd94ce | 653 | cc = sii->icbus->drv_cc.core; |
a232c8a1 AS |
654 | if (cc) { |
655 | slowminfreq = ai_slowclk_freq(sih, false, cc); | |
656 | fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2) | |
657 | * 1000000) + (slowminfreq - 1)) / slowminfreq; | |
658 | } | |
5b435de0 AS |
659 | return fpdelay; |
660 | } | |
661 | ||
5b435de0 AS |
662 | /* |
663 | * clock control policy function throught chipcommon | |
664 | * | |
665 | * set dynamic clk control mode (forceslow, forcefast, dynamic) | |
666 | * returns true if we are forcing fast clock | |
667 | * this is a wrapper over the next internal function | |
668 | * to allow flexible policy settings for outside caller | |
669 | */ | |
712e3c1f | 670 | bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) |
5b435de0 AS |
671 | { |
672 | struct si_info *sii; | |
712e3c1f | 673 | struct bcma_device *cc; |
5b435de0 | 674 | |
ed1dd814 | 675 | sii = container_of(sih, struct si_info, pub); |
5b435de0 | 676 | |
40bd94ce | 677 | cc = sii->icbus->drv_cc.core; |
712e3c1f HM |
678 | bcma_core_set_clockmode(cc, mode); |
679 | return mode == BCMA_CLKMODE_FAST; | |
5b435de0 AS |
680 | } |
681 | ||
5b435de0 AS |
682 | /* Enable BT-COEX & Ex-PA for 4313 */ |
683 | void ai_epa_4313war(struct si_pub *sih) | |
684 | { | |
40bd94ce | 685 | struct si_info *sii = container_of(sih, struct si_info, pub); |
c8086745 | 686 | struct bcma_device *cc; |
5b435de0 | 687 | |
40bd94ce | 688 | cc = sii->icbus->drv_cc.core; |
5b435de0 AS |
689 | |
690 | /* EPA Fix */ | |
c8086745 | 691 | bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK); |
5b435de0 AS |
692 | } |
693 | ||
694 | /* check if the device is removed */ | |
695 | bool ai_deviceremoved(struct si_pub *sih) | |
696 | { | |
d8df4901 | 697 | u32 w = 0; |
5b435de0 AS |
698 | struct si_info *sii; |
699 | ||
ed1dd814 | 700 | sii = container_of(sih, struct si_info, pub); |
5b435de0 | 701 | |
22291cea HM |
702 | if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) |
703 | return false; | |
704 | ||
cbc80db2 | 705 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); |
5b435de0 AS |
706 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) |
707 | return true; | |
708 | ||
709 | return false; | |
710 | } |