sdio_chip.c 14.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Copyright (c) 2011 Broadcom Corporation
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/* ***** SDIO interface chip backplane handle functions ***** */

#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/mmc/card.h>
21
#include <linux/ssb/ssb_regs.h>
22
#include <linux/bcma/bcma.h>
23

24 25 26 27
#include <chipcommon.h>
#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
28
#include <soc.h>
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#include "dhd.h"
#include "dhd_dbg.h"
#include "sdio_host.h"
#include "sdio_chip.h"

/* chip core base & ramsize */
/* bcm4329 */
/* SDIO device core, ID 0x829 */
#define BCM4329_CORE_BUS_BASE		0x18011000
/* internal memory core, ID 0x80e */
#define BCM4329_CORE_SOCRAM_BASE	0x18003000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE		0x18002000
#define BCM4329_RAMSIZE			0x48000

#define	SBCOREREV(sbidh) \
45 46
	((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
	  ((sbidh) & SSB_IDHIGH_RCLO))
47

48 49 50 51
/* SOC Interconnect types (aka chip types) */
#define SOCI_SB		0
#define SOCI_AI		1

52 53 54 55
/* EROM CompIdentB */
#define CIB_REV_MASK		0xff000000
#define CIB_REV_SHIFT		24

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
	u8 strength;	/* Pad Drive Strength in mA */
	u8 sel;		/* Chip-specific select value */
};
/* SDIO Drive Strength to sel value table for PMU Rev 1 */
static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
	{
	4, 0x2}, {
	2, 0x3}, {
	1, 0x0}, {
	0, 0x0}
	};
/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
	{
	12, 0x7}, {
	10, 0x6}, {
	8, 0x5}, {
	6, 0x4}, {
	4, 0x2}, {
	2, 0x1}, {
	0, 0x0}
	};
/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
	{
	32, 0x7}, {
	26, 0x6}, {
	22, 0x5}, {
	16, 0x4}, {
	12, 0x3}, {
	8, 0x2}, {
	4, 0x1}, {
	0, 0x0}
	};

94 95 96 97 98 99 100 101 102 103 104 105
u8
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
{
	u8 idx;

	for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
		if (coreid == ci->c_inf[idx].id)
			return idx;

	return BRCMF_MAX_CORENUM;
}

106
static u32
107 108
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
		      struct chip_info *ci, u16 coreid)
109 110
{
	u32 regdata;
111 112 113
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
114 115

	regdata = brcmf_sdcard_reg_read(sdiodev,
116
			CORE_SB(ci->c_inf[idx].base, sbidhigh), 4);
117 118 119
	return SBCOREREV(regdata);
}

120 121 122 123 124 125 126 127 128 129 130
static u32
brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
		      struct chip_info *ci, u16 coreid)
{
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

	return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
}

131 132 133
static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
		       struct chip_info *ci, u16 coreid)
134 135
{
	u32 regdata;
136 137 138
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
139 140

	regdata = brcmf_sdcard_reg_read(sdiodev,
141
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
142 143 144
	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
	return (SSB_TMSLOW_CLOCK == regdata);
145 146
}

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
static bool
brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
		       struct chip_info *ci, u16 coreid)
{
	u32 regdata;
	u8 idx;
	bool ret;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
	ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;

	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
					4);
	ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);

	return ret;
}

169 170 171 172 173 174 175
void
brcmf_sdio_chip_coredisable(struct brcmf_sdio_dev *sdiodev, u32 corebase)
{
	u32 regdata;

	regdata = brcmf_sdcard_reg_read(sdiodev,
		CORE_SB(corebase, sbtmstatelow), 4);
176
	if (regdata & SSB_TMSLOW_RESET)
177 178 179 180
		return;

	regdata = brcmf_sdcard_reg_read(sdiodev,
		CORE_SB(corebase, sbtmstatelow), 4);
181
	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
182 183 184 185 186 187 188
		/*
		 * set target reject and spin until busy is clear
		 * (preserve core-specific bits)
		 */
		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4);
		brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
189
				       4, regdata | SSB_TMSLOW_REJECT);
190 191 192 193 194 195

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4);
		udelay(1);
		SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatehigh), 4) &
196
			SSB_TMSHIGH_BUSY), 100000);
197 198 199

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatehigh), 4);
200
		if (regdata & SSB_TMSHIGH_BUSY)
