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/ssb/ssb_regs.h>
22 #include <linux/bcma/bcma.h>
24 #include <chipcommon.h>
25 #include <brcm_hw_ids.h>
26 #include <brcmu_wifi.h>
27 #include <brcmu_utils.h>
30 #include "sdio_host.h"
31 #include "sdio_chip.h"
33 /* chip core base & ramsize */
35 /* SDIO device core, ID 0x829 */
36 #define BCM4329_CORE_BUS_BASE 0x18011000
37 /* internal memory core, ID 0x80e */
38 #define BCM4329_CORE_SOCRAM_BASE 0x18003000
39 /* ARM Cortex M3 core, ID 0x82a */
40 #define BCM4329_CORE_ARM_BASE 0x18002000
41 #define BCM4329_RAMSIZE 0x48000
43 #define SBCOREREV(sbidh) \
44 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
45 ((sbidh) & SSB_IDHIGH_RCLO))
47 /* SOC Interconnect types (aka chip types) */
52 #define CIB_REV_MASK 0xff000000
53 #define CIB_REV_SHIFT 24
55 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
56 /* SDIO Pad drive strength to select value mappings */
57 struct sdiod_drive_str
{
58 u8 strength
; /* Pad Drive Strength in mA */
59 u8 sel
; /* Chip-specific select value */
61 /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
62 static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8
[] = {
74 brcmf_sdio_chip_getinfidx(struct chip_info
*ci
, u16 coreid
)
78 for (idx
= 0; idx
< BRCMF_MAX_CORENUM
; idx
++)
79 if (coreid
== ci
->c_inf
[idx
].id
)
82 return BRCMF_MAX_CORENUM
;
86 brcmf_sdio_sb_corerev(struct brcmf_sdio_dev
*sdiodev
,
87 struct chip_info
*ci
, u16 coreid
)
92 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
94 regdata
= brcmf_sdcard_reg_read(sdiodev
,
95 CORE_SB(ci
->c_inf
[idx
].base
, sbidhigh
), 4);
96 return SBCOREREV(regdata
);
100 brcmf_sdio_ai_corerev(struct brcmf_sdio_dev
*sdiodev
,
101 struct chip_info
*ci
, u16 coreid
)
105 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
107 return (ci
->c_inf
[idx
].cib
& CIB_REV_MASK
) >> CIB_REV_SHIFT
;
111 brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
112 struct chip_info
*ci
, u16 coreid
)
117 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
119 regdata
= brcmf_sdcard_reg_read(sdiodev
,
120 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
121 regdata
&= (SSB_TMSLOW_RESET
| SSB_TMSLOW_REJECT
|
122 SSB_IMSTATE_REJECT
| SSB_TMSLOW_CLOCK
);
123 return (SSB_TMSLOW_CLOCK
== regdata
);
127 brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev
*sdiodev
,
128 struct chip_info
*ci
, u16 coreid
)
134 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
136 regdata
= brcmf_sdcard_reg_read(sdiodev
,
137 ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
, 4);
138 ret
= (regdata
& (BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
)) == BCMA_IOCTL_CLK
;
140 regdata
= brcmf_sdcard_reg_read(sdiodev
,
141 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
143 ret
= ret
&& ((regdata
& BCMA_RESET_CTL_RESET
) == 0);
149 brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev
*sdiodev
,
150 struct chip_info
*ci
, u16 coreid
)
155 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
157 regdata
= brcmf_sdcard_reg_read(sdiodev
,
158 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
159 if (regdata
& SSB_TMSLOW_RESET
)
162 regdata
= brcmf_sdcard_reg_read(sdiodev
,
163 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
164 if ((regdata
& SSB_TMSLOW_CLOCK
) != 0) {
166 * set target reject and spin until busy is clear
167 * (preserve core-specific bits)
169 regdata
= brcmf_sdcard_reg_read(sdiodev
,
170 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
171 brcmf_sdcard_reg_write(sdiodev
,
172 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
173 4, regdata
| SSB_TMSLOW_REJECT
);
175 regdata
= brcmf_sdcard_reg_read(sdiodev
,
176 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
178 SPINWAIT((brcmf_sdcard_reg_read(sdiodev
,
179 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
), 4) &
180 SSB_TMSHIGH_BUSY
), 100000);
182 regdata
= brcmf_sdcard_reg_read(sdiodev
,
183 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
), 4);
184 if (regdata
& SSB_TMSHIGH_BUSY
)
185 brcmf_dbg(ERROR
, "core state still busy\n");
187 regdata
= brcmf_sdcard_reg_read(sdiodev
,
188 CORE_SB(ci
->c_inf
[idx
].base
, sbidlow
), 4);
189 if (regdata
& SSB_IDLOW_INITIATOR
) {
190 regdata
= brcmf_sdcard_reg_read(sdiodev
,
191 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4) |
193 brcmf_sdcard_reg_write(sdiodev
,
194 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4,
196 regdata
= brcmf_sdcard_reg_read(sdiodev
,
197 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4);
199 SPINWAIT((brcmf_sdcard_reg_read(sdiodev
,
200 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4) &
201 SSB_IMSTATE_BUSY
), 100000);
204 /* set reset and reject while enabling the clocks */
205 brcmf_sdcard_reg_write(sdiodev
,
206 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4,
207 (SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
|
208 SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
));
209 regdata
= brcmf_sdcard_reg_read(sdiodev
,
210 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
213 /* clear the initiator reject bit */
214 regdata
= brcmf_sdcard_reg_read(sdiodev
,
215 CORE_SB(ci
->c_inf
[idx
].base
, sbidlow
), 4);
216 if (regdata
& SSB_IDLOW_INITIATOR
) {
217 regdata
= brcmf_sdcard_reg_read(sdiodev
,
218 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4) &
220 brcmf_sdcard_reg_write(sdiodev
,
221 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4,
226 /* leave reset and reject asserted */
227 brcmf_sdcard_reg_write(sdiodev
,
228 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4,
229 (SSB_TMSLOW_REJECT
| SSB_TMSLOW_RESET
));
234 brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev
*sdiodev
,
235 struct chip_info
*ci
, u16 coreid
)
240 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
242 /* if core is already in reset, just return */
243 regdata
= brcmf_sdcard_reg_read(sdiodev
,
244 ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
246 if ((regdata
& BCMA_RESET_CTL_RESET
) != 0)
249 brcmf_sdcard_reg_write(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
251 regdata
= brcmf_sdcard_reg_read(sdiodev
,
252 ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
, 4);
255 brcmf_sdcard_reg_write(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
256 4, BCMA_RESET_CTL_RESET
);
261 brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev
*sdiodev
,
262 struct chip_info
*ci
, u16 coreid
)
267 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
270 * Must do the disable sequence first to work for
271 * arbitrary current core state.
273 brcmf_sdio_sb_coredisable(sdiodev
, ci
, coreid
);
276 * Now do the initialization sequence.
277 * set reset while enabling the clock and
278 * forcing them on throughout the core
280 brcmf_sdcard_reg_write(sdiodev
,
281 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4,
282 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
| SSB_TMSLOW_RESET
);
283 regdata
= brcmf_sdcard_reg_read(sdiodev
,
284 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
287 /* clear any serror */
288 regdata
= brcmf_sdcard_reg_read(sdiodev
,
289 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
), 4);
290 if (regdata
& SSB_TMSHIGH_SERR
)
291 brcmf_sdcard_reg_write(sdiodev
,
292 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatehigh
), 4, 0);
294 regdata
= brcmf_sdcard_reg_read(sdiodev
,
295 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4);
296 if (regdata
& (SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
))
297 brcmf_sdcard_reg_write(sdiodev
,
298 CORE_SB(ci
->c_inf
[idx
].base
, sbimstate
), 4,
299 regdata
& ~(SSB_IMSTATE_IBE
| SSB_IMSTATE_TO
));
301 /* clear reset and allow it to propagate throughout the core */
302 brcmf_sdcard_reg_write(sdiodev
,
303 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4,
304 SSB_TMSLOW_FGC
| SSB_TMSLOW_CLOCK
);
305 regdata
= brcmf_sdcard_reg_read(sdiodev
,
306 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
309 /* leave clock enabled */
310 brcmf_sdcard_reg_write(sdiodev
,
311 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
),
312 4, SSB_TMSLOW_CLOCK
);
313 regdata
= brcmf_sdcard_reg_read(sdiodev
,
314 CORE_SB(ci
->c_inf
[idx
].base
, sbtmstatelow
), 4);
319 brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev
*sdiodev
,
320 struct chip_info
*ci
, u16 coreid
)
325 idx
= brcmf_sdio_chip_getinfidx(ci
, coreid
);
327 /* must disable first to work for arbitrary current core state */
328 brcmf_sdio_ai_coredisable(sdiodev
, ci
, coreid
);
330 /* now do initialization sequence */
331 brcmf_sdcard_reg_write(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
332 4, BCMA_IOCTL_FGC
| BCMA_IOCTL_CLK
);
333 regdata
= brcmf_sdcard_reg_read(sdiodev
,
334 ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
, 4);
335 brcmf_sdcard_reg_write(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_RESET_CTL
,
339 brcmf_sdcard_reg_write(sdiodev
, ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
,
341 regdata
= brcmf_sdcard_reg_read(sdiodev
,
342 ci
->c_inf
[idx
].wrapbase
+BCMA_IOCTL
, 4);
346 static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev
*sdiodev
,
347 struct chip_info
*ci
, u32 regs
)
353 * Chipid is assume to be at offset 0 from regs arg
354 * For different chiptypes or old sdio hosts w/o chipcommon,
355 * other ways of recognition should be added here.
357 ci
->c_inf
[0].id
= BCMA_CORE_CHIPCOMMON
;
358 ci
->c_inf
[0].base
= regs
;
359 regdata
= brcmf_sdcard_reg_read(sdiodev
,
360 CORE_CC_REG(ci
->c_inf
[0].base
, chipid
), 4);
361 ci
->chip
= regdata
& CID_ID_MASK
;
362 ci
->chiprev
= (regdata
& CID_REV_MASK
) >> CID_REV_SHIFT
;
363 ci
->socitype
= (regdata
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
365 brcmf_dbg(INFO
, "chipid=0x%x chiprev=%d\n", ci
->chip
, ci
->chiprev
);
367 /* Address of cores for new chips should be added here */
369 case BCM4329_CHIP_ID
:
370 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
371 ci
->c_inf
[1].base
= BCM4329_CORE_BUS_BASE
;
372 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
373 ci
->c_inf
[2].base
= BCM4329_CORE_SOCRAM_BASE
;
374 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
375 ci
->c_inf
[3].base
= BCM4329_CORE_ARM_BASE
;
376 ci
->ramsize
= BCM4329_RAMSIZE
;
378 case BCM4330_CHIP_ID
:
379 ci
->c_inf
[0].wrapbase
= 0x18100000;
380 ci
->c_inf
[0].cib
= 0x27004211;
381 ci
->c_inf
[1].id
= BCMA_CORE_SDIO_DEV
;
382 ci
->c_inf
[1].base
= 0x18002000;
383 ci
->c_inf
[1].wrapbase
= 0x18102000;
384 ci
->c_inf
[1].cib
= 0x07004211;
385 ci
->c_inf
[2].id
= BCMA_CORE_INTERNAL_MEM
;
386 ci
->c_inf
[2].base
= 0x18004000;
387 ci
->c_inf
[2].wrapbase
= 0x18104000;
388 ci
->c_inf
[2].cib
= 0x0d080401;
389 ci
->c_inf
[3].id
= BCMA_CORE_ARM_CM3
;
390 ci
->c_inf
[3].base
= 0x18003000;
391 ci
->c_inf
[3].wrapbase
= 0x18103000;
392 ci
->c_inf
[3].cib
= 0x03004211;
393 ci
->ramsize
= 0x48000;
396 brcmf_dbg(ERROR
, "chipid 0x%x is not supported\n", ci
->chip
);
400 switch (ci
->socitype
) {
402 ci
->iscoreup
= brcmf_sdio_sb_iscoreup
;
403 ci
->corerev
= brcmf_sdio_sb_corerev
;
404 ci
->coredisable
= brcmf_sdio_sb_coredisable
;
405 ci
->resetcore
= brcmf_sdio_sb_resetcore
;
408 ci
->iscoreup
= brcmf_sdio_ai_iscoreup
;
409 ci
->corerev
= brcmf_sdio_ai_corerev
;
410 ci
->coredisable
= brcmf_sdio_ai_coredisable
;
411 ci
->resetcore
= brcmf_sdio_ai_resetcore
;
414 brcmf_dbg(ERROR
, "socitype %u not supported\n", ci
->socitype
);
422 brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev
*sdiodev
)
427 /* Try forcing SDIO core to do ALPAvail request only */
428 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_ALP_AVAIL_REQ
;
429 brcmf_sdcard_cfg_write(sdiodev
, SDIO_FUNC_1
,
430 SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
432 brcmf_dbg(ERROR
, "error writing for HT off\n");
436 /* If register supported, wait for ALPAvail and then force ALP */
437 /* This may take up to 15 milliseconds */
438 clkval
= brcmf_sdcard_cfg_read(sdiodev
, SDIO_FUNC_1
,
439 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
);
441 if ((clkval
& ~SBSDIO_AVBITS
) != clkset
) {
442 brcmf_dbg(ERROR
, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
447 SPINWAIT(((clkval
= brcmf_sdcard_cfg_read(sdiodev
, SDIO_FUNC_1
,
448 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
)),
449 !SBSDIO_ALPAV(clkval
)),
450 PMU_MAX_TRANSITION_DLY
);
451 if (!SBSDIO_ALPAV(clkval
)) {
452 brcmf_dbg(ERROR
, "timeout on ALPAV wait, clkval 0x%02x\n",
457 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_FORCE_ALP
;
458 brcmf_sdcard_cfg_write(sdiodev
, SDIO_FUNC_1
,
459 SBSDIO_FUNC1_CHIPCLKCSR
, clkset
, &err
);
462 /* Also, disable the extra SDIO pull-ups */
463 brcmf_sdcard_cfg_write(sdiodev
, SDIO_FUNC_1
,
464 SBSDIO_FUNC1_SDIOPULLUP
, 0, NULL
);
470 brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev
*sdiodev
,
471 struct chip_info
*ci
)
473 /* get chipcommon rev */
474 ci
->c_inf
[0].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[0].id
);
476 /* get chipcommon capabilites */
478 brcmf_sdcard_reg_read(sdiodev
,
479 CORE_CC_REG(ci
->c_inf
[0].base
, capabilities
), 4);
481 /* get pmu caps & rev */
482 if (ci
->c_inf
[0].caps
& CC_CAP_PMU
) {
483 ci
->pmucaps
= brcmf_sdcard_reg_read(sdiodev
,
484 CORE_CC_REG(ci
->c_inf
[0].base
, pmucapabilities
), 4);
485 ci
->pmurev
= ci
->pmucaps
& PCAP_REV_MASK
;
488 ci
->c_inf
[1].rev
= ci
->corerev(sdiodev
, ci
, ci
->c_inf
[1].id
);
490 brcmf_dbg(INFO
, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
491 ci
->c_inf
[0].rev
, ci
->pmurev
,
492 ci
->c_inf
[1].rev
, ci
->c_inf
[1].id
);
495 * Make sure any on-chip ARM is off (in case strapping is wrong),
496 * or downloaded code was already running.
498 ci
->coredisable(sdiodev
, ci
, BCMA_CORE_ARM_CM3
);
501 int brcmf_sdio_chip_attach(struct brcmf_sdio_dev
*sdiodev
,
502 struct chip_info
**ci_ptr
, u32 regs
)
505 struct chip_info
*ci
;
507 brcmf_dbg(TRACE
, "Enter\n");
509 /* alloc chip_info_t */
510 ci
= kzalloc(sizeof(struct chip_info
), GFP_ATOMIC
);
514 ret
= brcmf_sdio_chip_buscoreprep(sdiodev
);
518 ret
= brcmf_sdio_chip_recognition(sdiodev
, ci
, regs
);
522 brcmf_sdio_chip_buscoresetup(sdiodev
, ci
);
524 brcmf_sdcard_reg_write(sdiodev
,
525 CORE_CC_REG(ci
->c_inf
[0].base
, gpiopullup
), 4, 0);
526 brcmf_sdcard_reg_write(sdiodev
,
527 CORE_CC_REG(ci
->c_inf
[0].base
, gpiopulldown
), 4, 0);
538 brcmf_sdio_chip_detach(struct chip_info
**ci_ptr
)
540 brcmf_dbg(TRACE
, "Enter\n");
546 static char *brcmf_sdio_chip_name(uint chipid
, char *buf
, uint len
)
550 fmt
= ((chipid
> 0xa000) || (chipid
< 0x4000)) ? "%d" : "%x";
551 snprintf(buf
, len
, fmt
, chipid
);
556 brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev
*sdiodev
,
557 struct chip_info
*ci
, u32 drivestrength
)
559 struct sdiod_drive_str
*str_tab
= NULL
;
564 if (!(ci
->c_inf
[0].caps
& CC_CAP_PMU
))
567 switch (SDIOD_DRVSTR_KEY(ci
->chip
, ci
->pmurev
)) {
568 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID
, 12):
569 str_tab
= (struct sdiod_drive_str
*)&sdiod_drvstr_tab1_1v8
;
570 str_mask
= 0x00003800;
574 brcmf_dbg(ERROR
, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
575 brcmf_sdio_chip_name(ci
->chip
, chn
, 8),
576 ci
->chiprev
, ci
->pmurev
);
580 if (str_tab
!= NULL
) {
581 u32 drivestrength_sel
= 0;
585 for (i
= 0; str_tab
[i
].strength
!= 0; i
++) {
586 if (drivestrength
>= str_tab
[i
].strength
) {
587 drivestrength_sel
= str_tab
[i
].sel
;
592 brcmf_sdcard_reg_write(sdiodev
,
593 CORE_CC_REG(ci
->c_inf
[0].base
, chipcontrol_addr
),
595 cc_data_temp
= brcmf_sdcard_reg_read(sdiodev
,
596 CORE_CC_REG(ci
->c_inf
[0].base
, chipcontrol_addr
), 4);
597 cc_data_temp
&= ~str_mask
;
598 drivestrength_sel
<<= str_shift
;
599 cc_data_temp
|= drivestrength_sel
;
600 brcmf_sdcard_reg_write(sdiodev
,
601 CORE_CC_REG(ci
->c_inf
[0].base
, chipcontrol_addr
),
604 brcmf_dbg(INFO
, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
605 drivestrength
, cc_data_temp
);