Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmsmac/aiutils.c
178665 views
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
19
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21
#include <linux/delay.h>
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"
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 strength 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
318
#define IS_SIM(chippkg) \
319
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
320
321
#define GOODCOREADDR(x, b) \
322
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
323
IS_ALIGNED((x), SI_CORE_SIZE))
324
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
443
static bool
444
ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
445
{
446
/* no cores found, bail out */
447
if (cc->bus->nr_cores == 0)
448
return false;
449
450
/* get chipcommon rev */
451
sii->pub.ccrev = cc->id.rev;
452
453
/* get chipcommon chipstatus */
454
sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
455
456
/* get chipcommon capabilities */
457
sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
458
459
/* get pmu rev and caps */
460
if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
461
sii->pub.pmucaps = bcma_read32(cc,
462
CHIPCREGOFFS(pmucapabilities));
463
sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
464
}
465
466
return true;
467
}
468
469
static struct si_info *ai_doattach(struct si_info *sii,
470
struct bcma_bus *pbus)
471
{
472
struct si_pub *sih = &sii->pub;
473
struct bcma_device *cc;
474
475
sii->icbus = pbus;
476
sii->pcibus = pbus->host_pci;
477
478
/* switch to Chipcommon core */
479
cc = pbus->drv_cc.core;
480
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;
486
487
if (!ai_buscore_setup(sii, cc))
488
goto exit;
489
490
/* === NVRAM, clock is ready === */
491
bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
492
bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
493
494
/* PMU specific initializations */
495
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
496
(void)si_pmu_measure_alpclk(sih);
497
}
498
499
return sii;
500
501
exit:
502
503
return NULL;
504
}
505
506
/*
507
* Allocate a si handle and do the attach.
508
*/
509
struct si_pub *
510
ai_attach(struct bcma_bus *pbus)
511
{
512
struct si_info *sii;
513
514
/* alloc struct si_info */
515
sii = kzalloc(sizeof(*sii), GFP_ATOMIC);
516
if (sii == NULL)
517
return NULL;
518
519
if (ai_doattach(sii, pbus) == NULL) {
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
532
sii = container_of(sih, struct si_info, pub);
533
534
kfree(sii);
535
}
536
537
/*
538
* read/modify chipcommon core register.
539
*/
540
uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
541
{
542
struct bcma_device *cc;
543
u32 w;
544
struct si_info *sii;
545
546
sii = container_of(sih, struct si_info, pub);
547
cc = sii->icbus->drv_cc.core;
548
549
/* mask and set */
550
if (mask || val)
551
bcma_maskset32(cc, regoff, ~mask, val);
552
553
/* readback */
554
w = bcma_read32(cc, regoff);
555
556
return w;
557
}
558
559
/* return the slow clock source - LPO, XTAL, or PCI */
560
static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
561
{
562
return SCC_SS_XTAL;
563
}
564
565
/*
566
* return the ILP (slowclock) min or max frequency
567
* precondition: we've established the chip has dynamic clk control
568
*/
569
static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
570
struct bcma_device *cc)
571
{
572
uint div;
573
574
/* Chipc rev 10 is InstaClock */
575
div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
576
div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
577
return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
578
}
579
580
static void
581
ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
582
{
583
uint slowmaxfreq, pll_delay, slowclk;
584
uint pll_on_delay, fref_sel_delay;
585
586
pll_delay = PLL_DELAY;
587
588
/*
589
* If the slow clock is not sourced by the xtal then
590
* add the xtal_on_delay since the xtal will also be
591
* powered down by dynamic clk control logic.
592
*/
593
594
slowclk = ai_slowclk_src(sih, cc);
595
if (slowclk != SCC_SS_XTAL)
596
pll_delay += XTAL_ON_DELAY;
597
598
/* Starting with 4318 it is ILP that is used for the delays */
599
slowmaxfreq =
600
ai_slowclk_freq(sih, false, cc);
601
602
pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
603
fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
604
605
bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay);
606
bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay);
607
}
608
609
/* initialize power control delay registers */
610
void ai_clkctl_init(struct si_pub *sih)
611
{
612
struct si_info *sii = container_of(sih, struct si_info, pub);
613
struct bcma_device *cc;
614
615
if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
616
return;
617
618
cc = sii->icbus->drv_cc.core;
619
if (cc == NULL)
620
return;
621
622
/* set all Instaclk chip ILP to 1 MHz */
623
bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
624
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
625
626
ai_clkctl_setdelay(sih, cc);
627
}
628
629
/*
630
* return the value suitable for writing to the
631
* dot11 core FAST_PWRUP_DELAY register
632
*/
633
u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
634
{
635
struct si_info *sii;
636
struct bcma_device *cc;
637
uint slowminfreq;
638
u16 fpdelay;
639
640
sii = container_of(sih, struct si_info, pub);
641
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
642
fpdelay = si_pmu_fast_pwrup_delay(sih);
643
return fpdelay;
644
}
645
646
if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
647
return 0;
648
649
fpdelay = 0;
650
cc = sii->icbus->drv_cc.core;
651
if (cc) {
652
slowminfreq = ai_slowclk_freq(sih, false, cc);
653
fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
654
* 1000000) + (slowminfreq - 1)) / slowminfreq;
655
}
656
return fpdelay;
657
}
658
659
/*
660
* clock control policy function through chipcommon
661
*
662
* set dynamic clk control mode (forceslow, forcefast, dynamic)
663
* returns true if we are forcing fast clock
664
* this is a wrapper over the next internal function
665
* to allow flexible policy settings for outside caller
666
*/
667
bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
668
{
669
struct si_info *sii;
670
struct bcma_device *cc;
671
672
sii = container_of(sih, struct si_info, pub);
673
674
cc = sii->icbus->drv_cc.core;
675
bcma_core_set_clockmode(cc, mode);
676
return mode == BCMA_CLKMODE_FAST;
677
}
678
679
/* Enable BT-COEX & Ex-PA for 4313 */
680
void ai_epa_4313war(struct si_pub *sih)
681
{
682
struct si_info *sii = container_of(sih, struct si_info, pub);
683
struct bcma_device *cc;
684
685
cc = sii->icbus->drv_cc.core;
686
687
/* EPA Fix */
688
bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
689
}
690
691
/* check if the device is removed */
692
bool ai_deviceremoved(struct si_pub *sih)
693
{
694
u32 w = 0;
695
struct si_info *sii;
696
697
sii = container_of(sih, struct si_info, pub);
698
699
if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
700
return false;
701
702
pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
703
if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
704
return true;
705
706
return false;
707
}
708
709