]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
brcmfmac: Create common nvram parsing routines.
[karo-tx-linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / sdio_chip.c
1 /*
2  * Copyright (c) 2011 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /* ***** SDIO interface chip backplane handle functions ***** */
17
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>
25
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"
34
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
44
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
53
54 #define SBCOREREV(sbidh) \
55         ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
56           ((sbidh) & SSB_IDHIGH_RCLO))
57
58 /* SOC Interconnect types (aka chip types) */
59 #define SOCI_SB         0
60 #define SOCI_AI         1
61
62 /* EROM CompIdentB */
63 #define CIB_REV_MASK            0xff000000
64 #define CIB_REV_SHIFT           24
65
66 /* ARM CR4 core specific control flag bits */
67 #define ARMCR4_BCMA_IOCTL_CPUHALT       0x0020
68
69 #define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
70 /* SDIO Pad drive strength to select value mappings */
71 struct sdiod_drive_str {
72         u8 strength;    /* Pad Drive Strength in mA */
73         u8 sel;         /* Chip-specific select value */
74 };
75 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
76 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
77         {32, 0x6},
78         {26, 0x7},
79         {22, 0x4},
80         {16, 0x5},
81         {12, 0x2},
82         {8, 0x3},
83         {4, 0x0},
84         {0, 0x1}
85 };
86
87 /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
88 static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
89         {6, 0x7},
90         {5, 0x6},
91         {4, 0x5},
92         {3, 0x4},
93         {2, 0x2},
94         {1, 0x1},
95         {0, 0x0}
96 };
97
98 /* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
99 static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
100         {3, 0x3},
101         {2, 0x2},
102         {1, 0x1},
103         {0, 0x0} };
104
105 /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
106 static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
107         {16, 0x7},
108         {12, 0x5},
109         {8,  0x3},
110         {4,  0x1}
111 };
112
113 u8
114 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
115 {
116         u8 idx;
117
118         for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
119                 if (coreid == ci->c_inf[idx].id)
120                         return idx;
121
122         return BRCMF_MAX_CORENUM;
123 }
124
125 static u32
126 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
127                       struct chip_info *ci, u16 coreid)
128 {
129         u32 regdata;
130         u8 idx;
131
132         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
133
134         regdata = brcmf_sdiod_regrl(sdiodev,
135                                     CORE_SB(ci->c_inf[idx].base, sbidhigh),
136                                     NULL);
137         return SBCOREREV(regdata);
138 }
139
140 static u32
141 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
142                       struct chip_info *ci, u16 coreid)
143 {
144         u8 idx;
145
146         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
147
148         return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
149 }
150
151 static bool
152 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
153                        struct chip_info *ci, u16 coreid)
154 {
155         u32 regdata;
156         u8 idx;
157
158         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
159         if (idx == BRCMF_MAX_CORENUM)
160                 return false;
161
162         regdata = brcmf_sdiod_regrl(sdiodev,
163                                     CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
164                                     NULL);
165         regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
166                     SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
167         return (SSB_TMSLOW_CLOCK == regdata);
168 }
169
170 static bool
171 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
172                        struct chip_info *ci, u16 coreid)
173 {
174         u32 regdata;
175         u8 idx;
176         bool ret;
177
178         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
179         if (idx == BRCMF_MAX_CORENUM)
180                 return false;
181
182         regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
183                                     NULL);
184         ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
185
186         regdata = brcmf_sdiod_regrl(sdiodev,
187                                     ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
188                                     NULL);
189         ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
190
191         return ret;
192 }
193
194 static void
195 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
196                           struct chip_info *ci, u16 coreid, u32 core_bits)
197 {
198         u32 regdata, base;
199         u8 idx;
200
201         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
202         base = ci->c_inf[idx].base;
203
204         regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
205         if (regdata & SSB_TMSLOW_RESET)
206                 return;
207
208         regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
209         if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
210                 /*
211                  * set target reject and spin until busy is clear
212                  * (preserve core-specific bits)
213                  */
214                 regdata = brcmf_sdiod_regrl(sdiodev,
215                                             CORE_SB(base, sbtmstatelow), NULL);
216                 brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
217                                   regdata | SSB_TMSLOW_REJECT, NULL);
218
219                 regdata = brcmf_sdiod_regrl(sdiodev,
220                                             CORE_SB(base, sbtmstatelow), NULL);
221                 udelay(1);
222                 SPINWAIT((brcmf_sdiod_regrl(sdiodev,
223                                             CORE_SB(base, sbtmstatehigh),
224                                             NULL) &
225                           SSB_TMSHIGH_BUSY), 100000);
226
227                 regdata = brcmf_sdiod_regrl(sdiodev,
228                                             CORE_SB(base, sbtmstatehigh),
229                                             NULL);
230                 if (regdata & SSB_TMSHIGH_BUSY)
231                         brcmf_err("core state still busy\n");
232
233                 regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
234                                             NULL);
235                 if (regdata & SSB_IDLOW_INITIATOR) {
236                         regdata = brcmf_sdiod_regrl(sdiodev,
237                                                     CORE_SB(base, sbimstate),
238                                                     NULL);
239                         regdata |= SSB_IMSTATE_REJECT;
240                         brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
241                                           regdata, NULL);
242                         regdata = brcmf_sdiod_regrl(sdiodev,
243                                                     CORE_SB(base, sbimstate),
244                                                     NULL);
245                         udelay(1);
246                         SPINWAIT((brcmf_sdiod_regrl(sdiodev,
247                                                     CORE_SB(base, sbimstate),
248                                                     NULL) &
249                                   SSB_IMSTATE_BUSY), 100000);
250                 }
251
252                 /* set reset and reject while enabling the clocks */
253                 regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
254                           SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
255                 brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
256                                   regdata, NULL);
257                 regdata = brcmf_sdiod_regrl(sdiodev,
258                                             CORE_SB(base, sbtmstatelow), NULL);
259                 udelay(10);
260
261                 /* clear the initiator reject bit */
262                 regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
263                                             NULL);
264                 if (regdata & SSB_IDLOW_INITIATOR) {
265                         regdata = brcmf_sdiod_regrl(sdiodev,
266                                                     CORE_SB(base, sbimstate),
267                                                     NULL);
268                         regdata &= ~SSB_IMSTATE_REJECT;
269                         brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
270                                           regdata, NULL);
271                 }
272         }
273
274         /* leave reset and reject asserted */
275         brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
276                           (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
277         udelay(1);
278 }
279
280 static void
281 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
282                           struct chip_info *ci, u16 coreid, u32 core_bits)
283 {
284         u8 idx;
285         u32 regdata;
286
287         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
288         if (idx == BRCMF_MAX_CORENUM)
289                 return;
290
291         /* if core is already in reset, just return */
292         regdata = brcmf_sdiod_regrl(sdiodev,
293                                     ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
294                                     NULL);
295         if ((regdata & BCMA_RESET_CTL_RESET) != 0)
296                 return;
297
298         /* ensure no pending backplane operation
299          * 300uc should be sufficient for backplane ops to be finish
300          * extra 10ms is taken into account for firmware load stage
301          * after 10300us carry on disabling the core anyway
302          */
303         SPINWAIT(brcmf_sdiod_regrl(sdiodev,
304                                    ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
305                                    NULL), 10300);
306         regdata = brcmf_sdiod_regrl(sdiodev,
307                                     ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
308                                     NULL);
309         if (regdata)
310                 brcmf_err("disabling core 0x%x with reset status %x\n",
311                           coreid, regdata);
312
313         brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
314                           BCMA_RESET_CTL_RESET, NULL);
315         udelay(1);
316
317         brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
318                           core_bits, NULL);
319         regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
320                                     NULL);
321         usleep_range(10, 20);
322
323 }
324
325 static void
326 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
327                         struct chip_info *ci, u16 coreid, u32 core_bits)
328 {
329         u32 regdata;
330         u8 idx;
331
332         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
333         if (idx == BRCMF_MAX_CORENUM)
334                 return;
335
336         /*
337          * Must do the disable sequence first to work for
338          * arbitrary current core state.
339          */
340         brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
341
342         /*
343          * Now do the initialization sequence.
344          * set reset while enabling the clock and
345          * forcing them on throughout the core
346          */
347         brcmf_sdiod_regwl(sdiodev,
348                           CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
349                           SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
350                           NULL);
351         regdata = brcmf_sdiod_regrl(sdiodev,
352                                     CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
353                                     NULL);
354         udelay(1);
355
356         /* clear any serror */
357         regdata = brcmf_sdiod_regrl(sdiodev,
358                                     CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
359                                     NULL);
360         if (regdata & SSB_TMSHIGH_SERR)
361                 brcmf_sdiod_regwl(sdiodev,
362                                   CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
363                                   0, NULL);
364
365         regdata = brcmf_sdiod_regrl(sdiodev,
366                                     CORE_SB(ci->c_inf[idx].base, sbimstate),
367                                     NULL);
368         if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
369                 brcmf_sdiod_regwl(sdiodev,
370                                   CORE_SB(ci->c_inf[idx].base, sbimstate),
371                                   regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
372                                   NULL);
373
374         /* clear reset and allow it to propagate throughout the core */
375         brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
376                           SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
377         regdata = brcmf_sdiod_regrl(sdiodev,
378                                     CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
379                                     NULL);
380         udelay(1);
381
382         /* leave clock enabled */
383         brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
384                           SSB_TMSLOW_CLOCK, NULL);
385         regdata = brcmf_sdiod_regrl(sdiodev,
386                                     CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
387                                     NULL);
388         udelay(1);
389 }
390
391 static void
392 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
393                         struct chip_info *ci, u16 coreid, u32 core_bits)
394 {
395         u8 idx;
396         u32 regdata;
397
398         idx = brcmf_sdio_chip_getinfidx(ci, coreid);
399         if (idx == BRCMF_MAX_CORENUM)
400                 return;
401
402         /* must disable first to work for arbitrary current core state */
403         brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
404
405         /* now do initialization sequence */
406         brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
407                           core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
408         regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
409                                     NULL);
410         brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
411                           0, NULL);
412         regdata = brcmf_sdiod_regrl(sdiodev,
413                                     ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
414                                     NULL);
415         udelay(1);
416
417         brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
418                           core_bits | BCMA_IOCTL_CLK, NULL);
419         regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
420                                     NULL);
421         udelay(1);
422 }
423
424 #ifdef DEBUG
425 /* safety check for chipinfo */
426 static int brcmf_sdio_chip_cichk(struct chip_info *ci)
427 {
428         u8 core_idx;
429
430         /* check RAM core presence for ARM CM3 core */
431         core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
432         if (BRCMF_MAX_CORENUM != core_idx) {
433                 core_idx = brcmf_sdio_chip_getinfidx(ci,
434                                                      BCMA_CORE_INTERNAL_MEM);
435                 if (BRCMF_MAX_CORENUM == core_idx) {
436                         brcmf_err("RAM core not provided with ARM CM3 core\n");
437                         return -ENODEV;
438                 }
439         }
440
441         /* check RAM base for ARM CR4 core */
442         core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
443         if (BRCMF_MAX_CORENUM != core_idx) {
444                 if (ci->rambase == 0) {
445                         brcmf_err("RAM base not provided with ARM CR4 core\n");
446                         return -ENOMEM;
447                 }
448         }
449
450         return 0;
451 }
452 #else   /* DEBUG */
453 static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
454 {
455         return 0;
456 }
457 #endif
458
459 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
460                                        struct chip_info *ci)
461 {
462         u32 regdata;
463         int ret;
464
465         /* Get CC core rev
466          * Chipid is assume to be at offset 0 from regs arg
467          * For different chiptypes or old sdio hosts w/o chipcommon,
468          * other ways of recognition should be added here.
469          */
470         ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
471         ci->c_inf[0].base = SI_ENUM_BASE;
472         regdata = brcmf_sdiod_regrl(sdiodev,
473                                     CORE_CC_REG(ci->c_inf[0].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         ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
481
482         brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
483
484         /* Address of cores for new chips should be added here */
485         switch (ci->chip) {
486         case BCM43143_CHIP_ID:
487                 ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
488                 ci->c_inf[0].cib = 0x2b000000;
489                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
490                 ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
491                 ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
492                 ci->c_inf[1].cib = 0x18000000;
493                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
494                 ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
495                 ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
496                 ci->c_inf[2].cib = 0x14000000;
497                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
498                 ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
499                 ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
500                 ci->c_inf[3].cib = 0x07000000;
501                 ci->ramsize = BCM43143_RAMSIZE;
502                 break;
503         case BCM43241_CHIP_ID:
504                 ci->c_inf[0].wrapbase = 0x18100000;
505                 ci->c_inf[0].cib = 0x2a084411;
506                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
507                 ci->c_inf[1].base = 0x18002000;
508                 ci->c_inf[1].wrapbase = 0x18102000;
509                 ci->c_inf[1].cib = 0x0e004211;
510                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
511                 ci->c_inf[2].base = 0x18004000;
512                 ci->c_inf[2].wrapbase = 0x18104000;
513                 ci->c_inf[2].cib = 0x14080401;
514                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
515                 ci->c_inf[3].base = 0x18003000;
516                 ci->c_inf[3].wrapbase = 0x18103000;
517                 ci->c_inf[3].cib = 0x07004211;
518                 ci->ramsize = 0x90000;
519                 break;
520         case BCM4329_CHIP_ID:
521                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
522                 ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
523                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
524                 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
525                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
526                 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
527                 ci->ramsize = BCM4329_RAMSIZE;
528                 break;
529         case BCM4330_CHIP_ID:
530                 ci->c_inf[0].wrapbase = 0x18100000;
531                 ci->c_inf[0].cib = 0x27004211;
532                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
533                 ci->c_inf[1].base = 0x18002000;
534                 ci->c_inf[1].wrapbase = 0x18102000;
535                 ci->c_inf[1].cib = 0x07004211;
536                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
537                 ci->c_inf[2].base = 0x18004000;
538                 ci->c_inf[2].wrapbase = 0x18104000;
539                 ci->c_inf[2].cib = 0x0d080401;
540                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
541                 ci->c_inf[3].base = 0x18003000;
542                 ci->c_inf[3].wrapbase = 0x18103000;
543                 ci->c_inf[3].cib = 0x03004211;
544                 ci->ramsize = 0x48000;
545                 break;
546         case BCM4334_CHIP_ID:
547                 ci->c_inf[0].wrapbase = 0x18100000;
548                 ci->c_inf[0].cib = 0x29004211;
549                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
550                 ci->c_inf[1].base = 0x18002000;
551                 ci->c_inf[1].wrapbase = 0x18102000;
552                 ci->c_inf[1].cib = 0x0d004211;
553                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
554                 ci->c_inf[2].base = 0x18004000;
555                 ci->c_inf[2].wrapbase = 0x18104000;
556                 ci->c_inf[2].cib = 0x13080401;
557                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
558                 ci->c_inf[3].base = 0x18003000;
559                 ci->c_inf[3].wrapbase = 0x18103000;
560                 ci->c_inf[3].cib = 0x07004211;
561                 ci->ramsize = 0x80000;
562                 break;
563         case BCM4335_CHIP_ID:
564                 ci->c_inf[0].wrapbase = 0x18100000;
565                 ci->c_inf[0].cib = 0x2b084411;
566                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
567                 ci->c_inf[1].base = 0x18005000;
568                 ci->c_inf[1].wrapbase = 0x18105000;
569                 ci->c_inf[1].cib = 0x0f004211;
570                 ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
571                 ci->c_inf[2].base = 0x18002000;
572                 ci->c_inf[2].wrapbase = 0x18102000;
573                 ci->c_inf[2].cib = 0x01084411;
574                 ci->ramsize = 0xc0000;
575                 ci->rambase = 0x180000;
576                 break;
577         case BCM4339_CHIP_ID:
578                 ci->c_inf[0].wrapbase = 0x18100000;
579                 ci->c_inf[0].cib = 0x2e084411;
580                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
581                 ci->c_inf[1].base = 0x18005000;
582                 ci->c_inf[1].wrapbase = 0x18105000;
583                 ci->c_inf[1].cib = 0x15004211;
584                 ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
585                 ci->c_inf[2].base = 0x18002000;
586                 ci->c_inf[2].wrapbase = 0x18102000;
587                 ci->c_inf[2].cib = 0x04084411;
588                 ci->ramsize = 0xc0000;
589                 ci->rambase = 0x180000;
590                 break;
591         case BCM43362_CHIP_ID:
592                 ci->c_inf[0].wrapbase = 0x18100000;
593                 ci->c_inf[0].cib = 0x27004211;
594                 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
595                 ci->c_inf[1].base = 0x18002000;
596                 ci->c_inf[1].wrapbase = 0x18102000;
597                 ci->c_inf[1].cib = 0x0a004211;
598                 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
599                 ci->c_inf[2].base = 0x18004000;
600                 ci->c_inf[2].wrapbase = 0x18104000;
601                 ci->c_inf[2].cib = 0x08080401;
602                 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
603                 ci->c_inf[3].base = 0x18003000;
604                 ci->c_inf[3].wrapbase = 0x18103000;
605                 ci->c_inf[3].cib = 0x03004211;
606                 ci->ramsize = 0x3C000;
607                 break;
608         default:
609                 brcmf_err("chipid 0x%x is not supported\n", ci->chip);
610                 return -ENODEV;
611         }
612
613         ret = brcmf_sdio_chip_cichk(ci);
614         if (ret)
615                 return ret;
616
617         switch (ci->socitype) {
618         case SOCI_SB:
619                 ci->iscoreup = brcmf_sdio_sb_iscoreup;
620                 ci->corerev = brcmf_sdio_sb_corerev;
621                 ci->coredisable = brcmf_sdio_sb_coredisable;
622                 ci->resetcore = brcmf_sdio_sb_resetcore;
623                 break;
624         case SOCI_AI:
625                 ci->iscoreup = brcmf_sdio_ai_iscoreup;
626                 ci->corerev = brcmf_sdio_ai_corerev;
627                 ci->coredisable = brcmf_sdio_ai_coredisable;
628                 ci->resetcore = brcmf_sdio_ai_resetcore;
629                 break;
630         default:
631                 brcmf_err("socitype %u not supported\n", ci->socitype);
632                 return -ENODEV;
633         }
634
635         return 0;
636 }
637
638 static int
639 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
640 {
641         int err = 0;
642         u8 clkval, clkset;
643
644         /* Try forcing SDIO core to do ALPAvail request only */
645         clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
646         brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
647         if (err) {
648                 brcmf_err("error writing for HT off\n");
649                 return err;
650         }
651
652         /* If register supported, wait for ALPAvail and then force ALP */
653         /* This may take up to 15 milliseconds */
654         clkval = brcmf_sdiod_regrb(sdiodev,
655                                    SBSDIO_FUNC1_CHIPCLKCSR, NULL);
656
657         if ((clkval & ~SBSDIO_AVBITS) != clkset) {
658                 brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
659                           clkset, clkval);
660                 return -EACCES;
661         }
662
663         SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
664                                               SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
665                         !SBSDIO_ALPAV(clkval)),
666                         PMU_MAX_TRANSITION_DLY);
667         if (!SBSDIO_ALPAV(clkval)) {
668                 brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
669                           clkval);
670                 return -EBUSY;
671         }
672
673         clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
674         brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
675         udelay(65);
676
677         /* Also, disable the extra SDIO pull-ups */
678         brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
679
680         return 0;
681 }
682
683 static void
684 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
685                              struct chip_info *ci)
686 {
687         u32 base = ci->c_inf[0].base;
688
689         /* get chipcommon rev */
690         ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
691
692         /* get chipcommon capabilites */
693         ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev,
694                                               CORE_CC_REG(base, capabilities),
695                                               NULL);
696
697         /* get pmu caps & rev */
698         if (ci->c_inf[0].caps & CC_CAP_PMU) {
699                 ci->pmucaps =
700                         brcmf_sdiod_regrl(sdiodev,
701                                           CORE_CC_REG(base, pmucapabilities),
702                                           NULL);
703                 ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
704         }
705
706         ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
707
708         brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
709                   ci->c_inf[0].rev, ci->pmurev,
710                   ci->c_inf[1].rev, ci->c_inf[1].id);
711
712         /*
713          * Make sure any on-chip ARM is off (in case strapping is wrong),
714          * or downloaded code was already running.
715          */
716         ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
717 }
718
719 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
720                            struct chip_info **ci_ptr)
721 {
722         int ret;
723         struct chip_info *ci;
724
725         brcmf_dbg(TRACE, "Enter\n");
726
727         /* alloc chip_info_t */
728         ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
729         if (!ci)
730                 return -ENOMEM;
731
732         ret = brcmf_sdio_chip_buscoreprep(sdiodev);
733         if (ret != 0)
734                 goto err;
735
736         ret = brcmf_sdio_chip_recognition(sdiodev, ci);
737         if (ret != 0)
738                 goto err;
739
740         brcmf_sdio_chip_buscoresetup(sdiodev, ci);
741
742         brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
743                           0, NULL);
744         brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
745                           0, NULL);
746
747         *ci_ptr = ci;
748         return 0;
749
750 err:
751         kfree(ci);
752         return ret;
753 }
754
755 void
756 brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
757 {
758         brcmf_dbg(TRACE, "Enter\n");
759
760         kfree(*ci_ptr);
761         *ci_ptr = NULL;
762 }
763
764 static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
765 {
766         const char *fmt;
767
768         fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
769         snprintf(buf, len, fmt, chipid);
770         return buf;
771 }
772
773 void
774 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
775                                   struct chip_info *ci, u32 drivestrength)
776 {
777         const struct sdiod_drive_str *str_tab = NULL;
778         u32 str_mask;
779         u32 str_shift;
780         char chn[8];
781         u32 base = ci->c_inf[0].base;
782         u32 i;
783         u32 drivestrength_sel = 0;
784         u32 cc_data_temp;
785         u32 addr;
786
787         if (!(ci->c_inf[0].caps & CC_CAP_PMU))
788                 return;
789
790         switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
791         case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
792                 str_tab = sdiod_drvstr_tab1_1v8;
793                 str_mask = 0x00003800;
794                 str_shift = 11;
795                 break;
796         case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
797                 str_tab = sdiod_drvstr_tab6_1v8;
798                 str_mask = 0x00001800;
799                 str_shift = 11;
800                 break;
801         case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
802                 /* note: 43143 does not support tristate */
803                 i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
804                 if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
805                         str_tab = sdiod_drvstr_tab2_3v3;
806                         str_mask = 0x00000007;
807                         str_shift = 0;
808                 } else
809                         brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
810                                   brcmf_sdio_chip_name(ci->chip, chn, 8),
811                                   drivestrength);
812                 break;
813         case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
814                 str_tab = sdiod_drive_strength_tab5_1v8;
815                 str_mask = 0x00003800;
816                 str_shift = 11;
817                 break;
818         default:
819                 brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
820                           brcmf_sdio_chip_name(ci->chip, chn, 8),
821                           ci->chiprev, ci->pmurev);
822                 break;
823         }
824
825         if (str_tab != NULL) {
826                 for (i = 0; str_tab[i].strength != 0; i++) {
827                         if (drivestrength >= str_tab[i].strength) {
828                                 drivestrength_sel = str_tab[i].sel;
829                                 break;
830                         }
831                 }
832                 addr = CORE_CC_REG(base, chipcontrol_addr);
833                 brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
834                 cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
835                 cc_data_temp &= ~str_mask;
836                 drivestrength_sel <<= str_shift;
837                 cc_data_temp |= drivestrength_sel;
838                 brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
839
840                 brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
841                           str_tab[i].strength, drivestrength, cc_data_temp);
842         }
843 }
844
845 static void
846 brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
847                             struct chip_info *ci)
848 {
849         ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
850         ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
851 }
852
853 static bool
854 brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
855 {
856         u8 core_idx;
857         u32 reg_addr;
858
859         if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
860                 brcmf_err("SOCRAM core is down after reset?\n");
861                 return false;
862         }
863
864         /* clear all interrupts */
865         core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
866         reg_addr = ci->c_inf[core_idx].base;
867         reg_addr += offsetof(struct sdpcmd_regs, intstatus);
868         brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
869
870         ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
871
872         return true;
873 }
874
875 static inline void
876 brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
877                             struct chip_info *ci)
878 {
879         ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
880                       ARMCR4_BCMA_IOCTL_CPUHALT);
881 }
882
883 static bool
884 brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
885 {
886         u8 core_idx;
887         u32 reg_addr;
888
889         /* clear all interrupts */
890         core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
891         reg_addr = ci->c_inf[core_idx].base;
892         reg_addr += offsetof(struct sdpcmd_regs, intstatus);
893         brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
894
895         /* Write reset vector to address 0 */
896         brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
897                           sizeof(ci->rst_vec));
898
899         /* restore ARM */
900         ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
901
902         return true;
903 }
904
905 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
906                                     struct chip_info *ci)
907 {
908         u8 arm_core_idx;
909
910         arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
911         if (BRCMF_MAX_CORENUM != arm_core_idx) {
912                 brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
913                 return;
914         }
915
916         brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
917 }
918
919 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
920                                    struct chip_info *ci)
921 {
922         u8 arm_core_idx;
923
924         arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
925         if (BRCMF_MAX_CORENUM != arm_core_idx)
926                 return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
927
928         return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci);
929 }