blob: e068107f5fae1966df778a2bf8e9e6d5ce02fa10 [file] [log] [blame]
Franky Lina83369b2011-11-04 22:23:28 +01001/*
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 <chipcommon.h>
22#include <brcm_hw_ids.h>
23#include <brcmu_wifi.h>
24#include <brcmu_utils.h>
Franky Lin2d4a9af2011-11-04 22:23:31 +010025#include <soc.h>
Franky Lina83369b2011-11-04 22:23:28 +010026#include "dhd.h"
27#include "dhd_dbg.h"
28#include "sdio_host.h"
29#include "sdio_chip.h"
30
31/* chip core base & ramsize */
32/* bcm4329 */
33/* SDIO device core, ID 0x829 */
34#define BCM4329_CORE_BUS_BASE 0x18011000
35/* internal memory core, ID 0x80e */
36#define BCM4329_CORE_SOCRAM_BASE 0x18003000
37/* ARM Cortex M3 core, ID 0x82a */
38#define BCM4329_CORE_ARM_BASE 0x18002000
39#define BCM4329_RAMSIZE 0x48000
40
41
42/* SB regs */
43/* sbidhigh */
44#define SBIDH_RC_MASK 0x000f /* revision code */
45#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
46#define SBIDH_RCE_SHIFT 8
47#define SBCOREREV(sbidh) \
48 ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
49 ((sbidh) & SBIDH_RC_MASK))
50#define SBIDH_CC_MASK 0x8ff0 /* core code */
51#define SBIDH_CC_SHIFT 4
52#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
53#define SBIDH_VC_SHIFT 16
54
Franky Line12afb62011-11-04 22:23:40 +010055#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
56/* SDIO Pad drive strength to select value mappings */
57struct sdiod_drive_str {
58 u8 strength; /* Pad Drive Strength in mA */
59 u8 sel; /* Chip-specific select value */
60};
61/* SDIO Drive Strength to sel value table for PMU Rev 1 */
62static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
63 {
64 4, 0x2}, {
65 2, 0x3}, {
66 1, 0x0}, {
67 0, 0x0}
68 };
69/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
70static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
71 {
72 12, 0x7}, {
73 10, 0x6}, {
74 8, 0x5}, {
75 6, 0x4}, {
76 4, 0x2}, {
77 2, 0x1}, {
78 0, 0x0}
79 };
80/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
81static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
82 {
83 32, 0x7}, {
84 26, 0x6}, {
85 22, 0x5}, {
86 16, 0x4}, {
87 12, 0x3}, {
88 8, 0x2}, {
89 4, 0x1}, {
90 0, 0x0}
91 };
92
Franky Lin454d2a82011-11-04 22:23:37 +010093static u32
94brcmf_sdio_chip_corerev(struct brcmf_sdio_dev *sdiodev,
95 u32 corebase)
96{
97 u32 regdata;
98
99 regdata = brcmf_sdcard_reg_read(sdiodev,
100 CORE_SB(corebase, sbidhigh), 4);
101 return SBCOREREV(regdata);
102}
103
Franky Lind8f64a42011-11-04 22:23:36 +0100104bool
105brcmf_sdio_chip_iscoreup(struct brcmf_sdio_dev *sdiodev,
106 u32 corebase)
107{
108 u32 regdata;
109
110 regdata = brcmf_sdcard_reg_read(sdiodev,
111 CORE_SB(corebase, sbtmstatelow), 4);
112 regdata &= (SBTML_RESET | SBTML_REJ_MASK |
113 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
114 return ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) == regdata);
115}
116
Franky Lin2d4a9af2011-11-04 22:23:31 +0100117void
118brcmf_sdio_chip_coredisable(struct brcmf_sdio_dev *sdiodev, u32 corebase)
119{
120 u32 regdata;
121
122 regdata = brcmf_sdcard_reg_read(sdiodev,
123 CORE_SB(corebase, sbtmstatelow), 4);
124 if (regdata & SBTML_RESET)
125 return;
126
127 regdata = brcmf_sdcard_reg_read(sdiodev,
128 CORE_SB(corebase, sbtmstatelow), 4);
129 if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
130 /*
131 * set target reject and spin until busy is clear
132 * (preserve core-specific bits)
133 */
134 regdata = brcmf_sdcard_reg_read(sdiodev,
135 CORE_SB(corebase, sbtmstatelow), 4);
136 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
137 4, regdata | SBTML_REJ);
138
139 regdata = brcmf_sdcard_reg_read(sdiodev,
140 CORE_SB(corebase, sbtmstatelow), 4);
141 udelay(1);
142 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
143 CORE_SB(corebase, sbtmstatehigh), 4) &
144 SBTMH_BUSY), 100000);
145
146 regdata = brcmf_sdcard_reg_read(sdiodev,
147 CORE_SB(corebase, sbtmstatehigh), 4);
148 if (regdata & SBTMH_BUSY)
149 brcmf_dbg(ERROR, "core state still busy\n");
150
151 regdata = brcmf_sdcard_reg_read(sdiodev,
152 CORE_SB(corebase, sbidlow), 4);
153 if (regdata & SBIDL_INIT) {
154 regdata = brcmf_sdcard_reg_read(sdiodev,
155 CORE_SB(corebase, sbimstate), 4) |
156 SBIM_RJ;
157 brcmf_sdcard_reg_write(sdiodev,
158 CORE_SB(corebase, sbimstate), 4,
159 regdata);
160 regdata = brcmf_sdcard_reg_read(sdiodev,
161 CORE_SB(corebase, sbimstate), 4);
162 udelay(1);
163 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
164 CORE_SB(corebase, sbimstate), 4) &
165 SBIM_BY), 100000);
166 }
167
168 /* set reset and reject while enabling the clocks */
169 brcmf_sdcard_reg_write(sdiodev,
170 CORE_SB(corebase, sbtmstatelow), 4,
171 (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
172 SBTML_REJ | SBTML_RESET));
173 regdata = brcmf_sdcard_reg_read(sdiodev,
174 CORE_SB(corebase, sbtmstatelow), 4);
175 udelay(10);
176
177 /* clear the initiator reject bit */
178 regdata = brcmf_sdcard_reg_read(sdiodev,
179 CORE_SB(corebase, sbidlow), 4);
180 if (regdata & SBIDL_INIT) {
181 regdata = brcmf_sdcard_reg_read(sdiodev,
182 CORE_SB(corebase, sbimstate), 4) &
183 ~SBIM_RJ;
184 brcmf_sdcard_reg_write(sdiodev,
185 CORE_SB(corebase, sbimstate), 4,
186 regdata);
187 }
188 }
189
190 /* leave reset and reject asserted */
191 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
192 (SBTML_REJ | SBTML_RESET));
193 udelay(1);
194}
195
Franky Lin2bc78e12011-11-04 22:23:38 +0100196void
197brcmf_sdio_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
198{
199 u32 regdata;
200
201 /*
202 * Must do the disable sequence first to work for
203 * arbitrary current core state.
204 */
205 brcmf_sdio_chip_coredisable(sdiodev, corebase);
206
207 /*
208 * Now do the initialization sequence.
209 * set reset while enabling the clock and
210 * forcing them on throughout the core
211 */
212 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
213 ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
214 SBTML_RESET);
215 udelay(1);
216
217 regdata = brcmf_sdcard_reg_read(sdiodev,
218 CORE_SB(corebase, sbtmstatehigh), 4);
219 if (regdata & SBTMH_SERR)
220 brcmf_sdcard_reg_write(sdiodev,
221 CORE_SB(corebase, sbtmstatehigh), 4, 0);
222
223 regdata = brcmf_sdcard_reg_read(sdiodev,
224 CORE_SB(corebase, sbimstate), 4);
225 if (regdata & (SBIM_IBE | SBIM_TO))
226 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
227 regdata & ~(SBIM_IBE | SBIM_TO));
228
229 /* clear reset and allow it to propagate throughout the core */
230 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
231 (SICF_FGC << SBTML_SICF_SHIFT) |
232 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
233 udelay(1);
234
235 /* leave clock enabled */
236 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
237 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
238 udelay(1);
239}
240
Franky Lina83369b2011-11-04 22:23:28 +0100241static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
242 struct chip_info *ci, u32 regs)
243{
244 u32 regdata;
245
246 /*
247 * Get CC core rev
248 * Chipid is assume to be at offset 0 from regs arg
249 * For different chiptypes or old sdio hosts w/o chipcommon,
250 * other ways of recognition should be added here.
251 */
252 ci->cccorebase = regs;
253 regdata = brcmf_sdcard_reg_read(sdiodev,
254 CORE_CC_REG(ci->cccorebase, chipid), 4);
255 ci->chip = regdata & CID_ID_MASK;
256 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
257
258 brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
259
260 /* Address of cores for new chips should be added here */
261 switch (ci->chip) {
262 case BCM4329_CHIP_ID:
263 ci->buscorebase = BCM4329_CORE_BUS_BASE;
264 ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
265 ci->armcorebase = BCM4329_CORE_ARM_BASE;
266 ci->ramsize = BCM4329_RAMSIZE;
267 break;
268 default:
269 brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
270 return -ENODEV;
271 }
272
Franky Lina83369b2011-11-04 22:23:28 +0100273 return 0;
274}
275
Franky Line63ac6b2011-11-04 22:23:29 +0100276static int
277brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
278{
279 int err = 0;
280 u8 clkval, clkset;
281
282 /* Try forcing SDIO core to do ALPAvail request only */
283 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
284 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
285 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
286 if (err) {
287 brcmf_dbg(ERROR, "error writing for HT off\n");
288 return err;
289 }
290
291 /* If register supported, wait for ALPAvail and then force ALP */
292 /* This may take up to 15 milliseconds */
293 clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
294 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
295
296 if ((clkval & ~SBSDIO_AVBITS) != clkset) {
297 brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
298 clkset, clkval);
299 return -EACCES;
300 }
301
302 SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
303 SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
304 !SBSDIO_ALPAV(clkval)),
305 PMU_MAX_TRANSITION_DLY);
306 if (!SBSDIO_ALPAV(clkval)) {
307 brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
308 clkval);
309 return -EBUSY;
310 }
311
312 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
313 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
314 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
315 udelay(65);
316
317 /* Also, disable the extra SDIO pull-ups */
318 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
319 SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
320
321 return 0;
322}
323
Franky Lin5b45e542011-11-04 22:23:30 +0100324static void
325brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
326 struct chip_info *ci)
327{
328 u32 regdata;
329
330 /* get chipcommon rev */
Franky Lin454d2a82011-11-04 22:23:37 +0100331 ci->ccrev = brcmf_sdio_chip_corerev(sdiodev, ci->cccorebase);
Franky Lin5b45e542011-11-04 22:23:30 +0100332
333 /* get chipcommon capabilites */
334 ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
335 CORE_CC_REG(ci->cccorebase, capabilities), 4);
336
337 /* get pmu caps & rev */
338 if (ci->cccaps & CC_CAP_PMU) {
339 ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
340 CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
341 ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
342 }
343
Franky Lin454d2a82011-11-04 22:23:37 +0100344
345 ci->buscorerev = brcmf_sdio_chip_corerev(sdiodev, ci->buscorebase);
Franky Lin5b45e542011-11-04 22:23:30 +0100346 regdata = brcmf_sdcard_reg_read(sdiodev,
347 CORE_SB(ci->buscorebase, sbidhigh), 4);
Franky Lin5b45e542011-11-04 22:23:30 +0100348 ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
349
350 brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
351 ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
Franky Lin966414d2011-11-04 22:23:32 +0100352
353 /*
354 * Make sure any on-chip ARM is off (in case strapping is wrong),
355 * or downloaded code was already running.
356 */
357 brcmf_sdio_chip_coredisable(sdiodev, ci->armcorebase);
Franky Lin5b45e542011-11-04 22:23:30 +0100358}
359
Franky Lina83369b2011-11-04 22:23:28 +0100360int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
Franky Lina97e4fc2011-11-04 22:23:35 +0100361 struct chip_info **ci_ptr, u32 regs)
Franky Lina83369b2011-11-04 22:23:28 +0100362{
Franky Lina97e4fc2011-11-04 22:23:35 +0100363 int ret;
364 struct chip_info *ci;
365
366 brcmf_dbg(TRACE, "Enter\n");
367
368 /* alloc chip_info_t */
369 ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
370 if (!ci)
371 return -ENOMEM;
Franky Lina83369b2011-11-04 22:23:28 +0100372
Franky Line63ac6b2011-11-04 22:23:29 +0100373 ret = brcmf_sdio_chip_buscoreprep(sdiodev);
374 if (ret != 0)
Franky Lina97e4fc2011-11-04 22:23:35 +0100375 goto err;
Franky Line63ac6b2011-11-04 22:23:29 +0100376
Franky Lina83369b2011-11-04 22:23:28 +0100377 ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
378 if (ret != 0)
Franky Lina97e4fc2011-11-04 22:23:35 +0100379 goto err;
Franky Lina83369b2011-11-04 22:23:28 +0100380
Franky Lin5b45e542011-11-04 22:23:30 +0100381 brcmf_sdio_chip_buscoresetup(sdiodev, ci);
382
Franky Lin960908d2011-11-04 22:23:33 +0100383 brcmf_sdcard_reg_write(sdiodev,
384 CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
385 brcmf_sdcard_reg_write(sdiodev,
386 CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
387
Franky Lina97e4fc2011-11-04 22:23:35 +0100388 *ci_ptr = ci;
389 return 0;
390
391err:
392 kfree(ci);
Franky Lina83369b2011-11-04 22:23:28 +0100393 return ret;
394}
Franky Lina8a6c042011-11-04 22:23:39 +0100395
396void
397brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
398{
399 brcmf_dbg(TRACE, "Enter\n");
400
401 kfree(*ci_ptr);
402 *ci_ptr = NULL;
403}
Franky Line12afb62011-11-04 22:23:40 +0100404
405static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
406{
407 const char *fmt;
408
409 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
410 snprintf(buf, len, fmt, chipid);
411 return buf;
412}
413
414void
415brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
416 struct chip_info *ci, u32 drivestrength)
417{
418 struct sdiod_drive_str *str_tab = NULL;
419 u32 str_mask = 0;
420 u32 str_shift = 0;
421 char chn[8];
422
423 if (!(ci->cccaps & CC_CAP_PMU))
424 return;
425
426 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
427 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
428 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
429 str_mask = 0x30000000;
430 str_shift = 28;
431 break;
432 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
433 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
434 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
435 str_mask = 0x00003800;
436 str_shift = 11;
437 break;
438 case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
439 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
440 str_mask = 0x00003800;
441 str_shift = 11;
442 break;
443 default:
444 brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
445 brcmf_sdio_chip_name(ci->chip, chn, 8),
446 ci->chiprev, ci->pmurev);
447 break;
448 }
449
450 if (str_tab != NULL) {
451 u32 drivestrength_sel = 0;
452 u32 cc_data_temp;
453 int i;
454
455 for (i = 0; str_tab[i].strength != 0; i++) {
456 if (drivestrength >= str_tab[i].strength) {
457 drivestrength_sel = str_tab[i].sel;
458 break;
459 }
460 }
461
462 brcmf_sdcard_reg_write(sdiodev,
463 CORE_CC_REG(ci->cccorebase, chipcontrol_addr),
464 4, 1);
465 cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
466 CORE_CC_REG(ci->cccorebase, chipcontrol_addr), 4);
467 cc_data_temp &= ~str_mask;
468 drivestrength_sel <<= str_shift;
469 cc_data_temp |= drivestrength_sel;
470 brcmf_sdcard_reg_write(sdiodev,
471 CORE_CC_REG(ci->cccorebase, chipcontrol_addr),
472 4, cc_data_temp);
473
474 brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
475 drivestrength, cc_data_temp);
476 }
477}