201 202 203 204
			brcmf_dbg(ERROR, "core state still busy\n");

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbidlow), 4);
205
		if (regdata & SSB_IDLOW_INITIATOR) {
206 207
			regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4) |
208
				SSB_IMSTATE_REJECT;
209 210 211 212 213 214 215 216
			brcmf_sdcard_reg_write(sdiodev,
				CORE_SB(corebase, sbimstate), 4,
				regdata);
			regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4);
			udelay(1);
			SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4) &
217
				SSB_IMSTATE_BUSY), 100000);
218 219 220 221 222
		}

		/* set reset and reject while enabling the clocks */
		brcmf_sdcard_reg_write(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4,
223 224
			(SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
			SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
225 226 227 228 229 230 231
		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4);
		udelay(10);

		/* clear the initiator reject bit */
		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbidlow), 4);
232
		if (regdata & SSB_IDLOW_INITIATOR) {
233 234
			regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4) &
235
				~SSB_IMSTATE_REJECT;
236 237 238 239 240 241 242 243
			brcmf_sdcard_reg_write(sdiodev,
				CORE_SB(corebase, sbimstate), 4,
				regdata);
		}
	}

	/* leave reset and reject asserted */
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
244
		(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
245 246 247
	udelay(1);
}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
void
brcmf_sdio_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
{
	u32 regdata;

	/*
	 * Must do the disable sequence first to work for
	 * arbitrary current core state.
	 */
	brcmf_sdio_chip_coredisable(sdiodev, corebase);

	/*
	 * Now do the initialization sequence.
	 * set reset while enabling the clock and
	 * forcing them on throughout the core
	 */
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
265
		SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
266 267 268 269
	udelay(1);

	regdata = brcmf_sdcard_reg_read(sdiodev,
					CORE_SB(corebase, sbtmstatehigh), 4);
270
	if (regdata & SSB_TMSHIGH_SERR)
271 272 273 274 275
		brcmf_sdcard_reg_write(sdiodev,
				       CORE_SB(corebase, sbtmstatehigh), 4, 0);

	regdata = brcmf_sdcard_reg_read(sdiodev,
					CORE_SB(corebase, sbimstate), 4);
276
	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
277
		brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
278
			regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
279 280 281

	/* clear reset and allow it to propagate throughout the core */
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
282
		SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
283 284 285
	udelay(1);

	/* leave clock enabled */
286 287
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
			       4, SSB_TMSLOW_CLOCK);
288 289 290
	udelay(1);
}

291 292 293 294 295 296 297 298 299 300 301
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
				       struct chip_info *ci, u32 regs)
{
	u32 regdata;

	/*
	 * Get CC core rev
	 * Chipid is assume to be at offset 0 from regs arg
	 * For different chiptypes or old sdio hosts w/o chipcommon,
	 * other ways of recognition should be added here.
	 */
302 303
	ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
	ci->c_inf[0].base = regs;
304
	regdata = brcmf_sdcard_reg_read(sdiodev,
305
			CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
306 307
	ci->chip = regdata & CID_ID_MASK;
	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
308
	ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
309 310 311 312 313 314

	brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);

	/* Address of cores for new chips should be added here */
	switch (ci->chip) {
	case BCM4329_CHIP_ID:
315 316 317 318 319 320
		ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
		ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
		ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
		ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
		ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
		ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
321 322 323 324 325 326 327
		ci->ramsize = BCM4329_RAMSIZE;
		break;
	default:
		brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
		return -ENODEV;
	}

328 329 330
	switch (ci->socitype) {
	case SOCI_SB:
		ci->iscoreup = brcmf_sdio_sb_iscoreup;
331
		ci->corerev = brcmf_sdio_sb_corerev;
332 333 334
		break;
	case SOCI_AI:
		ci->iscoreup = brcmf_sdio_ai_iscoreup;
335
		ci->corerev = brcmf_sdio_ai_corerev;
336 337 338 339 340 341
		break;
	default:
		brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype);
		return -ENODEV;
	}

342 343 344
	return 0;
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
static int
brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
{
	int err = 0;
	u8 clkval, clkset;

	/* Try forcing SDIO core to do ALPAvail request only */
	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_CHIPCLKCSR,	clkset, &err);
	if (err) {
		brcmf_dbg(ERROR, "error writing for HT off\n");
		return err;
	}

	/* If register supported, wait for ALPAvail and then force ALP */
	/* This may take up to 15 milliseconds */
	clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
				       SBSDIO_FUNC1_CHIPCLKCSR, NULL);

	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
		brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
			  clkset, clkval);
		return -EACCES;
	}

	SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
				SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
			!SBSDIO_ALPAV(clkval)),
			PMU_MAX_TRANSITION_DLY);
	if (!SBSDIO_ALPAV(clkval)) {
		brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
			  clkval);
		return -EBUSY;
	}

	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
	udelay(65);

	/* Also, disable the extra SDIO pull-ups */
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);

	return 0;
}

