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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20 #include <linux/types.h>
21 #include <linux/netdevice.h>
22 #include <linux/mmc/card.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 #define SBCOREREV(sbidh) \
46 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
47 ((sbidh) & SSB_IDHIGH_RCLO))
48
49 /* SOC Interconnect types (aka chip types) */
50 #define SOCI_SB 0
51 #define SOCI_AI 1
52
53 /* EROM CompIdentB */
54 #define CIB_REV_MASK 0xff000000
55 #define CIB_REV_SHIFT 24
56
57 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
58 /* SDIO Pad drive strength to select value mappings */
59 struct sdiod_drive_str {
60 u8 strength; /* Pad Drive Strength in mA */
61 u8 sel; /* Chip-specific select value */
62 };
63 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
64 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
65 {32, 0x6},
66 {26, 0x7},
67 {22, 0x4},
68 {16, 0x5},
69 {12, 0x2},
70 {8, 0x3},
71 {4, 0x0},
72 {0, 0x1}
73 };
74
75 u8
brcmf_sdio_chip_getinfidx(struct chip_info * ci,u16 coreid)76 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
77 {
78 u8 idx;
79
80 for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
81 if (coreid == ci->c_inf[idx].id)
82 return idx;
83
84 return BRCMF_MAX_CORENUM;
85 }
86
87 static u32
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)88 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
89 struct chip_info *ci, u16 coreid)
90 {
91 u32 regdata;
92 u8 idx;
93
94 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
95
96 regdata = brcmf_sdcard_reg_read(sdiodev,
97 CORE_SB(ci->c_inf[idx].base, sbidhigh), 4);
98 return SBCOREREV(regdata);
99 }
100
101 static u32
brcmf_sdio_ai_corerev(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)102 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
103 struct chip_info *ci, u16 coreid)
104 {
105 u8 idx;
106
107 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
108
109 return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
110 }
111
112 static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)113 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
114 struct chip_info *ci, u16 coreid)
115 {
116 u32 regdata;
117 u8 idx;
118
119 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
120
121 regdata = brcmf_sdcard_reg_read(sdiodev,
122 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
123 regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
124 SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
125 return (SSB_TMSLOW_CLOCK == regdata);
126 }
127
128 static bool
brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)129 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
130 struct chip_info *ci, u16 coreid)
131 {
132 u32 regdata;
133 u8 idx;
134 bool ret;
135
136 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
137
138 regdata = brcmf_sdcard_reg_read(sdiodev,
139 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
140 ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
141
142 regdata = brcmf_sdcard_reg_read(sdiodev,
143 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
144 4);
145 ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
146
147 return ret;
148 }
149
150 static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)151 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
152 struct chip_info *ci, u16 coreid)
153 {
154 u32 regdata;
155 u8 idx;
156
157 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
158
159 regdata = brcmf_sdcard_reg_read(sdiodev,
160 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
161 if (regdata & SSB_TMSLOW_RESET)
162 return;
163
164 regdata = brcmf_sdcard_reg_read(sdiodev,
165 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
166 if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
167 /*
168 * set target reject and spin until busy is clear
169 * (preserve core-specific bits)
170 */
171 regdata = brcmf_sdcard_reg_read(sdiodev,
172 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
173 brcmf_sdcard_reg_write(sdiodev,
174 CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
175 4, regdata | SSB_TMSLOW_REJECT);
176
177 regdata = brcmf_sdcard_reg_read(sdiodev,
178 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
179 udelay(1);
180 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
181 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) &
182 SSB_TMSHIGH_BUSY), 100000);
183
184 regdata = brcmf_sdcard_reg_read(sdiodev,
185 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
186 if (regdata & SSB_TMSHIGH_BUSY)
187 brcmf_dbg(ERROR, "core state still busy\n");
188
189 regdata = brcmf_sdcard_reg_read(sdiodev,
190 CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
191 if (regdata & SSB_IDLOW_INITIATOR) {
192 regdata = brcmf_sdcard_reg_read(sdiodev,
193 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) |
194 SSB_IMSTATE_REJECT;
195 brcmf_sdcard_reg_write(sdiodev,
196 CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
197 regdata);
198 regdata = brcmf_sdcard_reg_read(sdiodev,
199 CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
200 udelay(1);
201 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
202 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
203 SSB_IMSTATE_BUSY), 100000);
204 }
205
206 /* set reset and reject while enabling the clocks */
207 brcmf_sdcard_reg_write(sdiodev,
208 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
209 (SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
210 SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
211 regdata = brcmf_sdcard_reg_read(sdiodev,
212 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
213 udelay(10);
214
215 /* clear the initiator reject bit */
216 regdata = brcmf_sdcard_reg_read(sdiodev,
217 CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
218 if (regdata & SSB_IDLOW_INITIATOR) {
219 regdata = brcmf_sdcard_reg_read(sdiodev,
220 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
221 ~SSB_IMSTATE_REJECT;
222 brcmf_sdcard_reg_write(sdiodev,
223 CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
224 regdata);
225 }
226 }
227
228 /* leave reset and reject asserted */
229 brcmf_sdcard_reg_write(sdiodev,
230 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
231 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
232 udelay(1);
233 }
234
235 static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)236 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
237 struct chip_info *ci, u16 coreid)
238 {
239 u8 idx;
240 u32 regdata;
241
242 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
243
244 /* if core is already in reset, just return */
245 regdata = brcmf_sdcard_reg_read(sdiodev,
246 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
247 4);
248 if ((regdata & BCMA_RESET_CTL_RESET) != 0)
249 return;
250
251 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
252 4, 0);
253 regdata = brcmf_sdcard_reg_read(sdiodev,
254 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
255 udelay(10);
256
257 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
258 4, BCMA_RESET_CTL_RESET);
259 udelay(1);
260 }
261
262 static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)263 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
264 struct chip_info *ci, u16 coreid)
265 {
266 u32 regdata;
267 u8 idx;
268
269 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
270
271 /*
272 * Must do the disable sequence first to work for
273 * arbitrary current core state.
274 */
275 brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
276
277 /*
278 * Now do the initialization sequence.
279 * set reset while enabling the clock and
280 * forcing them on throughout the core
281 */
282 brcmf_sdcard_reg_write(sdiodev,
283 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
284 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
285 regdata = brcmf_sdcard_reg_read(sdiodev,
286 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
287 udelay(1);
288
289 /* clear any serror */
290 regdata = brcmf_sdcard_reg_read(sdiodev,
291 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
292 if (regdata & SSB_TMSHIGH_SERR)
293 brcmf_sdcard_reg_write(sdiodev,
294 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0);
295
296 regdata = brcmf_sdcard_reg_read(sdiodev,
297 CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
298 if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
299 brcmf_sdcard_reg_write(sdiodev,
300 CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
301 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
302
303 /* clear reset and allow it to propagate throughout the core */
304 brcmf_sdcard_reg_write(sdiodev,
305 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
306 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
307 regdata = brcmf_sdcard_reg_read(sdiodev,
308 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
309 udelay(1);
310
311 /* leave clock enabled */
312 brcmf_sdcard_reg_write(sdiodev,
313 CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
314 4, SSB_TMSLOW_CLOCK);
315 regdata = brcmf_sdcard_reg_read(sdiodev,
316 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
317 udelay(1);
318 }
319
320 static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u16 coreid)321 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
322 struct chip_info *ci, u16 coreid)
323 {
324 u8 idx;
325 u32 regdata;
326
327 idx = brcmf_sdio_chip_getinfidx(ci, coreid);
328
329 /* must disable first to work for arbitrary current core state */
330 brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
331
332 /* now do initialization sequence */
333 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
334 4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
335 regdata = brcmf_sdcard_reg_read(sdiodev,
336 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
337 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
338 4, 0);
339 udelay(1);
340
341 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
342 4, BCMA_IOCTL_CLK);
343 regdata = brcmf_sdcard_reg_read(sdiodev,
344 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
345 udelay(1);
346 }
347
brcmf_sdio_chip_recognition(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u32 regs)348 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
349 struct chip_info *ci, u32 regs)
350 {
351 u32 regdata;
352
353 /*
354 * Get CC core rev
355 * Chipid is assume to be at offset 0 from regs arg
356 * For different chiptypes or old sdio hosts w/o chipcommon,
357 * other ways of recognition should be added here.
358 */
359 ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
360 ci->c_inf[0].base = regs;
361 regdata = brcmf_sdcard_reg_read(sdiodev,
362 CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
363 ci->chip = regdata & CID_ID_MASK;
364 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
365 ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
366
367 brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
368
369 /* Address of cores for new chips should be added here */
370 switch (ci->chip) {
371 case BCM4329_CHIP_ID:
372 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
373 ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
374 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
375 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
376 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
377 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
378 ci->ramsize = BCM4329_RAMSIZE;
379 break;
380 case BCM4330_CHIP_ID:
381 ci->c_inf[0].wrapbase = 0x18100000;
382 ci->c_inf[0].cib = 0x27004211;
383 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
384 ci->c_inf[1].base = 0x18002000;
385 ci->c_inf[1].wrapbase = 0x18102000;
386 ci->c_inf[1].cib = 0x07004211;
387 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
388 ci->c_inf[2].base = 0x18004000;
389 ci->c_inf[2].wrapbase = 0x18104000;
390 ci->c_inf[2].cib = 0x0d080401;
391 ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
392 ci->c_inf[3].base = 0x18003000;
393 ci->c_inf[3].wrapbase = 0x18103000;
394 ci->c_inf[3].cib = 0x03004211;
395 ci->ramsize = 0x48000;
396 break;
397 default:
398 brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
399 return -ENODEV;
400 }
401
402 switch (ci->socitype) {
403 case SOCI_SB:
404 ci->iscoreup = brcmf_sdio_sb_iscoreup;
405 ci->corerev = brcmf_sdio_sb_corerev;
406 ci->coredisable = brcmf_sdio_sb_coredisable;
407 ci->resetcore = brcmf_sdio_sb_resetcore;
408 break;
409 case SOCI_AI:
410 ci->iscoreup = brcmf_sdio_ai_iscoreup;
411 ci->corerev = brcmf_sdio_ai_corerev;
412 ci->coredisable = brcmf_sdio_ai_coredisable;
413 ci->resetcore = brcmf_sdio_ai_resetcore;
414 break;
415 default:
416 brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype);
417 return -ENODEV;
418 }
419
420 return 0;
421 }
422
423 static int
brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev * sdiodev)424 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
425 {
426 int err = 0;
427 u8 clkval, clkset;
428
429 /* Try forcing SDIO core to do ALPAvail request only */
430 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
431 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
432 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
433 if (err) {
434 brcmf_dbg(ERROR, "error writing for HT off\n");
435 return err;
436 }
437
438 /* If register supported, wait for ALPAvail and then force ALP */
439 /* This may take up to 15 milliseconds */
440 clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
441 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
442
443 if ((clkval & ~SBSDIO_AVBITS) != clkset) {
444 brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
445 clkset, clkval);
446 return -EACCES;
447 }
448
449 SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
450 SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
451 !SBSDIO_ALPAV(clkval)),
452 PMU_MAX_TRANSITION_DLY);
453 if (!SBSDIO_ALPAV(clkval)) {
454 brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
455 clkval);
456 return -EBUSY;
457 }
458
459 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
460 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
461 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
462 udelay(65);
463
464 /* Also, disable the extra SDIO pull-ups */
465 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
466 SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
467
468 return 0;
469 }
470
471 static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci)472 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
473 struct chip_info *ci)
474 {
475 /* get chipcommon rev */
476 ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
477
478 /* get chipcommon capabilites */
479 ci->c_inf[0].caps =
480 brcmf_sdcard_reg_read(sdiodev,
481 CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
482
483 /* get pmu caps & rev */
484 if (ci->c_inf[0].caps & CC_CAP_PMU) {
485 ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
486 CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
487 ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
488 }
489
490 ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
491
492 brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
493 ci->c_inf[0].rev, ci->pmurev,
494 ci->c_inf[1].rev, ci->c_inf[1].id);
495
496 /*
497 * Make sure any on-chip ARM is off (in case strapping is wrong),
498 * or downloaded code was already running.
499 */
500 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
501 }
502
brcmf_sdio_chip_attach(struct brcmf_sdio_dev * sdiodev,struct chip_info ** ci_ptr,u32 regs)503 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
504 struct chip_info **ci_ptr, u32 regs)
505 {
506 int ret;
507 struct chip_info *ci;
508
509 brcmf_dbg(TRACE, "Enter\n");
510
511 /* alloc chip_info_t */
512 ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
513 if (!ci)
514 return -ENOMEM;
515
516 ret = brcmf_sdio_chip_buscoreprep(sdiodev);
517 if (ret != 0)
518 goto err;
519
520 ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
521 if (ret != 0)
522 goto err;
523
524 brcmf_sdio_chip_buscoresetup(sdiodev, ci);
525
526 brcmf_sdcard_reg_write(sdiodev,
527 CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
528 brcmf_sdcard_reg_write(sdiodev,
529 CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
530
531 *ci_ptr = ci;
532 return 0;
533
534 err:
535 kfree(ci);
536 return ret;
537 }
538
539 void
brcmf_sdio_chip_detach(struct chip_info ** ci_ptr)540 brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
541 {
542 brcmf_dbg(TRACE, "Enter\n");
543
544 kfree(*ci_ptr);
545 *ci_ptr = NULL;
546 }
547
brcmf_sdio_chip_name(uint chipid,char * buf,uint len)548 static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
549 {
550 const char *fmt;
551
552 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
553 snprintf(buf, len, fmt, chipid);
554 return buf;
555 }
556
557 void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev * sdiodev,struct chip_info * ci,u32 drivestrength)558 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
559 struct chip_info *ci, u32 drivestrength)
560 {
561 struct sdiod_drive_str *str_tab = NULL;
562 u32 str_mask = 0;
563 u32 str_shift = 0;
564 char chn[8];
565
566 if (!(ci->c_inf[0].caps & CC_CAP_PMU))
567 return;
568
569 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
570 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
571 str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
572 str_mask = 0x00003800;
573 str_shift = 11;
574 break;
575 default:
576 brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
577 brcmf_sdio_chip_name(ci->chip, chn, 8),
578 ci->chiprev, ci->pmurev);
579 break;
580 }
581
582 if (str_tab != NULL) {
583 u32 drivestrength_sel = 0;
584 u32 cc_data_temp;
585 int i;
586
587 for (i = 0; str_tab[i].strength != 0; i++) {
588 if (drivestrength >= str_tab[i].strength) {
589 drivestrength_sel = str_tab[i].sel;
590 break;
591 }
592 }
593
594 brcmf_sdcard_reg_write(sdiodev,
595 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
596 4, 1);
597 cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
598 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
599 cc_data_temp &= ~str_mask;
600 drivestrength_sel <<= str_shift;
601 cc_data_temp |= drivestrength_sel;
602 brcmf_sdcard_reg_write(sdiodev,
603 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
604 4, cc_data_temp);
605
606 brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
607 drivestrength, cc_data_temp);
608 }
609 }
610