2 * Copyright (c) 2011 Broadcom Corporation
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.
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.
16 /* ***** SDIO interface chip backplane handle functions ***** */
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <linux/mmc/card.h>
21 #include <linux/mmc/sdio_func.h>
22 #include <linux/mmc/sdio_ids.h>
23 #include <linux/ssb/ssb_regs.h>
24 #include <linux/bcma/bcma.h>
26 #include <chipcommon.h>
27 #include <brcm_hw_ids.h>
28 #include <brcmu_wifi.h>
29 #include <brcmu_utils.h>
32 #include "sdio_host.h"
33 #include "sdio_chip.h"
35 /* chip core base & ramsize */
37 /* SDIO device core, ID 0x829 */
38 #define BCM4329_CORE_BUS_BASE 0x18011000
39 /* internal memory core, ID 0x80e */
40 #define BCM4329_CORE_SOCRAM_BASE 0x18003000
41 /* ARM Cortex M3 core, ID 0x82a */
42 #define BCM4329_CORE_ARM_BASE 0x18002000
43 #define BCM4329_RAMSIZE 0x48000
46 /* SDIO device core */
47 #define BCM43143_CORE_BUS_BASE 0x18002000
48 /* internal memory core */
49 #define BCM43143_CORE_SOCRAM_BASE 0x18004000
50 /* ARM Cortex M3 core, ID 0x82a */
51 #define BCM43143_CORE_ARM_BASE 0x18003000
52 #define BCM43143_RAMSIZE 0x70000
54 /* All D11 cores, ID 0x812 */
55 #define BCM43xx_CORE_D11_BASE 0x18001000
57 #define SBCOREREV(sbidh) \
58 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
59 ((sbidh) & SSB_IDHIGH_RCLO))
61 /* SOC Interconnect types (aka chip types) */
66 #define CIB_REV_MASK 0xff000000
67 #define CIB_REV_SHIFT 24
69 /* ARM CR4 core specific control flag bits */
70 #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
72 /* D11 core specific control flag bits */
73 #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
74 #define D11_BCMA_IOCTL_PHYRESET 0x0008
76 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
77 /* SDIO Pad drive strength to select value mappings */
78 struct sdiod_drive_str
{
79 u8 strength
; /* Pad Drive Strength in mA */
80 u8 sel
; /* Chip-specific select value */
82 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
83 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8
[] = {
94 /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
95 static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8
[] = {
105 /* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
106 static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8
[] = {
112 /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
113 static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3
[] = {
121 brcmf_sdio_chip_getinfidx(struct brcmf_chip
*ci
, u16 coreid
)
125 for (idx
= 0; idx
< BRCMF_MAX_CORENUM
; idx
++)
126 if (coreid
== ci
->c_inf
[idx
].id
)
129 return BRCMF_MAX_CORENUM
;
133 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev
*sdiodev
,
134 struct brcmf_chip
*ci
, u16 coreid
)
139 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
141 regdata
= brcmf_sdiod_regrl(sdiodev
,
142 CORE_SB(ci
->c_inf
[idx
].base
, sbidhigh
),
144 return SBCOREREV(regdata
);
148 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev
*sdiodev
,
149 struct brcmf_chip
*ci
, u16 coreid
)
153 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
155 return (ci
->c_inf
[idx
].cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
159 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
160 struct brcmf_chip
*ci
, u16 coreid
)
165 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
166 if (idx
== BRCMF_MAX_CORENUM
)
169 regdata
= brcmf_sdiod_regrl(sdiodev
,
170 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
172 regdata
&= (SSB_TMSLOW_RESET
| SSB_TMSLOW_REJECT
|
173 SSB_IMSTATE_REJECT
| SSB_TMSLOW_CLOCK
);
174 return (SSB_TMSLOW_CLOCK
== regdata
);
178 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
179 struct brcmf_chip
*ci
, u16 coreid
)
185 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
186 if (idx
== BRCMF_MAX_CORENUM
)
189 regdata
= brcmf_sdiod_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
191 ret
= (regdata
& (BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
)) == BCMA_IOCTL_CLK
;
193 regdata
= brcmf_sdiod_regrl(sdiodev
,
194 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
196 ret
= ret
&& ((regdata
& BCMA_RESET_CTL_RESET
) == 0);
202 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev
*sdiodev
,
203 struct brcmf_chip
*ci
, u16 coreid
, u32 pre_resetbits
,
209 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
210 base
= ci
->c_inf
[idx
].base
;
212 regdata
= brcmf_sdiod_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
213 if (regdata
& SSB_TMSLOW_RESET
)
216 regdata
= brcmf_sdiod_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
217 if ((regdata
& SSB_TMSLOW_CLOCK
) != 0) {
219 * set target reject and spin until busy is clear
220 * (preserve core-specific bits)
222 regdata
= brcmf_sdiod_regrl(sdiodev
,
223 CORE_SB(base
, sbtmstatelow
), NULL
);
224 brcmf_sdiod_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
225 regdata
| SSB_TMSLOW_REJECT
, NULL
);
227 regdata
= brcmf_sdiod_regrl(sdiodev
,
228 CORE_SB(base
, sbtmstatelow
), NULL
);
230 SPINWAIT((brcmf_sdiod_regrl(sdiodev
,
231 CORE_SB(base
, sbtmstatehigh
),
233 SSB_TMSHIGH_BUSY
), 100000);
235 regdata
= brcmf_sdiod_regrl(sdiodev
,
236 CORE_SB(base
, sbtmstatehigh
),
238 if (regdata
& SSB_TMSHIGH_BUSY
)
239 brcmf_err("core state still busy\n");
241 regdata
= brcmf_sdiod_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
243 if (regdata
& SSB_IDLOW_INITIATOR
) {
244 regdata
= brcmf_sdiod_regrl(sdiodev
,
245 CORE_SB(base
, sbimstate
),
247 regdata
|= SSB_IMSTATE_REJECT
;
248 brcmf_sdiod_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
250 regdata
= brcmf_sdiod_regrl(sdiodev
,
251 CORE_SB(base
, sbimstate
),
254 SPINWAIT((brcmf_sdiod_regrl(sdiodev
,
255 CORE_SB(base
, sbimstate
),
257 SSB_IMSTATE_BUSY
), 100000);
260 /* set reset and reject while enabling the clocks */
261 regdata
= SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
|
262 SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
;
263 brcmf_sdiod_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
265 regdata
= brcmf_sdiod_regrl(sdiodev
,
266 CORE_SB(base
, sbtmstatelow
), NULL
);
269 /* clear the initiator reject bit */
270 regdata
= brcmf_sdiod_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
272 if (regdata
& SSB_IDLOW_INITIATOR
) {
273 regdata
= brcmf_sdiod_regrl(sdiodev
,
274 CORE_SB(base
, sbimstate
),
276 regdata
&= ~SSB_IMSTATE_REJECT
;
277 brcmf_sdiod_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
282 /* leave reset and reject asserted */
283 brcmf_sdiod_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
284 (SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
), NULL
);
289 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev
*sdiodev
,
290 struct brcmf_chip
*ci
, u16 coreid
, u32 pre_resetbits
,
297 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
298 if (idx
== BRCMF_MAX_CORENUM
)
301 wrapbase
= ci
->c_inf
[idx
].wrapbase
;
303 /* if core is already in reset, just return */
304 regdata
= brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_RESET_CTL
, NULL
);
305 if ((regdata
& BCMA_RESET_CTL_RESET
) != 0)
308 /* configure reset */
309 brcmf_sdiod_regwl(sdiodev
, wrapbase
+ BCMA_IOCTL
, pre_resetbits
|
310 BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
, NULL
);
311 regdata
= brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_IOCTL
, NULL
);
314 brcmf_sdiod_regwl(sdiodev
, wrapbase
+ BCMA_RESET_CTL
,
315 BCMA_RESET_CTL_RESET
, NULL
);
316 usleep_range(10, 20);
318 /* wait till reset is 1 */
319 SPINWAIT(brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_RESET_CTL
, NULL
) !=
320 BCMA_RESET_CTL_RESET
, 300);
322 /* post reset configure */
323 brcmf_sdiod_regwl(sdiodev
, wrapbase
+ BCMA_IOCTL
, pre_resetbits
|
324 BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
, NULL
);
325 regdata
= brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_IOCTL
, NULL
);
329 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev
*sdiodev
,
330 struct brcmf_chip
*ci
, u16 coreid
, u32 pre_resetbits
,
331 u32 in_resetbits
, u32 post_resetbits
)
336 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
337 if (idx
== BRCMF_MAX_CORENUM
)
341 * Must do the disable sequence first to work for
342 * arbitrary current core state.
344 brcmf_sdio_sb_coredisable(sdiodev
, ci
, coreid
, pre_resetbits
,
348 * Now do the initialization sequence.
349 * set reset while enabling the clock and
350 * forcing them on throughout the core
352 brcmf_sdiod_regwl(sdiodev
,
353 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
354 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
| SSB_TMSLOW_RESET
,
356 regdata
= brcmf_sdiod_regrl(sdiodev
,
357 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
361 /* clear any serror */
362 regdata
= brcmf_sdiod_regrl(sdiodev
,
363 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
365 if (regdata
& SSB_TMSHIGH_SERR
)
366 brcmf_sdiod_regwl(sdiodev
,
367 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
370 regdata
= brcmf_sdiod_regrl(sdiodev
,
371 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
373 if (regdata
& (SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
))
374 brcmf_sdiod_regwl(sdiodev
,
375 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
376 regdata
& ~(SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
),
379 /* clear reset and allow it to propagate throughout the core */
380 brcmf_sdiod_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
381 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
, NULL
);
382 regdata
= brcmf_sdiod_regrl(sdiodev
,
383 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
387 /* leave clock enabled */
388 brcmf_sdiod_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
389 SSB_TMSLOW_CLOCK
, NULL
);
390 regdata
= brcmf_sdiod_regrl(sdiodev
,
391 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
397 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev
*sdiodev
,
398 struct brcmf_chip
*ci
, u16 coreid
, u32 pre_resetbits
,
399 u32 in_resetbits
, u32 post_resetbits
)
405 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
406 if (idx
== BRCMF_MAX_CORENUM
)
409 wrapbase
= ci
->c_inf
[idx
].wrapbase
;
411 /* must disable first to work for arbitrary current core state */
412 brcmf_sdio_ai_coredisable(sdiodev
, ci
, coreid
, pre_resetbits
,
415 while (brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_RESET_CTL
, NULL
) &
416 BCMA_RESET_CTL_RESET
) {
417 brcmf_sdiod_regwl(sdiodev
, wrapbase
+ BCMA_RESET_CTL
, 0, NULL
);
418 usleep_range(40, 60);
421 brcmf_sdiod_regwl(sdiodev
, wrapbase
+ BCMA_IOCTL
, post_resetbits
|
422 BCMA_IOCTL_CLK
, NULL
);
423 regdata
= brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_IOCTL
, NULL
);
427 /* safety check for chipinfo */
428 static int brcmf_sdio_chip_cichk(struct brcmf_chip
*ci
)
432 /* check RAM core presence for ARM CM3 core */
433 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
434 if (BRCMF_MAX_CORENUM
!= core_idx
) {
435 core_idx
= brcmf_sdio_chip_getinfidx(ci
,
436 BCMA_CORE_INTERNAL_MEM
);
437 if (BRCMF_MAX_CORENUM
== core_idx
) {
438 brcmf_err("RAM core not provided with ARM CM3 core\n");
443 /* check RAM base for ARM CR4 core */
444 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CR4
);
445 if (BRCMF_MAX_CORENUM
!= core_idx
) {
446 if (ci
->rambase
== 0) {
447 brcmf_err("RAM base not provided with ARM CR4 core\n");
455 static inline int brcmf_sdio_chip_cichk(struct brcmf_chip
*ci
)
461 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev
*sdiodev
,
462 struct brcmf_chip
*ci
)
468 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
469 * For different chiptypes or old sdio hosts w/o chipcommon,
470 * other ways of recognition should be added here.
472 regdata
= brcmf_sdiod_regrl(sdiodev
,
473 CORE_CC_REG(SI_ENUM_BASE
, chipid
),
475 ci
->chip
= regdata
& CID_ID_MASK
;
476 ci
->chiprev
= (regdata
& CID_REV_MASK
) >> CID_REV_SHIFT
;
477 if (sdiodev
->func
[0]->device
== SDIO_DEVICE_ID_BROADCOM_4335_4339
&&
479 ci
->chip
= BCM4339_CHIP_ID
;
480 socitype
= (regdata
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
482 brcmf_dbg(INFO
, "found %s chip: id=0x%x, rev=%d\n",
483 socitype
== SOCI_SB
? "SB" : "AXI", ci
->chip
, ci
->chiprev
);
485 if (socitype
== SOCI_SB
) {
486 if (ci
->chip
!= BCM4329_CHIP_ID
) {
487 brcmf_err("SB chip is not supported\n");
490 ci
->iscoreup
= brcmf_sdio_sb_iscoreup
;
491 ci
->corerev
= brcmf_sdio_sb_corerev
;
492 ci
->coredisable
= brcmf_sdio_sb_coredisable
;
493 ci
->resetcore
= brcmf_sdio_sb_resetcore
;
495 ci
->c_inf
[0].id
= BCMA_CORE_CHIPCOMMON
;
496 ci
->c_inf
[0].base
= SI_ENUM_BASE
;
497 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
498 ci
->c_inf
[1].base
= BCM4329_CORE_BUS_BASE
;
499 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
500 ci
->c_inf
[2].base
= BCM4329_CORE_SOCRAM_BASE
;
501 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
502 ci
->c_inf
[3].base
= BCM4329_CORE_ARM_BASE
;
503 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
504 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
505 ci
->ramsize
= BCM4329_RAMSIZE
;
506 } else if (socitype
== SOCI_AI
) {
507 ci
->iscoreup
= brcmf_sdio_ai_iscoreup
;
508 ci
->corerev
= brcmf_sdio_ai_corerev
;
509 ci
->coredisable
= brcmf_sdio_ai_coredisable
;
510 ci
->resetcore
= brcmf_sdio_ai_resetcore
;
512 ci
->c_inf
[0].id
= BCMA_CORE_CHIPCOMMON
;
513 ci
->c_inf
[0].base
= SI_ENUM_BASE
;
515 /* Address of cores for new chips should be added here */
517 case BCM43143_CHIP_ID
:
518 ci
->c_inf
[0].wrapbase
= ci
->c_inf
[0].base
+ 0x00100000;
519 ci
->c_inf
[0].cib
= 0x2b000000;
520 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
521 ci
->c_inf
[1].base
= BCM43143_CORE_BUS_BASE
;
522 ci
->c_inf
[1].wrapbase
= ci
->c_inf
[1].base
+ 0x00100000;
523 ci
->c_inf
[1].cib
= 0x18000000;
524 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
525 ci
->c_inf
[2].base
= BCM43143_CORE_SOCRAM_BASE
;
526 ci
->c_inf
[2].wrapbase
= ci
->c_inf
[2].base
+ 0x00100000;
527 ci
->c_inf
[2].cib
= 0x14000000;
528 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
529 ci
->c_inf
[3].base
= BCM43143_CORE_ARM_BASE
;
530 ci
->c_inf
[3].wrapbase
= ci
->c_inf
[3].base
+ 0x00100000;
531 ci
->c_inf
[3].cib
= 0x07000000;
532 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
533 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
534 ci
->c_inf
[4].wrapbase
= ci
->c_inf
[4].base
+ 0x00100000;
535 ci
->ramsize
= BCM43143_RAMSIZE
;
537 case BCM43241_CHIP_ID
:
538 ci
->c_inf
[0].wrapbase
= 0x18100000;
539 ci
->c_inf
[0].cib
= 0x2a084411;
540 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
541 ci
->c_inf
[1].base
= 0x18002000;
542 ci
->c_inf
[1].wrapbase
= 0x18102000;
543 ci
->c_inf
[1].cib
= 0x0e004211;
544 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
545 ci
->c_inf
[2].base
= 0x18004000;
546 ci
->c_inf
[2].wrapbase
= 0x18104000;
547 ci
->c_inf
[2].cib
= 0x14080401;
548 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
549 ci
->c_inf
[3].base
= 0x18003000;
550 ci
->c_inf
[3].wrapbase
= 0x18103000;
551 ci
->c_inf
[3].cib
= 0x07004211;
552 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
553 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
554 ci
->c_inf
[4].wrapbase
= ci
->c_inf
[4].base
+ 0x00100000;
555 ci
->ramsize
= 0x90000;
557 case BCM4330_CHIP_ID
:
558 ci
->c_inf
[0].wrapbase
= 0x18100000;
559 ci
->c_inf
[0].cib
= 0x27004211;
560 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
561 ci
->c_inf
[1].base
= 0x18002000;
562 ci
->c_inf
[1].wrapbase
= 0x18102000;
563 ci
->c_inf
[1].cib
= 0x07004211;
564 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
565 ci
->c_inf
[2].base
= 0x18004000;
566 ci
->c_inf
[2].wrapbase
= 0x18104000;
567 ci
->c_inf
[2].cib
= 0x0d080401;
568 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
569 ci
->c_inf
[3].base
= 0x18003000;
570 ci
->c_inf
[3].wrapbase
= 0x18103000;
571 ci
->c_inf
[3].cib
= 0x03004211;
572 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
573 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
574 ci
->c_inf
[4].wrapbase
= ci
->c_inf
[4].base
+ 0x00100000;
575 ci
->ramsize
= 0x48000;
577 case BCM4334_CHIP_ID
:
578 ci
->c_inf
[0].wrapbase
= 0x18100000;
579 ci
->c_inf
[0].cib
= 0x29004211;
580 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
581 ci
->c_inf
[1].base
= 0x18002000;
582 ci
->c_inf
[1].wrapbase
= 0x18102000;
583 ci
->c_inf
[1].cib
= 0x0d004211;
584 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
585 ci
->c_inf
[2].base
= 0x18004000;
586 ci
->c_inf
[2].wrapbase
= 0x18104000;
587 ci
->c_inf
[2].cib
= 0x13080401;
588 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
589 ci
->c_inf
[3].base
= 0x18003000;
590 ci
->c_inf
[3].wrapbase
= 0x18103000;
591 ci
->c_inf
[3].cib
= 0x07004211;
592 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
593 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
594 ci
->c_inf
[4].wrapbase
= ci
->c_inf
[4].base
+ 0x00100000;
595 ci
->ramsize
= 0x80000;
597 case BCM4335_CHIP_ID
:
598 ci
->c_inf
[0].wrapbase
= 0x18100000;
599 ci
->c_inf
[0].cib
= 0x2b084411;
600 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
601 ci
->c_inf
[1].base
= 0x18005000;
602 ci
->c_inf
[1].wrapbase
= 0x18105000;
603 ci
->c_inf
[1].cib
= 0x0f004211;
604 ci
->c_inf
[2].id
= BCMA_CORE_ARM_CR4
;
605 ci
->c_inf
[2].base
= 0x18002000;
606 ci
->c_inf
[2].wrapbase
= 0x18102000;
607 ci
->c_inf
[2].cib
= 0x01084411;
608 ci
->c_inf
[3].id
= BCMA_CORE_80211
;
609 ci
->c_inf
[3].base
= BCM43xx_CORE_D11_BASE
;
610 ci
->c_inf
[3].wrapbase
= ci
->c_inf
[3].base
+ 0x00100000;
611 ci
->ramsize
= 0xc0000;
612 ci
->rambase
= 0x180000;
614 case BCM43362_CHIP_ID
:
615 ci
->c_inf
[0].wrapbase
= 0x18100000;
616 ci
->c_inf
[0].cib
= 0x27004211;
617 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
618 ci
->c_inf
[1].base
= 0x18002000;
619 ci
->c_inf
[1].wrapbase
= 0x18102000;
620 ci
->c_inf
[1].cib
= 0x0a004211;
621 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
622 ci
->c_inf
[2].base
= 0x18004000;
623 ci
->c_inf
[2].wrapbase
= 0x18104000;
624 ci
->c_inf
[2].cib
= 0x08080401;
625 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
626 ci
->c_inf
[3].base
= 0x18003000;
627 ci
->c_inf
[3].wrapbase
= 0x18103000;
628 ci
->c_inf
[3].cib
= 0x03004211;
629 ci
->c_inf
[4].id
= BCMA_CORE_80211
;
630 ci
->c_inf
[4].base
= BCM43xx_CORE_D11_BASE
;
631 ci
->c_inf
[4].wrapbase
= ci
->c_inf
[4].base
+ 0x00100000;
632 ci
->ramsize
= 0x3C000;
634 case BCM4339_CHIP_ID
:
635 ci
->c_inf
[0].wrapbase
= 0x18100000;
636 ci
->c_inf
[0].cib
= 0x2e084411;
637 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
638 ci
->c_inf
[1].base
= 0x18005000;
639 ci
->c_inf
[1].wrapbase
= 0x18105000;
640 ci
->c_inf
[1].cib
= 0x15004211;
641 ci
->c_inf
[2].id
= BCMA_CORE_ARM_CR4
;
642 ci
->c_inf
[2].base
= 0x18002000;
643 ci
->c_inf
[2].wrapbase
= 0x18102000;
644 ci
->c_inf
[2].cib
= 0x04084411;
645 ci
->c_inf
[3].id
= BCMA_CORE_80211
;
646 ci
->c_inf
[3].base
= BCM43xx_CORE_D11_BASE
;
647 ci
->c_inf
[3].wrapbase
= ci
->c_inf
[3].base
+ 0x00100000;
648 ci
->ramsize
= 0xc0000;
649 ci
->rambase
= 0x180000;
652 brcmf_err("AXI chip is not supported\n");
656 brcmf_err("chip backplane type %u is not supported\n",
661 return brcmf_sdio_chip_cichk(ci
);
665 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev
*sdiodev
)
670 /* Try forcing SDIO core to do ALPAvail request only */
671 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_ALP_AVAIL_REQ
;
672 brcmf_sdiod_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
674 brcmf_err("error writing for HT off\n");
678 /* If register supported, wait for ALPAvail and then force ALP */
679 /* This may take up to 15 milliseconds */
680 clkval
= brcmf_sdiod_regrb(sdiodev
,
681 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
);
683 if ((clkval
& ~SBSDIO_AVBITS
) != clkset
) {
684 brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
689 SPINWAIT(((clkval
= brcmf_sdiod_regrb(sdiodev
,
690 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
)),
691 !SBSDIO_ALPAV(clkval
)),
692 PMU_MAX_TRANSITION_DLY
);
693 if (!SBSDIO_ALPAV(clkval
)) {
694 brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
699 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_FORCE_ALP
;
700 brcmf_sdiod_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
703 /* Also, disable the extra SDIO pull-ups */
704 brcmf_sdiod_regwb(sdiodev
, SBSDIO_FUNC1_SDIOPULLUP
, 0, NULL
);
710 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev
*sdiodev
,
711 struct brcmf_chip
*ci
)
713 u32 base
= ci
->c_inf
[0].base
;
715 /* get chipcommon rev */
716 ci
->c_inf
[0].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[0].id
);
718 /* get chipcommon capabilites */
719 ci
->c_inf
[0].caps
= brcmf_sdiod_regrl(sdiodev
,
720 CORE_CC_REG(base
, capabilities
),
723 /* get pmu caps & rev */
724 if (ci
->c_inf
[0].caps
& CC_CAP_PMU
) {
726 brcmf_sdiod_regrl(sdiodev
,
727 CORE_CC_REG(base
, pmucapabilities
),
729 ci
->pmurev
= ci
->pmucaps
& PCAP_REV_MASK
;
732 ci
->c_inf
[1].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[1].id
);
734 brcmf_dbg(INFO
, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
735 ci
->c_inf
[0].rev
, ci
->pmurev
,
736 ci
->c_inf
[1].rev
, ci
->c_inf
[1].id
);
739 * Make sure any on-chip ARM is off (in case strapping is wrong),
740 * or downloaded code was already running.
742 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0, 0);
745 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev
*sdiodev
,
746 struct brcmf_chip
**ci_ptr
)
749 struct brcmf_chip
*ci
;
751 brcmf_dbg(TRACE
, "Enter\n");
753 ci
= kzalloc(sizeof(*ci
), GFP_ATOMIC
);
757 ret
= brcmf_sdio_chip_buscoreprep(sdiodev
);
761 ret
= brcmf_sdio_chip_recognition(sdiodev
, ci
);
765 brcmf_sdio_chip_buscoresetup(sdiodev
, ci
);
767 brcmf_sdiod_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopullup
),
769 brcmf_sdiod_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopulldown
),
781 brcmf_sdio_chip_detach(struct brcmf_chip
**ci_ptr
)
783 brcmf_dbg(TRACE
, "Enter\n");
789 static char *brcmf_sdio_chip_name(uint chipid
, char *buf
, uint len
)
793 fmt
= ((chipid
> 0xa000) || (chipid
< 0x4000)) ? "%d" : "%x";
794 snprintf(buf
, len
, fmt
, chipid
);
799 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev
*sdiodev
,
800 struct brcmf_chip
*ci
, u32 drivestrength
)
802 const struct sdiod_drive_str
*str_tab
= NULL
;
806 u32 base
= ci
->c_inf
[0].base
;
808 u32 drivestrength_sel
= 0;
812 if (!(ci
->c_inf
[0].caps
& CC_CAP_PMU
))
815 switch (SDIOD_DRVSTR_KEY(ci
->chip
, ci
->pmurev
)) {
816 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID
, 12):
817 str_tab
= sdiod_drvstr_tab1_1v8
;
818 str_mask
= 0x00003800;
821 case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID
, 17):
822 str_tab
= sdiod_drvstr_tab6_1v8
;
823 str_mask
= 0x00001800;
826 case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID
, 17):
827 /* note: 43143 does not support tristate */
828 i
= ARRAY_SIZE(sdiod_drvstr_tab2_3v3
) - 1;
829 if (drivestrength
>= sdiod_drvstr_tab2_3v3
[i
].strength
) {
830 str_tab
= sdiod_drvstr_tab2_3v3
;
831 str_mask
= 0x00000007;
834 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
835 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
838 case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID
, 13):
839 str_tab
= sdiod_drive_strength_tab5_1v8
;
840 str_mask
= 0x00003800;
844 brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
845 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
846 ci
->chiprev
, ci
->pmurev
);
850 if (str_tab
!= NULL
) {
851 for (i
= 0; str_tab
[i
].strength
!= 0; i
++) {
852 if (drivestrength
>= str_tab
[i
].strength
) {
853 drivestrength_sel
= str_tab
[i
].sel
;
857 addr
= CORE_CC_REG(base
, chipcontrol_addr
);
858 brcmf_sdiod_regwl(sdiodev
, addr
, 1, NULL
);
859 cc_data_temp
= brcmf_sdiod_regrl(sdiodev
, addr
, NULL
);
860 cc_data_temp
&= ~str_mask
;
861 drivestrength_sel
<<= str_shift
;
862 cc_data_temp
|= drivestrength_sel
;
863 brcmf_sdiod_regwl(sdiodev
, addr
, cc_data_temp
, NULL
);
865 brcmf_dbg(INFO
, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
866 str_tab
[i
].strength
, drivestrength
, cc_data_temp
);
871 brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev
*sdiodev
,
872 struct brcmf_chip
*ci
)
874 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0, 0);
875 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_80211
,
876 D11_BCMA_IOCTL_PHYRESET
| D11_BCMA_IOCTL_PHYCLOCKEN
,
877 D11_BCMA_IOCTL_PHYCLOCKEN
, D11_BCMA_IOCTL_PHYCLOCKEN
);
878 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
, 0, 0, 0);
881 static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev
*sdiodev
,
882 struct brcmf_chip
*ci
)
887 if (!ci
->iscoreup(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
)) {
888 brcmf_err("SOCRAM core is down after reset?\n");
892 /* clear all interrupts */
893 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_SDIO_DEV
);
894 reg_addr
= ci
->c_inf
[core_idx
].base
;
895 reg_addr
+= offsetof(struct sdpcmd_regs
, intstatus
);
896 brcmf_sdiod_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
898 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0, 0, 0);
904 brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev
*sdiodev
,
905 struct brcmf_chip
*ci
)
910 idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CR4
);
912 if (idx
== BRCMF_MAX_CORENUM
)
915 wrapbase
= ci
->c_inf
[idx
].wrapbase
;
916 regdata
= brcmf_sdiod_regrl(sdiodev
, wrapbase
+ BCMA_IOCTL
, NULL
);
917 regdata
&= ARMCR4_BCMA_IOCTL_CPUHALT
;
918 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
, regdata
,
919 ARMCR4_BCMA_IOCTL_CPUHALT
, ARMCR4_BCMA_IOCTL_CPUHALT
);
920 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_80211
,
921 D11_BCMA_IOCTL_PHYRESET
| D11_BCMA_IOCTL_PHYCLOCKEN
,
922 D11_BCMA_IOCTL_PHYCLOCKEN
, D11_BCMA_IOCTL_PHYCLOCKEN
);
925 static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev
*sdiodev
,
926 struct brcmf_chip
*ci
, u32 rstvec
)
931 /* clear all interrupts */
932 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_SDIO_DEV
);
933 reg_addr
= ci
->c_inf
[core_idx
].base
;
934 reg_addr
+= offsetof(struct sdpcmd_regs
, intstatus
);
935 brcmf_sdiod_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
937 /* Write reset vector to address 0 */
938 brcmf_sdiod_ramrw(sdiodev
, true, 0, (void *)&rstvec
,
942 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
, ARMCR4_BCMA_IOCTL_CPUHALT
,
948 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev
*sdiodev
,
949 struct brcmf_chip
*ci
)
953 arm_core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
954 if (BRCMF_MAX_CORENUM
!= arm_core_idx
) {
955 brcmf_sdio_chip_cm3_enterdl(sdiodev
, ci
);
959 brcmf_sdio_chip_cr4_enterdl(sdiodev
, ci
);
962 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev
*sdiodev
,
963 struct brcmf_chip
*ci
, u32 rstvec
)
967 arm_core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
968 if (BRCMF_MAX_CORENUM
!= arm_core_idx
)
969 return brcmf_sdio_chip_cm3_exitdl(sdiodev
, ci
);
971 return brcmf_sdio_chip_cr4_exitdl(sdiodev
, ci
, rstvec
);