393 394 395 396 397
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
			     struct chip_info *ci)
{
	u32 regdata;
398
	u8 idx;
399 400

	/* get chipcommon rev */
401
	ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
402 403

	/* get chipcommon capabilites */
404 405 406
	ci->c_inf[0].caps =
		brcmf_sdcard_reg_read(sdiodev,
		CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
407 408

	/* get pmu caps & rev */
409
	if (ci->c_inf[0].caps & CC_CAP_PMU) {
410
		ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
411
			CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
412 413 414
		ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
	}

415
	ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
416
	regdata = brcmf_sdcard_reg_read(sdiodev,
417 418
				CORE_SB(ci->c_inf[1].base, sbidhigh), 4);
	ci->c_inf[1].id = (regdata & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
419 420

	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
421 422
		  ci->c_inf[0].rev, ci->pmurev,
		  ci->c_inf[1].rev, ci->c_inf[1].id);
423 424 425 426 427

	/*
	 * Make sure any on-chip ARM is off (in case strapping is wrong),
	 * or downloaded code was already running.
	 */
428 429
	idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
	brcmf_sdio_chip_coredisable(sdiodev, ci->c_inf[idx].base);
430 431
}

432
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
433
			   struct chip_info **ci_ptr, u32 regs)
434
{
435 436 437 438 439 440 441 442 443
	int ret;
	struct chip_info *ci;

	brcmf_dbg(TRACE, "Enter\n");

	/* alloc chip_info_t */
	ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
	if (!ci)
		return -ENOMEM;
444

445 446
	ret = brcmf_sdio_chip_buscoreprep(sdiodev);
	if (ret != 0)
447
		goto err;
448

449 450
	ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
	if (ret != 0)
451
		goto err;
452

453 454
	brcmf_sdio_chip_buscoresetup(sdiodev, ci);

455
	brcmf_sdcard_reg_write(sdiodev,
456
		CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
457
	brcmf_sdcard_reg_write(sdiodev,
458
		CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
459

460 461 462 463 464
	*ci_ptr = ci;
	return 0;

err:
	kfree(ci);
465 466
	return ret;
}
467 468 469 470 471 472 473 474 475

void
brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
{
	brcmf_dbg(TRACE, "Enter\n");

	kfree(*ci_ptr);
	*ci_ptr = NULL;
}
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494

static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
{
	const char *fmt;

	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
	snprintf(buf, len, fmt, chipid);
	return buf;
}

void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
				  struct chip_info *ci, u32 drivestrength)
{
	struct sdiod_drive_str *str_tab = NULL;
	u32 str_mask = 0;
	u32 str_shift = 0;
	char chn[8];

495
	if (!(ci->c_inf[0].caps & CC_CAP_PMU))
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
		return;

	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
		str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
		str_mask = 0x30000000;
		str_shift = 28;
		break;
	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
		str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
		str_mask = 0x00003800;
		str_shift = 11;
		break;
	case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
		str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
		str_mask = 0x00003800;
		str_shift = 11;
		break;
	default:
		brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
			  brcmf_sdio_chip_name(ci->chip, chn, 8),
			  ci->chiprev, ci->pmurev);
		break;
	}

	if (str_tab != NULL) {
		u32 drivestrength_sel = 0;
		u32 cc_data_temp;
		int i;

		for (i = 0; str_tab[i].strength != 0; i++) {
			if (drivestrength >= str_tab[i].strength) {
				drivestrength_sel = str_tab[i].sel;
				break;
			}
		}

		brcmf_sdcard_reg_write(sdiodev,
535
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
536 537
			4, 1);
		cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
538
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
539 540 541 542
		cc_data_temp &= ~str_mask;
		drivestrength_sel <<= str_shift;
		cc_data_temp |= drivestrength_sel;
		brcmf_sdcard_reg_write(sdiodev,
543
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
544 545 546 547 548 549
			4, cc_data_temp);

		brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
			  drivestrength, cc_data_temp);
	}
}