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/ssb/ssb_regs.h>
22 #include <linux/bcma/bcma.h>
24 #include <chipcommon.h>
25 #include <brcm_hw_ids.h>
26 #include <brcmu_wifi.h>
27 #include <brcmu_utils.h>
30 #include "sdio_host.h"
31 #include "sdio_chip.h"
33 /* chip core base & ramsize */
35 /* SDIO device core, ID 0x829 */
36 #define BCM4329_CORE_BUS_BASE 0x18011000
37 /* internal memory core, ID 0x80e */
38 #define BCM4329_CORE_SOCRAM_BASE 0x18003000
39 /* ARM Cortex M3 core, ID 0x82a */
40 #define BCM4329_CORE_ARM_BASE 0x18002000
41 #define BCM4329_RAMSIZE 0x48000
44 /* SDIO device core */
45 #define BCM43143_CORE_BUS_BASE 0x18002000
46 /* internal memory core */
47 #define BCM43143_CORE_SOCRAM_BASE 0x18004000
48 /* ARM Cortex M3 core, ID 0x82a */
49 #define BCM43143_CORE_ARM_BASE 0x18003000
50 #define BCM43143_RAMSIZE 0x70000
52 #define SBCOREREV(sbidh) \
53 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
54 ((sbidh) & SSB_IDHIGH_RCLO))
56 /* SOC Interconnect types (aka chip types) */
61 #define CIB_REV_MASK 0xff000000
62 #define CIB_REV_SHIFT 24
64 /* ARM CR4 core specific control flag bits */
65 #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
67 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
68 /* SDIO Pad drive strength to select value mappings */
69 struct sdiod_drive_str
{
70 u8 strength
; /* Pad Drive Strength in mA */
71 u8 sel
; /* Chip-specific select value */
73 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
74 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8
[] = {
85 /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
86 static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3
[] = {
94 brcmf_sdio_chip_getinfidx(struct chip_info
*ci
, u16 coreid
)
98 for (idx
= 0; idx
< BRCMF_MAX_CORENUM
; idx
++)
99 if (coreid
== ci
->c_inf
[idx
].id
)
102 return BRCMF_MAX_CORENUM
;
106 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev
*sdiodev
,
107 struct chip_info
*ci
, u16 coreid
)
112 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
114 regdata
= brcmf_sdio_regrl(sdiodev
,
115 CORE_SB(ci
->c_inf
[idx
].base
, sbidhigh
),
117 return SBCOREREV(regdata
);
121 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev
*sdiodev
,
122 struct chip_info
*ci
, u16 coreid
)
126 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
128 return (ci
->c_inf
[idx
].cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
132 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
133 struct chip_info
*ci
, u16 coreid
)
138 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
140 regdata
= brcmf_sdio_regrl(sdiodev
,
141 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
143 regdata
&= (SSB_TMSLOW_RESET
| SSB_TMSLOW_REJECT
|
144 SSB_IMSTATE_REJECT
| SSB_TMSLOW_CLOCK
);
145 return (SSB_TMSLOW_CLOCK
== regdata
);
149 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
150 struct chip_info
*ci
, u16 coreid
)
156 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
158 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
160 ret
= (regdata
& (BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
)) == BCMA_IOCTL_CLK
;
162 regdata
= brcmf_sdio_regrl(sdiodev
,
163 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
165 ret
= ret
&& ((regdata
& BCMA_RESET_CTL_RESET
) == 0);
171 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev
*sdiodev
,
172 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
177 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
178 base
= ci
->c_inf
[idx
].base
;
180 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
181 if (regdata
& SSB_TMSLOW_RESET
)
184 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
185 if ((regdata
& SSB_TMSLOW_CLOCK
) != 0) {
187 * set target reject and spin until busy is clear
188 * (preserve core-specific bits)
190 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
192 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
193 regdata
| SSB_TMSLOW_REJECT
, NULL
);
195 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
198 SPINWAIT((brcmf_sdio_regrl(sdiodev
,
199 CORE_SB(base
, sbtmstatehigh
),
201 SSB_TMSHIGH_BUSY
), 100000);
203 regdata
= brcmf_sdio_regrl(sdiodev
,
204 CORE_SB(base
, sbtmstatehigh
),
206 if (regdata
& SSB_TMSHIGH_BUSY
)
207 brcmf_err("core state still busy\n");
209 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
211 if (regdata
& SSB_IDLOW_INITIATOR
) {
212 regdata
= brcmf_sdio_regrl(sdiodev
,
213 CORE_SB(base
, sbimstate
),
215 regdata
|= SSB_IMSTATE_REJECT
;
216 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
218 regdata
= brcmf_sdio_regrl(sdiodev
,
219 CORE_SB(base
, sbimstate
),
222 SPINWAIT((brcmf_sdio_regrl(sdiodev
,
223 CORE_SB(base
, sbimstate
),
225 SSB_IMSTATE_BUSY
), 100000);
228 /* set reset and reject while enabling the clocks */
229 regdata
= SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
|
230 SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
;
231 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
233 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
237 /* clear the initiator reject bit */
238 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
240 if (regdata
& SSB_IDLOW_INITIATOR
) {
241 regdata
= brcmf_sdio_regrl(sdiodev
,
242 CORE_SB(base
, sbimstate
),
244 regdata
&= ~SSB_IMSTATE_REJECT
;
245 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
250 /* leave reset and reject asserted */
251 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
252 (SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
), NULL
);
257 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev
*sdiodev
,
258 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
263 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
265 /* if core is already in reset, just return */
266 regdata
= brcmf_sdio_regrl(sdiodev
,
267 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
269 if ((regdata
& BCMA_RESET_CTL_RESET
) != 0)
272 /* ensure no pending backplane operation
273 * 300uc should be sufficient for backplane ops to be finish
274 * extra 10ms is taken into account for firmware load stage
275 * after 10300us carry on disabling the core anyway
277 SPINWAIT(brcmf_sdio_regrl(sdiodev
,
278 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_ST
,
280 regdata
= brcmf_sdio_regrl(sdiodev
,
281 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_ST
,
284 brcmf_err("disabling core 0x%x with reset status %x\n",
287 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
288 BCMA_RESET_CTL_RESET
, NULL
);
291 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
293 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
295 usleep_range(10, 20);
300 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev
*sdiodev
,
301 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
306 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
309 * Must do the disable sequence first to work for
310 * arbitrary current core state.
312 brcmf_sdio_sb_coredisable(sdiodev
, ci
, coreid
, 0);
315 * Now do the initialization sequence.
316 * set reset while enabling the clock and
317 * forcing them on throughout the core
319 brcmf_sdio_regwl(sdiodev
,
320 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
321 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
| SSB_TMSLOW_RESET
,
323 regdata
= brcmf_sdio_regrl(sdiodev
,
324 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
328 /* clear any serror */
329 regdata
= brcmf_sdio_regrl(sdiodev
,
330 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
332 if (regdata
& SSB_TMSHIGH_SERR
)
333 brcmf_sdio_regwl(sdiodev
,
334 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
337 regdata
= brcmf_sdio_regrl(sdiodev
,
338 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
340 if (regdata
& (SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
))
341 brcmf_sdio_regwl(sdiodev
,
342 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
343 regdata
& ~(SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
),
346 /* clear reset and allow it to propagate throughout the core */
347 brcmf_sdio_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
348 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
, NULL
);
349 regdata
= brcmf_sdio_regrl(sdiodev
,
350 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
354 /* leave clock enabled */
355 brcmf_sdio_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
356 SSB_TMSLOW_CLOCK
, NULL
);
357 regdata
= brcmf_sdio_regrl(sdiodev
,
358 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
364 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev
*sdiodev
,
365 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
370 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
372 /* must disable first to work for arbitrary current core state */
373 brcmf_sdio_ai_coredisable(sdiodev
, ci
, coreid
, core_bits
);
375 /* now do initialization sequence */
376 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
377 core_bits
| BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
, NULL
);
378 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
380 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
382 regdata
= brcmf_sdio_regrl(sdiodev
,
383 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
387 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
388 core_bits
| BCMA_IOCTL_CLK
, NULL
);
389 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
395 /* safety check for chipinfo */
396 static int brcmf_sdio_chip_cichk(struct chip_info
*ci
)
400 /* check RAM core presence for ARM CM3 core */
401 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
402 if (BRCMF_MAX_CORENUM
!= core_idx
) {
403 core_idx
= brcmf_sdio_chip_getinfidx(ci
,
404 BCMA_CORE_INTERNAL_MEM
);
405 if (BRCMF_MAX_CORENUM
== core_idx
) {
406 brcmf_err("RAM core not provided with ARM CM3 core\n");
411 /* check RAM base for ARM CR4 core */
412 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CR4
);
413 if (BRCMF_MAX_CORENUM
!= core_idx
) {
414 if (ci
->rambase
== 0) {
415 brcmf_err("RAM base not provided with ARM CR4 core\n");
423 static inline int brcmf_sdio_chip_cichk(struct chip_info
*ci
)
429 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev
*sdiodev
,
430 struct chip_info
*ci
, u32 regs
)
436 * Chipid is assume to be at offset 0 from regs arg
437 * For different chiptypes or old sdio hosts w/o chipcommon,
438 * other ways of recognition should be added here.
440 ci
->c_inf
[0].id
= BCMA_CORE_CHIPCOMMON
;
441 ci
->c_inf
[0].base
= regs
;
442 regdata
= brcmf_sdio_regrl(sdiodev
,
443 CORE_CC_REG(ci
->c_inf
[0].base
, chipid
),
445 ci
->chip
= regdata
& CID_ID_MASK
;
446 ci
->chiprev
= (regdata
& CID_REV_MASK
) >> CID_REV_SHIFT
;
447 ci
->socitype
= (regdata
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
449 brcmf_dbg(INFO
, "chipid=0x%x chiprev=%d\n", ci
->chip
, ci
->chiprev
);
451 /* Address of cores for new chips should be added here */
453 case BCM43143_CHIP_ID
:
454 ci
->c_inf
[0].wrapbase
= ci
->c_inf
[0].base
+ 0x00100000;
455 ci
->c_inf
[0].cib
= 0x2b000000;
456 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
457 ci
->c_inf
[1].base
= BCM43143_CORE_BUS_BASE
;
458 ci
->c_inf
[1].wrapbase
= ci
->c_inf
[1].base
+ 0x00100000;
459 ci
->c_inf
[1].cib
= 0x18000000;
460 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
461 ci
->c_inf
[2].base
= BCM43143_CORE_SOCRAM_BASE
;
462 ci
->c_inf
[2].wrapbase
= ci
->c_inf
[2].base
+ 0x00100000;
463 ci
->c_inf
[2].cib
= 0x14000000;
464 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
465 ci
->c_inf
[3].base
= BCM43143_CORE_ARM_BASE
;
466 ci
->c_inf
[3].wrapbase
= ci
->c_inf
[3].base
+ 0x00100000;
467 ci
->c_inf
[3].cib
= 0x07000000;
468 ci
->ramsize
= BCM43143_RAMSIZE
;
470 case BCM43241_CHIP_ID
:
471 ci
->c_inf
[0].wrapbase
= 0x18100000;
472 ci
->c_inf
[0].cib
= 0x2a084411;
473 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
474 ci
->c_inf
[1].base
= 0x18002000;
475 ci
->c_inf
[1].wrapbase
= 0x18102000;
476 ci
->c_inf
[1].cib
= 0x0e004211;
477 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
478 ci
->c_inf
[2].base
= 0x18004000;
479 ci
->c_inf
[2].wrapbase
= 0x18104000;
480 ci
->c_inf
[2].cib
= 0x14080401;
481 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
482 ci
->c_inf
[3].base
= 0x18003000;
483 ci
->c_inf
[3].wrapbase
= 0x18103000;
484 ci
->c_inf
[3].cib
= 0x07004211;
485 ci
->ramsize
= 0x90000;
487 case BCM4329_CHIP_ID
:
488 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
489 ci
->c_inf
[1].base
= BCM4329_CORE_BUS_BASE
;
490 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
491 ci
->c_inf
[2].base
= BCM4329_CORE_SOCRAM_BASE
;
492 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
493 ci
->c_inf
[3].base
= BCM4329_CORE_ARM_BASE
;
494 ci
->ramsize
= BCM4329_RAMSIZE
;
496 case BCM4330_CHIP_ID
:
497 ci
->c_inf
[0].wrapbase
= 0x18100000;
498 ci
->c_inf
[0].cib
= 0x27004211;
499 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
500 ci
->c_inf
[1].base
= 0x18002000;
501 ci
->c_inf
[1].wrapbase
= 0x18102000;
502 ci
->c_inf
[1].cib
= 0x07004211;
503 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
504 ci
->c_inf
[2].base
= 0x18004000;
505 ci
->c_inf
[2].wrapbase
= 0x18104000;
506 ci
->c_inf
[2].cib
= 0x0d080401;
507 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
508 ci
->c_inf
[3].base
= 0x18003000;
509 ci
->c_inf
[3].wrapbase
= 0x18103000;
510 ci
->c_inf
[3].cib
= 0x03004211;
511 ci
->ramsize
= 0x48000;
513 case BCM4334_CHIP_ID
:
514 ci
->c_inf
[0].wrapbase
= 0x18100000;
515 ci
->c_inf
[0].cib
= 0x29004211;
516 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
517 ci
->c_inf
[1].base
= 0x18002000;
518 ci
->c_inf
[1].wrapbase
= 0x18102000;
519 ci
->c_inf
[1].cib
= 0x0d004211;
520 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
521 ci
->c_inf
[2].base
= 0x18004000;
522 ci
->c_inf
[2].wrapbase
= 0x18104000;
523 ci
->c_inf
[2].cib
= 0x13080401;
524 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
525 ci
->c_inf
[3].base
= 0x18003000;
526 ci
->c_inf
[3].wrapbase
= 0x18103000;
527 ci
->c_inf
[3].cib
= 0x07004211;
528 ci
->ramsize
= 0x80000;
530 case BCM4335_CHIP_ID
:
531 ci
->c_inf
[0].wrapbase
= 0x18100000;
532 ci
->c_inf
[0].cib
= 0x2b084411;
533 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
534 ci
->c_inf
[1].base
= 0x18005000;
535 ci
->c_inf
[1].wrapbase
= 0x18105000;
536 ci
->c_inf
[1].cib
= 0x0f004211;
537 ci
->c_inf
[2].id
= BCMA_CORE_ARM_CR4
;
538 ci
->c_inf
[2].base
= 0x18002000;
539 ci
->c_inf
[2].wrapbase
= 0x18102000;
540 ci
->c_inf
[2].cib
= 0x01084411;
541 ci
->ramsize
= 0xc0000;
542 ci
->rambase
= 0x180000;
545 brcmf_err("chipid 0x%x is not supported\n", ci
->chip
);
549 ret
= brcmf_sdio_chip_cichk(ci
);
553 switch (ci
->socitype
) {
555 ci
->iscoreup
= brcmf_sdio_sb_iscoreup
;
556 ci
->corerev
= brcmf_sdio_sb_corerev
;
557 ci
->coredisable
= brcmf_sdio_sb_coredisable
;
558 ci
->resetcore
= brcmf_sdio_sb_resetcore
;
561 ci
->iscoreup
= brcmf_sdio_ai_iscoreup
;
562 ci
->corerev
= brcmf_sdio_ai_corerev
;
563 ci
->coredisable
= brcmf_sdio_ai_coredisable
;
564 ci
->resetcore
= brcmf_sdio_ai_resetcore
;
567 brcmf_err("socitype %u not supported\n", ci
->socitype
);
575 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev
*sdiodev
)
580 /* Try forcing SDIO core to do ALPAvail request only */
581 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_ALP_AVAIL_REQ
;
582 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
584 brcmf_err("error writing for HT off\n");
588 /* If register supported, wait for ALPAvail and then force ALP */
589 /* This may take up to 15 milliseconds */
590 clkval
= brcmf_sdio_regrb(sdiodev
,
591 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
);
593 if ((clkval
& ~SBSDIO_AVBITS
) != clkset
) {
594 brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
599 SPINWAIT(((clkval
= brcmf_sdio_regrb(sdiodev
,
600 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
)),
601 !SBSDIO_ALPAV(clkval
)),
602 PMU_MAX_TRANSITION_DLY
);
603 if (!SBSDIO_ALPAV(clkval
)) {
604 brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
609 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_FORCE_ALP
;
610 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
613 /* Also, disable the extra SDIO pull-ups */
614 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_SDIOPULLUP
, 0, NULL
);
620 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev
*sdiodev
,
621 struct chip_info
*ci
)
623 u32 base
= ci
->c_inf
[0].base
;
625 /* get chipcommon rev */
626 ci
->c_inf
[0].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[0].id
);
628 /* get chipcommon capabilites */
629 ci
->c_inf
[0].caps
= brcmf_sdio_regrl(sdiodev
,
630 CORE_CC_REG(base
, capabilities
),
633 /* get pmu caps & rev */
634 if (ci
->c_inf
[0].caps
& CC_CAP_PMU
) {
636 brcmf_sdio_regrl(sdiodev
,
637 CORE_CC_REG(base
, pmucapabilities
),
639 ci
->pmurev
= ci
->pmucaps
& PCAP_REV_MASK
;
642 ci
->c_inf
[1].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[1].id
);
644 brcmf_dbg(INFO
, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
645 ci
->c_inf
[0].rev
, ci
->pmurev
,
646 ci
->c_inf
[1].rev
, ci
->c_inf
[1].id
);
649 * Make sure any on-chip ARM is off (in case strapping is wrong),
650 * or downloaded code was already running.
652 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
655 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev
*sdiodev
,
656 struct chip_info
**ci_ptr
, u32 regs
)
659 struct chip_info
*ci
;
661 brcmf_dbg(TRACE
, "Enter\n");
663 /* alloc chip_info_t */
664 ci
= kzalloc(sizeof(struct chip_info
), GFP_ATOMIC
);
668 ret
= brcmf_sdio_chip_buscoreprep(sdiodev
);
672 ret
= brcmf_sdio_chip_recognition(sdiodev
, ci
, regs
);
676 brcmf_sdio_chip_buscoresetup(sdiodev
, ci
);
678 brcmf_sdio_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopullup
),
680 brcmf_sdio_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopulldown
),
692 brcmf_sdio_chip_detach(struct chip_info
**ci_ptr
)
694 brcmf_dbg(TRACE
, "Enter\n");
700 static char *brcmf_sdio_chip_name(uint chipid
, char *buf
, uint len
)
704 fmt
= ((chipid
> 0xa000) || (chipid
< 0x4000)) ? "%d" : "%x";
705 snprintf(buf
, len
, fmt
, chipid
);
710 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev
*sdiodev
,
711 struct chip_info
*ci
, u32 drivestrength
)
713 const struct sdiod_drive_str
*str_tab
= NULL
;
717 u32 base
= ci
->c_inf
[0].base
;
719 u32 drivestrength_sel
= 0;
723 if (!(ci
->c_inf
[0].caps
& CC_CAP_PMU
))
726 switch (SDIOD_DRVSTR_KEY(ci
->chip
, ci
->pmurev
)) {
727 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID
, 12):
728 str_tab
= sdiod_drvstr_tab1_1v8
;
729 str_mask
= 0x00003800;
732 case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID
, 17):
733 /* note: 43143 does not support tristate */
734 i
= ARRAY_SIZE(sdiod_drvstr_tab2_3v3
) - 1;
735 if (drivestrength
>= sdiod_drvstr_tab2_3v3
[i
].strength
) {
736 str_tab
= sdiod_drvstr_tab2_3v3
;
737 str_mask
= 0x00000007;
740 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
741 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
745 brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
746 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
747 ci
->chiprev
, ci
->pmurev
);
751 if (str_tab
!= NULL
) {
752 for (i
= 0; str_tab
[i
].strength
!= 0; i
++) {
753 if (drivestrength
>= str_tab
[i
].strength
) {
754 drivestrength_sel
= str_tab
[i
].sel
;
758 addr
= CORE_CC_REG(base
, chipcontrol_addr
);
759 brcmf_sdio_regwl(sdiodev
, addr
, 1, NULL
);
760 cc_data_temp
= brcmf_sdio_regrl(sdiodev
, addr
, NULL
);
761 cc_data_temp
&= ~str_mask
;
762 drivestrength_sel
<<= str_shift
;
763 cc_data_temp
|= drivestrength_sel
;
764 brcmf_sdio_regwl(sdiodev
, addr
, cc_data_temp
, NULL
);
766 brcmf_dbg(INFO
, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
767 str_tab
[i
].strength
, drivestrength
, cc_data_temp
);
773 brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev
*sdiodev
, u32 nvram_addr
,
774 char *nvram_dat
, uint nvram_sz
)
780 /* read back and verify */
781 brcmf_dbg(INFO
, "Compare NVRAM dl & ul; size=%d\n", nvram_sz
);
782 nvram_ularray
= kmalloc(nvram_sz
, GFP_KERNEL
);
783 /* do not proceed while no memory but */
787 /* Upload image to verify downloaded contents. */
788 memset(nvram_ularray
, 0xaa, nvram_sz
);
790 /* Read the vars list to temp buffer for comparison */
791 err
= brcmf_sdio_ramrw(sdiodev
, false, nvram_addr
, nvram_ularray
,
794 brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
795 err
, nvram_sz
, nvram_addr
);
796 } else if (memcmp(nvram_dat
, nvram_ularray
, nvram_sz
)) {
797 brcmf_err("Downloaded NVRAM image is corrupted\n");
800 kfree(nvram_ularray
);
806 brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev
*sdiodev
, u32 nvram_addr
,
807 char *nvram_dat
, uint nvram_sz
)
813 static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev
*sdiodev
,
814 struct chip_info
*ci
,
815 char *nvram_dat
, uint nvram_sz
)
822 nvram_addr
= (ci
->ramsize
- 4) - nvram_sz
+ ci
->rambase
;
824 /* Write the vars list */
825 err
= brcmf_sdio_ramrw(sdiodev
, true, nvram_addr
, nvram_dat
, nvram_sz
);
827 brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
828 err
, nvram_sz
, nvram_addr
);
832 if (!brcmf_sdio_chip_verifynvram(sdiodev
, nvram_addr
,
833 nvram_dat
, nvram_sz
))
837 * nvram size, converted to words, in lower 16-bits, checksum
840 token
= nvram_sz
/ 4;
841 token
= (~token
<< 16) | (token
& 0x0000FFFF);
842 token_le
= cpu_to_le32(token
);
844 brcmf_dbg(INFO
, "RAM size: %d\n", ci
->ramsize
);
845 brcmf_dbg(INFO
, "nvram is placed at %d, size %d, token=0x%08x\n",
846 nvram_addr
, nvram_sz
, token
);
848 /* Write the length token to the last word */
849 if (brcmf_sdio_ramrw(sdiodev
, true, (ci
->ramsize
- 4 + ci
->rambase
),
857 brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev
*sdiodev
,
858 struct chip_info
*ci
)
862 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
863 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
, 0);
865 /* clear length token */
866 brcmf_sdio_ramrw(sdiodev
, true, ci
->ramsize
- 4, (u8
*)&zeros
, 4);
870 brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev
*sdiodev
, struct chip_info
*ci
,
871 char *nvram_dat
, uint nvram_sz
)
876 if (!ci
->iscoreup(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
)) {
877 brcmf_err("SOCRAM core is down after reset?\n");
881 if (!brcmf_sdio_chip_writenvram(sdiodev
, ci
, nvram_dat
, nvram_sz
))
884 /* clear all interrupts */
885 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_SDIO_DEV
);
886 reg_addr
= ci
->c_inf
[core_idx
].base
;
887 reg_addr
+= offsetof(struct sdpcmd_regs
, intstatus
);
888 brcmf_sdio_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
890 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
896 brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev
*sdiodev
,
897 struct chip_info
*ci
)
899 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
,
900 ARMCR4_BCMA_IOCTL_CPUHALT
);
904 brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev
*sdiodev
, struct chip_info
*ci
,
905 char *nvram_dat
, uint nvram_sz
)
910 if (!brcmf_sdio_chip_writenvram(sdiodev
, ci
, nvram_dat
, nvram_sz
))
913 /* clear all interrupts */
914 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_SDIO_DEV
);
915 reg_addr
= ci
->c_inf
[core_idx
].base
;
916 reg_addr
+= offsetof(struct sdpcmd_regs
, intstatus
);
917 brcmf_sdio_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
919 /* Write reset vector to address 0 */
920 brcmf_sdio_ramrw(sdiodev
, true, 0, (void *)&ci
->rst_vec
,
921 sizeof(ci
->rst_vec
));
924 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
, 0);
929 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev
*sdiodev
,
930 struct chip_info
*ci
)
934 arm_core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
935 if (BRCMF_MAX_CORENUM
!= arm_core_idx
) {
936 brcmf_sdio_chip_cm3_enterdl(sdiodev
, ci
);
940 brcmf_sdio_chip_cr4_enterdl(sdiodev
, ci
);
943 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev
*sdiodev
,
944 struct chip_info
*ci
, char *nvram_dat
,
949 arm_core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
950 if (BRCMF_MAX_CORENUM
!= arm_core_idx
)
951 return brcmf_sdio_chip_cm3_exitdl(sdiodev
, ci
, nvram_dat
,
954 return brcmf_sdio_chip_cr4_exitdl(sdiodev
, ci
, nvram_dat
, nvram_sz
);