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/ssb/ssb_regs.h>
23 #include <linux/bcma/bcma.h>
25 #include <chipcommon.h>
26 #include <brcm_hw_ids.h>
27 #include <brcmu_wifi.h>
28 #include <brcmu_utils.h>
31 #include "sdio_host.h"
32 #include "sdio_chip.h"
34 /* chip core base & ramsize */
36 /* SDIO device core, ID 0x829 */
37 #define BCM4329_CORE_BUS_BASE 0x18011000
38 /* internal memory core, ID 0x80e */
39 #define BCM4329_CORE_SOCRAM_BASE 0x18003000
40 /* ARM Cortex M3 core, ID 0x82a */
41 #define BCM4329_CORE_ARM_BASE 0x18002000
42 #define BCM4329_RAMSIZE 0x48000
45 /* SDIO device core */
46 #define BCM43143_CORE_BUS_BASE 0x18002000
47 /* internal memory core */
48 #define BCM43143_CORE_SOCRAM_BASE 0x18004000
49 /* ARM Cortex M3 core, ID 0x82a */
50 #define BCM43143_CORE_ARM_BASE 0x18003000
51 #define BCM43143_RAMSIZE 0x70000
53 #define SBCOREREV(sbidh) \
54 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
55 ((sbidh) & SSB_IDHIGH_RCLO))
57 /* SOC Interconnect types (aka chip types) */
62 #define CIB_REV_MASK 0xff000000
63 #define CIB_REV_SHIFT 24
65 /* ARM CR4 core specific control flag bits */
66 #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
68 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
69 /* SDIO Pad drive strength to select value mappings */
70 struct sdiod_drive_str
{
71 u8 strength
; /* Pad Drive Strength in mA */
72 u8 sel
; /* Chip-specific select value */
74 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
75 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8
[] = {
86 /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
87 static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3
[] = {
95 brcmf_sdio_chip_getinfidx(struct chip_info
*ci
, u16 coreid
)
99 for (idx
= 0; idx
< BRCMF_MAX_CORENUM
; idx
++)
100 if (coreid
== ci
->c_inf
[idx
].id
)
103 return BRCMF_MAX_CORENUM
;
107 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev
*sdiodev
,
108 struct chip_info
*ci
, u16 coreid
)
113 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
115 regdata
= brcmf_sdio_regrl(sdiodev
,
116 CORE_SB(ci
->c_inf
[idx
].base
, sbidhigh
),
118 return SBCOREREV(regdata
);
122 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev
*sdiodev
,
123 struct chip_info
*ci
, u16 coreid
)
127 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
129 return (ci
->c_inf
[idx
].cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
133 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
134 struct chip_info
*ci
, u16 coreid
)
139 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
141 regdata
= brcmf_sdio_regrl(sdiodev
,
142 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
144 regdata
&= (SSB_TMSLOW_RESET
| SSB_TMSLOW_REJECT
|
145 SSB_IMSTATE_REJECT
| SSB_TMSLOW_CLOCK
);
146 return (SSB_TMSLOW_CLOCK
== regdata
);
150 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
151 struct chip_info
*ci
, u16 coreid
)
157 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
159 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
161 ret
= (regdata
& (BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
)) == BCMA_IOCTL_CLK
;
163 regdata
= brcmf_sdio_regrl(sdiodev
,
164 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
166 ret
= ret
&& ((regdata
& BCMA_RESET_CTL_RESET
) == 0);
172 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev
*sdiodev
,
173 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
178 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
179 base
= ci
->c_inf
[idx
].base
;
181 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
182 if (regdata
& SSB_TMSLOW_RESET
)
185 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
), NULL
);
186 if ((regdata
& SSB_TMSLOW_CLOCK
) != 0) {
188 * set target reject and spin until busy is clear
189 * (preserve core-specific bits)
191 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
193 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
194 regdata
| SSB_TMSLOW_REJECT
, NULL
);
196 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
199 SPINWAIT((brcmf_sdio_regrl(sdiodev
,
200 CORE_SB(base
, sbtmstatehigh
),
202 SSB_TMSHIGH_BUSY
), 100000);
204 regdata
= brcmf_sdio_regrl(sdiodev
,
205 CORE_SB(base
, sbtmstatehigh
),
207 if (regdata
& SSB_TMSHIGH_BUSY
)
208 brcmf_err("core state still busy\n");
210 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
212 if (regdata
& SSB_IDLOW_INITIATOR
) {
213 regdata
= brcmf_sdio_regrl(sdiodev
,
214 CORE_SB(base
, sbimstate
),
216 regdata
|= SSB_IMSTATE_REJECT
;
217 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
219 regdata
= brcmf_sdio_regrl(sdiodev
,
220 CORE_SB(base
, sbimstate
),
223 SPINWAIT((brcmf_sdio_regrl(sdiodev
,
224 CORE_SB(base
, sbimstate
),
226 SSB_IMSTATE_BUSY
), 100000);
229 /* set reset and reject while enabling the clocks */
230 regdata
= SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
|
231 SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
;
232 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
234 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
238 /* clear the initiator reject bit */
239 regdata
= brcmf_sdio_regrl(sdiodev
, CORE_SB(base
, sbidlow
),
241 if (regdata
& SSB_IDLOW_INITIATOR
) {
242 regdata
= brcmf_sdio_regrl(sdiodev
,
243 CORE_SB(base
, sbimstate
),
245 regdata
&= ~SSB_IMSTATE_REJECT
;
246 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbimstate
),
251 /* leave reset and reject asserted */
252 brcmf_sdio_regwl(sdiodev
, CORE_SB(base
, sbtmstatelow
),
253 (SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
), NULL
);
258 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev
*sdiodev
,
259 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
264 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
266 /* if core is already in reset, just return */
267 regdata
= brcmf_sdio_regrl(sdiodev
,
268 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
270 if ((regdata
& BCMA_RESET_CTL_RESET
) != 0)
273 /* ensure no pending backplane operation
274 * 300uc should be sufficient for backplane ops to be finish
275 * extra 10ms is taken into account for firmware load stage
276 * after 10300us carry on disabling the core anyway
278 SPINWAIT(brcmf_sdio_regrl(sdiodev
,
279 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_ST
,
281 regdata
= brcmf_sdio_regrl(sdiodev
,
282 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_ST
,
285 brcmf_err("disabling core 0x%x with reset status %x\n",
288 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
289 BCMA_RESET_CTL_RESET
, NULL
);
292 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
294 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
296 usleep_range(10, 20);
301 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev
*sdiodev
,
302 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
307 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
310 * Must do the disable sequence first to work for
311 * arbitrary current core state.
313 brcmf_sdio_sb_coredisable(sdiodev
, ci
, coreid
, 0);
316 * Now do the initialization sequence.
317 * set reset while enabling the clock and
318 * forcing them on throughout the core
320 brcmf_sdio_regwl(sdiodev
,
321 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
322 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
| SSB_TMSLOW_RESET
,
324 regdata
= brcmf_sdio_regrl(sdiodev
,
325 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
329 /* clear any serror */
330 regdata
= brcmf_sdio_regrl(sdiodev
,
331 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
333 if (regdata
& SSB_TMSHIGH_SERR
)
334 brcmf_sdio_regwl(sdiodev
,
335 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
),
338 regdata
= brcmf_sdio_regrl(sdiodev
,
339 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
341 if (regdata
& (SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
))
342 brcmf_sdio_regwl(sdiodev
,
343 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
),
344 regdata
& ~(SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
),
347 /* clear reset and allow it to propagate throughout the core */
348 brcmf_sdio_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
349 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
, NULL
);
350 regdata
= brcmf_sdio_regrl(sdiodev
,
351 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
355 /* leave clock enabled */
356 brcmf_sdio_regwl(sdiodev
, CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
357 SSB_TMSLOW_CLOCK
, NULL
);
358 regdata
= brcmf_sdio_regrl(sdiodev
,
359 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
365 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev
*sdiodev
,
366 struct chip_info
*ci
, u16 coreid
, u32 core_bits
)
371 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
373 /* must disable first to work for arbitrary current core state */
374 brcmf_sdio_ai_coredisable(sdiodev
, ci
, coreid
, core_bits
);
376 /* now do initialization sequence */
377 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
378 core_bits
| BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
, NULL
);
379 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
381 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
383 regdata
= brcmf_sdio_regrl(sdiodev
,
384 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
388 brcmf_sdio_regwl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
389 core_bits
| BCMA_IOCTL_CLK
, NULL
);
390 regdata
= brcmf_sdio_regrl(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
396 /* safety check for chipinfo */
397 static int brcmf_sdio_chip_cichk(struct chip_info
*ci
)
401 /* check RAM core presence for ARM CM3 core */
402 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
403 if (BRCMF_MAX_CORENUM
!= core_idx
) {
404 core_idx
= brcmf_sdio_chip_getinfidx(ci
,
405 BCMA_CORE_INTERNAL_MEM
);
406 if (BRCMF_MAX_CORENUM
== core_idx
) {
407 brcmf_err("RAM core not provided with ARM CM3 core\n");
412 /* check RAM base for ARM CR4 core */
413 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CR4
);
414 if (BRCMF_MAX_CORENUM
!= core_idx
) {
415 if (ci
->rambase
== 0) {
416 brcmf_err("RAM base not provided with ARM CR4 core\n");
424 static inline int brcmf_sdio_chip_cichk(struct chip_info
*ci
)
430 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev
*sdiodev
,
431 struct chip_info
*ci
, u32 regs
)
437 * Chipid is assume to be at offset 0 from regs arg
438 * For different chiptypes or old sdio hosts w/o chipcommon,
439 * other ways of recognition should be added here.
441 ci
->c_inf
[0].id
= BCMA_CORE_CHIPCOMMON
;
442 ci
->c_inf
[0].base
= regs
;
443 regdata
= brcmf_sdio_regrl(sdiodev
,
444 CORE_CC_REG(ci
->c_inf
[0].base
, chipid
),
446 ci
->chip
= regdata
& CID_ID_MASK
;
447 ci
->chiprev
= (regdata
& CID_REV_MASK
) >> CID_REV_SHIFT
;
448 if (sdiodev
->func
[0]->device
== SDIO_DEVICE_ID_BROADCOM_4335_4339
&&
450 ci
->chip
= BCM4339_CHIP_ID
;
451 ci
->socitype
= (regdata
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
453 brcmf_dbg(INFO
, "chipid=0x%x chiprev=%d\n", ci
->chip
, ci
->chiprev
);
455 /* Address of cores for new chips should be added here */
457 case BCM43143_CHIP_ID
:
458 ci
->c_inf
[0].wrapbase
= ci
->c_inf
[0].base
+ 0x00100000;
459 ci
->c_inf
[0].cib
= 0x2b000000;
460 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
461 ci
->c_inf
[1].base
= BCM43143_CORE_BUS_BASE
;
462 ci
->c_inf
[1].wrapbase
= ci
->c_inf
[1].base
+ 0x00100000;
463 ci
->c_inf
[1].cib
= 0x18000000;
464 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
465 ci
->c_inf
[2].base
= BCM43143_CORE_SOCRAM_BASE
;
466 ci
->c_inf
[2].wrapbase
= ci
->c_inf
[2].base
+ 0x00100000;
467 ci
->c_inf
[2].cib
= 0x14000000;
468 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
469 ci
->c_inf
[3].base
= BCM43143_CORE_ARM_BASE
;
470 ci
->c_inf
[3].wrapbase
= ci
->c_inf
[3].base
+ 0x00100000;
471 ci
->c_inf
[3].cib
= 0x07000000;
472 ci
->ramsize
= BCM43143_RAMSIZE
;
474 case BCM43241_CHIP_ID
:
475 ci
->c_inf
[0].wrapbase
= 0x18100000;
476 ci
->c_inf
[0].cib
= 0x2a084411;
477 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
478 ci
->c_inf
[1].base
= 0x18002000;
479 ci
->c_inf
[1].wrapbase
= 0x18102000;
480 ci
->c_inf
[1].cib
= 0x0e004211;
481 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
482 ci
->c_inf
[2].base
= 0x18004000;
483 ci
->c_inf
[2].wrapbase
= 0x18104000;
484 ci
->c_inf
[2].cib
= 0x14080401;
485 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
486 ci
->c_inf
[3].base
= 0x18003000;
487 ci
->c_inf
[3].wrapbase
= 0x18103000;
488 ci
->c_inf
[3].cib
= 0x07004211;
489 ci
->ramsize
= 0x90000;
491 case BCM4329_CHIP_ID
:
492 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
493 ci
->c_inf
[1].base
= BCM4329_CORE_BUS_BASE
;
494 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
495 ci
->c_inf
[2].base
= BCM4329_CORE_SOCRAM_BASE
;
496 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
497 ci
->c_inf
[3].base
= BCM4329_CORE_ARM_BASE
;
498 ci
->ramsize
= BCM4329_RAMSIZE
;
500 case BCM4330_CHIP_ID
:
501 ci
->c_inf
[0].wrapbase
= 0x18100000;
502 ci
->c_inf
[0].cib
= 0x27004211;
503 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
504 ci
->c_inf
[1].base
= 0x18002000;
505 ci
->c_inf
[1].wrapbase
= 0x18102000;
506 ci
->c_inf
[1].cib
= 0x07004211;
507 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
508 ci
->c_inf
[2].base
= 0x18004000;
509 ci
->c_inf
[2].wrapbase
= 0x18104000;
510 ci
->c_inf
[2].cib
= 0x0d080401;
511 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
512 ci
->c_inf
[3].base
= 0x18003000;
513 ci
->c_inf
[3].wrapbase
= 0x18103000;
514 ci
->c_inf
[3].cib
= 0x03004211;
515 ci
->ramsize
= 0x48000;
517 case BCM4334_CHIP_ID
:
518 ci
->c_inf
[0].wrapbase
= 0x18100000;
519 ci
->c_inf
[0].cib
= 0x29004211;
520 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
521 ci
->c_inf
[1].base
= 0x18002000;
522 ci
->c_inf
[1].wrapbase
= 0x18102000;
523 ci
->c_inf
[1].cib
= 0x0d004211;
524 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
525 ci
->c_inf
[2].base
= 0x18004000;
526 ci
->c_inf
[2].wrapbase
= 0x18104000;
527 ci
->c_inf
[2].cib
= 0x13080401;
528 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
529 ci
->c_inf
[3].base
= 0x18003000;
530 ci
->c_inf
[3].wrapbase
= 0x18103000;
531 ci
->c_inf
[3].cib
= 0x07004211;
532 ci
->ramsize
= 0x80000;
534 case BCM4335_CHIP_ID
:
535 ci
->c_inf
[0].wrapbase
= 0x18100000;
536 ci
->c_inf
[0].cib
= 0x2b084411;
537 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
538 ci
->c_inf
[1].base
= 0x18005000;
539 ci
->c_inf
[1].wrapbase
= 0x18105000;
540 ci
->c_inf
[1].cib
= 0x0f004211;
541 ci
->c_inf
[2].id
= BCMA_CORE_ARM_CR4
;
542 ci
->c_inf
[2].base
= 0x18002000;
543 ci
->c_inf
[2].wrapbase
= 0x18102000;
544 ci
->c_inf
[2].cib
= 0x01084411;
545 ci
->ramsize
= 0xc0000;
546 ci
->rambase
= 0x180000;
548 case BCM4339_CHIP_ID
:
549 ci
->c_inf
[0].wrapbase
= 0x18100000;
550 ci
->c_inf
[0].cib
= 0x2e084411;
551 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
552 ci
->c_inf
[1].base
= 0x18005000;
553 ci
->c_inf
[1].wrapbase
= 0x18105000;
554 ci
->c_inf
[1].cib
= 0x15004211;
555 ci
->c_inf
[2].id
= BCMA_CORE_ARM_CR4
;
556 ci
->c_inf
[2].base
= 0x18002000;
557 ci
->c_inf
[2].wrapbase
= 0x18102000;
558 ci
->c_inf
[2].cib
= 0x04084411;
559 ci
->ramsize
= 0xc0000;
560 ci
->rambase
= 0x180000;
563 brcmf_err("chipid 0x%x is not supported\n", ci
->chip
);
567 ret
= brcmf_sdio_chip_cichk(ci
);
571 switch (ci
->socitype
) {
573 ci
->iscoreup
= brcmf_sdio_sb_iscoreup
;
574 ci
->corerev
= brcmf_sdio_sb_corerev
;
575 ci
->coredisable
= brcmf_sdio_sb_coredisable
;
576 ci
->resetcore
= brcmf_sdio_sb_resetcore
;
579 ci
->iscoreup
= brcmf_sdio_ai_iscoreup
;
580 ci
->corerev
= brcmf_sdio_ai_corerev
;
581 ci
->coredisable
= brcmf_sdio_ai_coredisable
;
582 ci
->resetcore
= brcmf_sdio_ai_resetcore
;
585 brcmf_err("socitype %u not supported\n", ci
->socitype
);
593 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev
*sdiodev
)
598 /* Try forcing SDIO core to do ALPAvail request only */
599 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_ALP_AVAIL_REQ
;
600 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
602 brcmf_err("error writing for HT off\n");
606 /* If register supported, wait for ALPAvail and then force ALP */
607 /* This may take up to 15 milliseconds */
608 clkval
= brcmf_sdio_regrb(sdiodev
,
609 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
);
611 if ((clkval
& ~SBSDIO_AVBITS
) != clkset
) {
612 brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
617 SPINWAIT(((clkval
= brcmf_sdio_regrb(sdiodev
,
618 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
)),
619 !SBSDIO_ALPAV(clkval
)),
620 PMU_MAX_TRANSITION_DLY
);
621 if (!SBSDIO_ALPAV(clkval
)) {
622 brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
627 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_FORCE_ALP
;
628 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
631 /* Also, disable the extra SDIO pull-ups */
632 brcmf_sdio_regwb(sdiodev
, SBSDIO_FUNC1_SDIOPULLUP
, 0, NULL
);
638 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev
*sdiodev
,
639 struct chip_info
*ci
)
641 u32 base
= ci
->c_inf
[0].base
;
643 /* get chipcommon rev */
644 ci
->c_inf
[0].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[0].id
);
646 /* get chipcommon capabilites */
647 ci
->c_inf
[0].caps
= brcmf_sdio_regrl(sdiodev
,
648 CORE_CC_REG(base
, capabilities
),
651 /* get pmu caps & rev */
652 if (ci
->c_inf
[0].caps
& CC_CAP_PMU
) {
654 brcmf_sdio_regrl(sdiodev
,
655 CORE_CC_REG(base
, pmucapabilities
),
657 ci
->pmurev
= ci
->pmucaps
& PCAP_REV_MASK
;
660 ci
->c_inf
[1].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[1].id
);
662 brcmf_dbg(INFO
, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
663 ci
->c_inf
[0].rev
, ci
->pmurev
,
664 ci
->c_inf
[1].rev
, ci
->c_inf
[1].id
);
667 * Make sure any on-chip ARM is off (in case strapping is wrong),
668 * or downloaded code was already running.
670 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
673 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev
*sdiodev
,
674 struct chip_info
**ci_ptr
, u32 regs
)
677 struct chip_info
*ci
;
679 brcmf_dbg(TRACE
, "Enter\n");
681 /* alloc chip_info_t */
682 ci
= kzalloc(sizeof(struct chip_info
), GFP_ATOMIC
);
686 ret
= brcmf_sdio_chip_buscoreprep(sdiodev
);
690 ret
= brcmf_sdio_chip_recognition(sdiodev
, ci
, regs
);
694 brcmf_sdio_chip_buscoresetup(sdiodev
, ci
);
696 brcmf_sdio_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopullup
),
698 brcmf_sdio_regwl(sdiodev
, CORE_CC_REG(ci
->c_inf
[0].base
, gpiopulldown
),
710 brcmf_sdio_chip_detach(struct chip_info
**ci_ptr
)
712 brcmf_dbg(TRACE
, "Enter\n");
718 static char *brcmf_sdio_chip_name(uint chipid
, char *buf
, uint len
)
722 fmt
= ((chipid
> 0xa000) || (chipid
< 0x4000)) ? "%d" : "%x";
723 snprintf(buf
, len
, fmt
, chipid
);
728 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev
*sdiodev
,
729 struct chip_info
*ci
, u32 drivestrength
)
731 const struct sdiod_drive_str
*str_tab
= NULL
;
735 u32 base
= ci
->c_inf
[0].base
;
737 u32 drivestrength_sel
= 0;
741 if (!(ci
->c_inf
[0].caps
& CC_CAP_PMU
))
744 switch (SDIOD_DRVSTR_KEY(ci
->chip
, ci
->pmurev
)) {
745 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID
, 12):
746 str_tab
= sdiod_drvstr_tab1_1v8
;
747 str_mask
= 0x00003800;
750 case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID
, 17):
751 /* note: 43143 does not support tristate */
752 i
= ARRAY_SIZE(sdiod_drvstr_tab2_3v3
) - 1;
753 if (drivestrength
>= sdiod_drvstr_tab2_3v3
[i
].strength
) {
754 str_tab
= sdiod_drvstr_tab2_3v3
;
755 str_mask
= 0x00000007;
758 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
759 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
763 brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
764 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
765 ci
->chiprev
, ci
->pmurev
);
769 if (str_tab
!= NULL
) {
770 for (i
= 0; str_tab
[i
].strength
!= 0; i
++) {
771 if (drivestrength
>= str_tab
[i
].strength
) {
772 drivestrength_sel
= str_tab
[i
].sel
;
776 addr
= CORE_CC_REG(base
, chipcontrol_addr
);
777 brcmf_sdio_regwl(sdiodev
, addr
, 1, NULL
);
778 cc_data_temp
= brcmf_sdio_regrl(sdiodev
, addr
, NULL
);
779 cc_data_temp
&= ~str_mask
;
780 drivestrength_sel
<<= str_shift
;
781 cc_data_temp
|= drivestrength_sel
;
782 brcmf_sdio_regwl(sdiodev
, addr
, cc_data_temp
, NULL
);
784 brcmf_dbg(INFO
, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
785 str_tab
[i
].strength
, drivestrength
, cc_data_temp
);
791 brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev
*sdiodev
, u32 nvram_addr
,
792 char *nvram_dat
, uint nvram_sz
)
798 /* read back and verify */
799 brcmf_dbg(INFO
, "Compare NVRAM dl & ul; size=%d\n", nvram_sz
);
800 nvram_ularray
= kmalloc(nvram_sz
, GFP_KERNEL
);
801 /* do not proceed while no memory but */
805 /* Upload image to verify downloaded contents. */
806 memset(nvram_ularray
, 0xaa, nvram_sz
);
808 /* Read the vars list to temp buffer for comparison */
809 err
= brcmf_sdio_ramrw(sdiodev
, false, nvram_addr
, nvram_ularray
,
812 brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
813 err
, nvram_sz
, nvram_addr
);
814 } else if (memcmp(nvram_dat
, nvram_ularray
, nvram_sz
)) {
815 brcmf_err("Downloaded NVRAM image is corrupted\n");
818 kfree(nvram_ularray
);
824 brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev
*sdiodev
, u32 nvram_addr
,
825 char *nvram_dat
, uint nvram_sz
)
831 static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev
*sdiodev
,
832 struct chip_info
*ci
,
833 char *nvram_dat
, uint nvram_sz
)
840 nvram_addr
= (ci
->ramsize
- 4) - nvram_sz
+ ci
->rambase
;
842 /* Write the vars list */
843 err
= brcmf_sdio_ramrw(sdiodev
, true, nvram_addr
, nvram_dat
, nvram_sz
);
845 brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
846 err
, nvram_sz
, nvram_addr
);
850 if (!brcmf_sdio_chip_verifynvram(sdiodev
, nvram_addr
,
851 nvram_dat
, nvram_sz
))
855 * nvram size, converted to words, in lower 16-bits, checksum
858 token
= nvram_sz
/ 4;
859 token
= (~token
<< 16) | (token
& 0x0000FFFF);
860 token_le
= cpu_to_le32(token
);
862 brcmf_dbg(INFO
, "RAM size: %d\n", ci
->ramsize
);
863 brcmf_dbg(INFO
, "nvram is placed at %d, size %d, token=0x%08x\n",
864 nvram_addr
, nvram_sz
, token
);
866 /* Write the length token to the last word */
867 if (brcmf_sdio_ramrw(sdiodev
, true, (ci
->ramsize
- 4 + ci
->rambase
),
875 brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev
*sdiodev
,
876 struct chip_info
*ci
)
880 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
881 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
, 0);
883 /* clear length token */
884 brcmf_sdio_ramrw(sdiodev
, true, ci
->ramsize
- 4, (u8
*)&zeros
, 4);
888 brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev
*sdiodev
, struct chip_info
*ci
,
889 char *nvram_dat
, uint nvram_sz
)
894 if (!ci
->iscoreup(sdiodev
, ci
, BCMA_CORE_INTERNAL_MEM
)) {
895 brcmf_err("SOCRAM core is down after reset?\n");
899 if (!brcmf_sdio_chip_writenvram(sdiodev
, ci
, nvram_dat
, nvram_sz
))
902 /* clear all interrupts */
903 core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_SDIO_DEV
);
904 reg_addr
= ci
->c_inf
[core_idx
].base
;
905 reg_addr
+= offsetof(struct sdpcmd_regs
, intstatus
);
906 brcmf_sdio_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
908 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CM3
, 0);
914 brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev
*sdiodev
,
915 struct chip_info
*ci
)
917 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
,
918 ARMCR4_BCMA_IOCTL_CPUHALT
);
922 brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev
*sdiodev
, struct chip_info
*ci
,
923 char *nvram_dat
, uint nvram_sz
)
928 if (!brcmf_sdio_chip_writenvram(sdiodev
, ci
, nvram_dat
, nvram_sz
))
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_sdio_regwl(sdiodev
, reg_addr
, 0xFFFFFFFF, NULL
);
937 /* Write reset vector to address 0 */
938 brcmf_sdio_ramrw(sdiodev
, true, 0, (void *)&ci
->rst_vec
,
939 sizeof(ci
->rst_vec
));
942 ci
->resetcore(sdiodev
, ci
, BCMA_CORE_ARM_CR4
, 0);
947 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev
*sdiodev
,
948 struct chip_info
*ci
)
952 arm_core_idx
= brcmf_sdio_chip_getinfidx(ci
, BCMA_CORE_ARM_CM3
);
953 if (BRCMF_MAX_CORENUM
!= arm_core_idx
) {
954 brcmf_sdio_chip_cm3_enterdl(sdiodev
, ci
);
958 brcmf_sdio_chip_cr4_enterdl(sdiodev
, ci
);
961 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev
*sdiodev
,
962 struct chip_info
*ci
, char *nvram_dat
,
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
, nvram_dat
,
972 return brcmf_sdio_chip_cr4_exitdl(sdiodev
, ci
, nvram_dat
, nvram_sz
);