brcm80211: fmac: optimize chip core info management
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / sdio_chip.c
CommitLineData
a83369b6
FL
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>
61213be4 21#include <linux/ssb/ssb_regs.h>
99ba15cd 22#include <linux/bcma/bcma.h>
61213be4 23
a83369b6
FL
24#include <chipcommon.h>
25#include <brcm_hw_ids.h>
26#include <brcmu_wifi.h>
27#include <brcmu_utils.h>
2d4a9af1 28#include <soc.h>
a83369b6
FL
29#include "dhd.h"
30#include "dhd_dbg.h"
31#include "sdio_host.h"
32#include "sdio_chip.h"
33
34/* chip core base & ramsize */
35/* bcm4329 */
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
43
a83369b6 44#define SBCOREREV(sbidh) \
61213be4
FL
45 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
46 ((sbidh) & SSB_IDHIGH_RCLO))
a83369b6 47
e12afb6c
FL
48#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
49/* SDIO Pad drive strength to select value mappings */
50struct sdiod_drive_str {
51 u8 strength; /* Pad Drive Strength in mA */
52 u8 sel; /* Chip-specific select value */
53};
54/* SDIO Drive Strength to sel value table for PMU Rev 1 */
55static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
56 {
57 4, 0x2}, {
58 2, 0x3}, {
59 1, 0x0}, {
60 0, 0x0}
61 };
62/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
63static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
64 {
65 12, 0x7}, {
66 10, 0x6}, {
67 8, 0x5}, {
68 6, 0x4}, {
69 4, 0x2}, {
70 2, 0x1}, {
71 0, 0x0}
72 };
73/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
74static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
75 {
76 32, 0x7}, {
77 26, 0x6}, {
78 22, 0x5}, {
79 16, 0x4}, {
80 12, 0x3}, {
81 8, 0x2}, {
82 4, 0x1}, {
83 0, 0x0}
84 };
85
99ba15cd
FL
86u8
87brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
88{
89 u8 idx;
90
91 for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
92 if (coreid == ci->c_inf[idx].id)
93 return idx;
94
95 return BRCMF_MAX_CORENUM;
96}
97
454d2a88
FL
98static u32
99brcmf_sdio_chip_corerev(struct brcmf_sdio_dev *sdiodev,
100 u32 corebase)
101{
102 u32 regdata;
103
104 regdata = brcmf_sdcard_reg_read(sdiodev,
105 CORE_SB(corebase, sbidhigh), 4);
106 return SBCOREREV(regdata);
107}
108
d8f64a42
FL
109bool
110brcmf_sdio_chip_iscoreup(struct brcmf_sdio_dev *sdiodev,
111 u32 corebase)
112{
113 u32 regdata;
114
115 regdata = brcmf_sdcard_reg_read(sdiodev,
116 CORE_SB(corebase, sbtmstatelow), 4);
61213be4
FL
117 regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
118 SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
119 return (SSB_TMSLOW_CLOCK == regdata);
d8f64a42
FL
120}
121
2d4a9af1
FL
122void
123brcmf_sdio_chip_coredisable(struct brcmf_sdio_dev *sdiodev, u32 corebase)
124{
125 u32 regdata;
126
127 regdata = brcmf_sdcard_reg_read(sdiodev,
128 CORE_SB(corebase, sbtmstatelow), 4);
61213be4 129 if (regdata & SSB_TMSLOW_RESET)
2d4a9af1
FL
130 return;
131
132 regdata = brcmf_sdcard_reg_read(sdiodev,
133 CORE_SB(corebase, sbtmstatelow), 4);
61213be4 134 if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
2d4a9af1
FL
135 /*
136 * set target reject and spin until busy is clear
137 * (preserve core-specific bits)
138 */
139 regdata = brcmf_sdcard_reg_read(sdiodev,
140 CORE_SB(corebase, sbtmstatelow), 4);
141 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
61213be4 142 4, regdata | SSB_TMSLOW_REJECT);
2d4a9af1
FL
143
144 regdata = brcmf_sdcard_reg_read(sdiodev,
145 CORE_SB(corebase, sbtmstatelow), 4);
146 udelay(1);
147 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
148 CORE_SB(corebase, sbtmstatehigh), 4) &
61213be4 149 SSB_TMSHIGH_BUSY), 100000);
2d4a9af1
FL
150
151 regdata = brcmf_sdcard_reg_read(sdiodev,
152 CORE_SB(corebase, sbtmstatehigh), 4);
61213be4 153 if (regdata & SSB_TMSHIGH_BUSY)
2d4a9af1
FL
154 brcmf_dbg(ERROR, "core state still busy\n");
155
156 regdata = brcmf_sdcard_reg_read(sdiodev,
157 CORE_SB(corebase, sbidlow), 4);
61213be4 158 if (regdata & SSB_IDLOW_INITIATOR) {
2d4a9af1
FL
159 regdata = brcmf_sdcard_reg_read(sdiodev,
160 CORE_SB(corebase, sbimstate), 4) |
61213be4 161 SSB_IMSTATE_REJECT;
2d4a9af1
FL
162 brcmf_sdcard_reg_write(sdiodev,
163 CORE_SB(corebase, sbimstate), 4,
164 regdata);
165 regdata = brcmf_sdcard_reg_read(sdiodev,
166 CORE_SB(corebase, sbimstate), 4);
167 udelay(1);
168 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
169 CORE_SB(corebase, sbimstate), 4) &
61213be4 170 SSB_IMSTATE_BUSY), 100000);
2d4a9af1
FL
171 }
172
173 /* set reset and reject while enabling the clocks */
174 brcmf_sdcard_reg_write(sdiodev,
175 CORE_SB(corebase, sbtmstatelow), 4,
61213be4
FL
176 (SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
177 SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
2d4a9af1
FL
178 regdata = brcmf_sdcard_reg_read(sdiodev,
179 CORE_SB(corebase, sbtmstatelow), 4);
180 udelay(10);
181
182 /* clear the initiator reject bit */
183 regdata = brcmf_sdcard_reg_read(sdiodev,
184 CORE_SB(corebase, sbidlow), 4);
61213be4 185 if (regdata & SSB_IDLOW_INITIATOR) {
2d4a9af1
FL
186 regdata = brcmf_sdcard_reg_read(sdiodev,
187 CORE_SB(corebase, sbimstate), 4) &
61213be4 188 ~SSB_IMSTATE_REJECT;
2d4a9af1
FL
189 brcmf_sdcard_reg_write(sdiodev,
190 CORE_SB(corebase, sbimstate), 4,
191 regdata);
192 }
193 }
194
195 /* leave reset and reject asserted */
196 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
61213be4 197 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
2d4a9af1
FL
198 udelay(1);
199}
200
2bc78e10
FL
201void
202brcmf_sdio_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
203{
204 u32 regdata;
205
206 /*
207 * Must do the disable sequence first to work for
208 * arbitrary current core state.
209 */
210 brcmf_sdio_chip_coredisable(sdiodev, corebase);
211
212 /*
213 * Now do the initialization sequence.
214 * set reset while enabling the clock and
215 * forcing them on throughout the core
216 */
217 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
61213be4 218 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
2bc78e10
FL
219 udelay(1);
220
221 regdata = brcmf_sdcard_reg_read(sdiodev,
222 CORE_SB(corebase, sbtmstatehigh), 4);
61213be4 223 if (regdata & SSB_TMSHIGH_SERR)
2bc78e10
FL
224 brcmf_sdcard_reg_write(sdiodev,
225 CORE_SB(corebase, sbtmstatehigh), 4, 0);
226
227 regdata = brcmf_sdcard_reg_read(sdiodev,
228 CORE_SB(corebase, sbimstate), 4);
61213be4 229 if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
2bc78e10 230 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
61213be4 231 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
2bc78e10
FL
232
233 /* clear reset and allow it to propagate throughout the core */
234 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
61213be4 235 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
2bc78e10
FL
236 udelay(1);
237
238 /* leave clock enabled */
61213be4
FL
239 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
240 4, SSB_TMSLOW_CLOCK);
2bc78e10
FL
241 udelay(1);
242}
243
a83369b6
FL
244static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
245 struct chip_info *ci, u32 regs)
246{
247 u32 regdata;
248
249 /*
250 * Get CC core rev
251 * Chipid is assume to be at offset 0 from regs arg
252 * For different chiptypes or old sdio hosts w/o chipcommon,
253 * other ways of recognition should be added here.
254 */
99ba15cd
FL
255 ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
256 ci->c_inf[0].base = regs;
a83369b6 257 regdata = brcmf_sdcard_reg_read(sdiodev,
99ba15cd 258 CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
a83369b6
FL
259 ci->chip = regdata & CID_ID_MASK;
260 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
261
262 brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
263
264 /* Address of cores for new chips should be added here */
265 switch (ci->chip) {
266 case BCM4329_CHIP_ID:
99ba15cd
FL
267 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
268 ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
269 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
270 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
271 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
272 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
a83369b6
FL
273 ci->ramsize = BCM4329_RAMSIZE;
274 break;
275 default:
276 brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
277 return -ENODEV;
278 }
279
a83369b6
FL
280 return 0;
281}
282
e63ac6b8
FL
283static int
284brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
285{
286 int err = 0;
287 u8 clkval, clkset;
288
289 /* Try forcing SDIO core to do ALPAvail request only */
290 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
291 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
292 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
293 if (err) {
294 brcmf_dbg(ERROR, "error writing for HT off\n");
295 return err;
296 }
297
298 /* If register supported, wait for ALPAvail and then force ALP */
299 /* This may take up to 15 milliseconds */
300 clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
301 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
302
303 if ((clkval & ~SBSDIO_AVBITS) != clkset) {
304 brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
305 clkset, clkval);
306 return -EACCES;
307 }
308
309 SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
310 SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
311 !SBSDIO_ALPAV(clkval)),
312 PMU_MAX_TRANSITION_DLY);
313 if (!SBSDIO_ALPAV(clkval)) {
314 brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
315 clkval);
316 return -EBUSY;
317 }
318
319 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
320 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
321 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
322 udelay(65);
323
324 /* Also, disable the extra SDIO pull-ups */
325 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
326 SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
327
328 return 0;
329}
330
5b45e54e
FL
331static void
332brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
333 struct chip_info *ci)
334{
335 u32 regdata;
99ba15cd 336 u8 idx;
5b45e54e
FL
337
338 /* get chipcommon rev */
99ba15cd
FL
339 ci->c_inf[0].rev =
340 brcmf_sdio_chip_corerev(sdiodev, ci->c_inf[0].base);
5b45e54e
FL
341
342 /* get chipcommon capabilites */
99ba15cd
FL
343 ci->c_inf[0].caps =
344 brcmf_sdcard_reg_read(sdiodev,
345 CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
5b45e54e
FL
346
347 /* get pmu caps & rev */
99ba15cd 348 if (ci->c_inf[0].caps & CC_CAP_PMU) {
5b45e54e 349 ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
99ba15cd 350 CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
5b45e54e
FL
351 ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
352 }
353
99ba15cd 354 ci->c_inf[1].rev = brcmf_sdio_chip_corerev(sdiodev, ci->c_inf[1].base);
5b45e54e 355 regdata = brcmf_sdcard_reg_read(sdiodev,
99ba15cd
FL
356 CORE_SB(ci->c_inf[1].base, sbidhigh), 4);
357 ci->c_inf[1].id = (regdata & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
5b45e54e
FL
358
359 brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
99ba15cd
FL
360 ci->c_inf[0].rev, ci->pmurev,
361 ci->c_inf[1].rev, ci->c_inf[1].id);
966414da
FL
362
363 /*
364 * Make sure any on-chip ARM is off (in case strapping is wrong),
365 * or downloaded code was already running.
366 */
99ba15cd
FL
367 idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
368 brcmf_sdio_chip_coredisable(sdiodev, ci->c_inf[idx].base);
5b45e54e
FL
369}
370
a83369b6 371int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
a97e4fc5 372 struct chip_info **ci_ptr, u32 regs)
a83369b6 373{
a97e4fc5
FL
374 int ret;
375 struct chip_info *ci;
376
377 brcmf_dbg(TRACE, "Enter\n");
378
379 /* alloc chip_info_t */
380 ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
381 if (!ci)
382 return -ENOMEM;
a83369b6 383
e63ac6b8
FL
384 ret = brcmf_sdio_chip_buscoreprep(sdiodev);
385 if (ret != 0)
a97e4fc5 386 goto err;
e63ac6b8 387
a83369b6
FL
388 ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
389 if (ret != 0)
a97e4fc5 390 goto err;
a83369b6 391
5b45e54e
FL
392 brcmf_sdio_chip_buscoresetup(sdiodev, ci);
393
960908dc 394 brcmf_sdcard_reg_write(sdiodev,
99ba15cd 395 CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
960908dc 396 brcmf_sdcard_reg_write(sdiodev,
99ba15cd 397 CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
960908dc 398
a97e4fc5
FL
399 *ci_ptr = ci;
400 return 0;
401
402err:
403 kfree(ci);
a83369b6
FL
404 return ret;
405}
a8a6c045
FL
406
407void
408brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
409{
410 brcmf_dbg(TRACE, "Enter\n");
411
412 kfree(*ci_ptr);
413 *ci_ptr = NULL;
414}
e12afb6c
FL
415
416static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
417{
418 const char *fmt;
419
420 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
421 snprintf(buf, len, fmt, chipid);
422 return buf;
423}
424
425void
426brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
427 struct chip_info *ci, u32 drivestrength)
428{
429 struct sdiod_drive_str *str_tab = NULL;
430 u32 str_mask = 0;
431 u32 str_shift = 0;
432 char chn[8];
433
99ba15cd 434 if (!(ci->c_inf[0].caps & CC_CAP_PMU))
e12afb6c
FL
435 return;
436
437 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
438 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
439 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
440 str_mask = 0x30000000;
441 str_shift = 28;
442 break;
443 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
444 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
445 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
446 str_mask = 0x00003800;
447 str_shift = 11;
448 break;
449 case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
450 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
451 str_mask = 0x00003800;
452 str_shift = 11;
453 break;
454 default:
455 brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
456 brcmf_sdio_chip_name(ci->chip, chn, 8),
457 ci->chiprev, ci->pmurev);
458 break;
459 }
460
461 if (str_tab != NULL) {
462 u32 drivestrength_sel = 0;
463 u32 cc_data_temp;
464 int i;
465
466 for (i = 0; str_tab[i].strength != 0; i++) {
467 if (drivestrength >= str_tab[i].strength) {
468 drivestrength_sel = str_tab[i].sel;
469 break;
470 }
471 }
472
473 brcmf_sdcard_reg_write(sdiodev,
99ba15cd 474 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
e12afb6c
FL
475 4, 1);
476 cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
99ba15cd 477 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
e12afb6c
FL
478 cc_data_temp &= ~str_mask;
479 drivestrength_sel <<= str_shift;
480 cc_data_temp |= drivestrength_sel;
481 brcmf_sdcard_reg_write(sdiodev,
99ba15cd 482 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
e12afb6c
FL
483 4, cc_data_temp);
484
485 brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
486 drivestrength, cc_data_temp);
487 }
488}
This page took 0.067536 seconds and 5 git commands to generate.