Staging: unisys: Remove RETINT macro
[linux/fpc-iii.git] / drivers / net / wireless / brcm80211 / brcmfmac / sdio_chip.c
blob82bf3c5d3cdcd928ebd2950af86369a198a2799a
1 /*
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>
30 #include <soc.h>
31 #include "dhd_dbg.h"
32 #include "sdio_host.h"
33 #include "sdio_chip.h"
35 /* chip core base & ramsize */
36 /* bcm4329 */
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
45 /* bcm43143 */
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) */
62 #define SOCI_SB 0
63 #define SOCI_AI 1
65 /* EROM CompIdentB */
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[] = {
84 {32, 0x6},
85 {26, 0x7},
86 {22, 0x4},
87 {16, 0x5},
88 {12, 0x2},
89 {8, 0x3},
90 {4, 0x0},
91 {0, 0x1}
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[] = {
96 {6, 0x7},
97 {5, 0x6},
98 {4, 0x5},
99 {3, 0x4},
100 {2, 0x2},
101 {1, 0x1},
102 {0, 0x0}
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[] = {
107 {3, 0x3},
108 {2, 0x2},
109 {1, 0x1},
110 {0, 0x0} };
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[] = {
114 {16, 0x7},
115 {12, 0x5},
116 {8, 0x3},
117 {4, 0x1}
121 brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid)
123 u8 idx;
125 for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
126 if (coreid == ci->c_inf[idx].id)
127 return idx;
129 return BRCMF_MAX_CORENUM;
132 static u32
133 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
134 struct brcmf_chip *ci, u16 coreid)
136 u32 regdata;
137 u8 idx;
139 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
141 regdata = brcmf_sdiod_regrl(sdiodev,
142 CORE_SB(ci->c_inf[idx].base, sbidhigh),
143 NULL);
144 return SBCOREREV(regdata);
147 static u32
148 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
149 struct brcmf_chip *ci, u16 coreid)
151 u8 idx;
153 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
155 return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
158 static bool
159 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
160 struct brcmf_chip *ci, u16 coreid)
162 u32 regdata;
163 u8 idx;
165 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
166 if (idx == BRCMF_MAX_CORENUM)
167 return false;
169 regdata = brcmf_sdiod_regrl(sdiodev,
170 CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
171 NULL);
172 regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
173 SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
174 return (SSB_TMSLOW_CLOCK == regdata);
177 static bool
178 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
179 struct brcmf_chip *ci, u16 coreid)
181 u32 regdata;
182 u8 idx;
183 bool ret;
185 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
186 if (idx == BRCMF_MAX_CORENUM)
187 return false;
189 regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
190 NULL);
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,
195 NULL);
196 ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
198 return ret;
201 static void
202 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
203 struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
204 u32 in_resetbits)
206 u32 regdata, base;
207 u8 idx;
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)
214 return;
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);
229 udelay(1);
230 SPINWAIT((brcmf_sdiod_regrl(sdiodev,
231 CORE_SB(base, sbtmstatehigh),
232 NULL) &
233 SSB_TMSHIGH_BUSY), 100000);
235 regdata = brcmf_sdiod_regrl(sdiodev,
236 CORE_SB(base, sbtmstatehigh),
237 NULL);
238 if (regdata & SSB_TMSHIGH_BUSY)
239 brcmf_err("core state still busy\n");
241 regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
242 NULL);
243 if (regdata & SSB_IDLOW_INITIATOR) {
244 regdata = brcmf_sdiod_regrl(sdiodev,
245 CORE_SB(base, sbimstate),
246 NULL);
247 regdata |= SSB_IMSTATE_REJECT;
248 brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
249 regdata, NULL);
250 regdata = brcmf_sdiod_regrl(sdiodev,
251 CORE_SB(base, sbimstate),
252 NULL);
253 udelay(1);
254 SPINWAIT((brcmf_sdiod_regrl(sdiodev,
255 CORE_SB(base, sbimstate),
256 NULL) &
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),
264 regdata, NULL);
265 regdata = brcmf_sdiod_regrl(sdiodev,
266 CORE_SB(base, sbtmstatelow), NULL);
267 udelay(10);
269 /* clear the initiator reject bit */
270 regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
271 NULL);
272 if (regdata & SSB_IDLOW_INITIATOR) {
273 regdata = brcmf_sdiod_regrl(sdiodev,
274 CORE_SB(base, sbimstate),
275 NULL);
276 regdata &= ~SSB_IMSTATE_REJECT;
277 brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
278 regdata, NULL);
282 /* leave reset and reject asserted */
283 brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
284 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
285 udelay(1);
288 static void
289 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
290 struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
291 u32 in_resetbits)
293 u8 idx;
294 u32 regdata;
295 u32 wrapbase;
297 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
298 if (idx == BRCMF_MAX_CORENUM)
299 return;
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)
306 return;
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);
313 /* put in reset */
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);
328 static void
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)
333 u32 regdata;
334 u8 idx;
336 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
337 if (idx == BRCMF_MAX_CORENUM)
338 return;
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,
345 in_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,
355 NULL);
356 regdata = brcmf_sdiod_regrl(sdiodev,
357 CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
358 NULL);
359 udelay(1);
361 /* clear any serror */
362 regdata = brcmf_sdiod_regrl(sdiodev,
363 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
364 NULL);
365 if (regdata & SSB_TMSHIGH_SERR)
366 brcmf_sdiod_regwl(sdiodev,
367 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
368 0, NULL);
370 regdata = brcmf_sdiod_regrl(sdiodev,
371 CORE_SB(ci->c_inf[idx].base, sbimstate),
372 NULL);
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),
377 NULL);
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),
384 NULL);
385 udelay(1);
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),
392 NULL);
393 udelay(1);
396 static void
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)
401 u8 idx;
402 u32 regdata;
403 u32 wrapbase;
405 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
406 if (idx == BRCMF_MAX_CORENUM)
407 return;
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,
413 in_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);
426 #ifdef DEBUG
427 /* safety check for chipinfo */
428 static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
430 u8 core_idx;
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");
439 return -ENODEV;
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");
448 return -ENOMEM;
452 return 0;
454 #else /* DEBUG */
455 static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
457 return 0;
459 #endif
461 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
462 struct brcmf_chip *ci)
464 u32 regdata;
465 u32 socitype;
467 /* Get CC core rev
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),
474 NULL);
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 &&
478 ci->chiprev >= 2)
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");
488 return -ENODEV;
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 */
516 switch (ci->chip) {
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;
536 break;
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;
556 break;
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;
576 break;
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;
596 break;
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;
613 break;
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;
633 break;
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;
650 break;
651 default:
652 brcmf_err("AXI chip is not supported\n");
653 return -ENODEV;
655 } else {
656 brcmf_err("chip backplane type %u is not supported\n",
657 socitype);
658 return -ENODEV;
661 return brcmf_sdio_chip_cichk(ci);
664 static int
665 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
667 int err = 0;
668 u8 clkval, clkset;
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);
673 if (err) {
674 brcmf_err("error writing for HT off\n");
675 return err;
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",
685 clkset, clkval);
686 return -EACCES;
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",
695 clkval);
696 return -EBUSY;
699 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
700 brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
701 udelay(65);
703 /* Also, disable the extra SDIO pull-ups */
704 brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
706 return 0;
709 static void
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),
721 NULL);
723 /* get pmu caps & rev */
724 if (ci->c_inf[0].caps & CC_CAP_PMU) {
725 ci->pmucaps =
726 brcmf_sdiod_regrl(sdiodev,
727 CORE_CC_REG(base, pmucapabilities),
728 NULL);
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)
748 int ret;
749 struct brcmf_chip *ci;
751 brcmf_dbg(TRACE, "Enter\n");
753 ci = kzalloc(sizeof(*ci), GFP_ATOMIC);
754 if (!ci)
755 return -ENOMEM;
757 ret = brcmf_sdio_chip_buscoreprep(sdiodev);
758 if (ret != 0)
759 goto err;
761 ret = brcmf_sdio_chip_recognition(sdiodev, ci);
762 if (ret != 0)
763 goto err;
765 brcmf_sdio_chip_buscoresetup(sdiodev, ci);
767 brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
768 0, NULL);
769 brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
770 0, NULL);
772 *ci_ptr = ci;
773 return 0;
775 err:
776 kfree(ci);
777 return ret;
780 void
781 brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr)
783 brcmf_dbg(TRACE, "Enter\n");
785 kfree(*ci_ptr);
786 *ci_ptr = NULL;
789 static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
791 const char *fmt;
793 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
794 snprintf(buf, len, fmt, chipid);
795 return buf;
798 void
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;
803 u32 str_mask;
804 u32 str_shift;
805 char chn[8];
806 u32 base = ci->c_inf[0].base;
807 u32 i;
808 u32 drivestrength_sel = 0;
809 u32 cc_data_temp;
810 u32 addr;
812 if (!(ci->c_inf[0].caps & CC_CAP_PMU))
813 return;
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;
819 str_shift = 11;
820 break;
821 case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
822 str_tab = sdiod_drvstr_tab6_1v8;
823 str_mask = 0x00001800;
824 str_shift = 11;
825 break;
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;
832 str_shift = 0;
833 } else
834 brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
835 brcmf_sdio_chip_name(ci->chip, chn, 8),
836 drivestrength);
837 break;
838 case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
839 str_tab = sdiod_drive_strength_tab5_1v8;
840 str_mask = 0x00003800;
841 str_shift = 11;
842 break;
843 default:
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);
847 break;
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;
854 break;
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);
870 static void
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)
884 u8 core_idx;
885 u32 reg_addr;
887 if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
888 brcmf_err("SOCRAM core is down after reset?\n");
889 return false;
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);
900 return true;
903 static inline void
904 brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
905 struct brcmf_chip *ci)
907 u8 idx;
908 u32 regdata;
909 u32 wrapbase;
910 idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
912 if (idx == BRCMF_MAX_CORENUM)
913 return;
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)
928 u8 core_idx;
929 u32 reg_addr;
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,
939 sizeof(rstvec));
941 /* restore ARM */
942 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
943 0, 0);
945 return true;
948 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
949 struct brcmf_chip *ci)
951 u8 arm_core_idx;
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);
956 return;
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)
965 u8 arm_core_idx;
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);