sdio_chip.c 17.7 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}
	};

F
Franky Lin 已提交
94 95 96 97 98 99 100 101 102 103 104 105
/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
static const struct sdiod_drive_str sdiod_drvstr_tab4_1v8[] = {
	{32, 0x6},
	{26, 0x7},
	{22, 0x4},
	{16, 0x5},
	{12, 0x2},
	{8, 0x3},
	{4, 0x0},
	{0, 0x1}
};

106 107 108 109 110 111 112 113 114 115 116 117
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;
}

118
static u32
119 120
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
		      struct chip_info *ci, u16 coreid)
121 122
{
	u32 regdata;
123 124 125
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
126 127

	regdata = brcmf_sdcard_reg_read(sdiodev,
128
			CORE_SB(ci->c_inf[idx].base, sbidhigh), 4);
129 130 131
	return SBCOREREV(regdata);
}

132 133 134 135 136 137 138 139 140 141 142
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;
}

143 144 145
static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
		       struct chip_info *ci, u16 coreid)
146 147
{
	u32 regdata;
148 149 150
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
151 152

	regdata = brcmf_sdcard_reg_read(sdiodev,
153
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
154 155 156
	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
	return (SSB_TMSLOW_CLOCK == regdata);
157 158
}

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
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;
}

181 182 183
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
			  struct chip_info *ci, u16 coreid)
184 185
{
	u32 regdata;
186 187 188
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
189 190

	regdata = brcmf_sdcard_reg_read(sdiodev,
191
		CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
192
	if (regdata & SSB_TMSLOW_RESET)
193 194 195
		return;

	regdata = brcmf_sdcard_reg_read(sdiodev,
196
		CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
197
	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
198 199 200 201 202
		/*
		 * set target reject and spin until busy is clear
		 * (preserve core-specific bits)
		 */
		regdata = brcmf_sdcard_reg_read(sdiodev,
203 204 205 206
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
		brcmf_sdcard_reg_write(sdiodev,
				CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
				4, regdata | SSB_TMSLOW_REJECT);
207 208

		regdata = brcmf_sdcard_reg_read(sdiodev,
209
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
210 211
		udelay(1);
		SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
212
			CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) &
213
			SSB_TMSHIGH_BUSY), 100000);
214 215

		regdata = brcmf_sdcard_reg_read(sdiodev,
216
			CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
217
		if (regdata & SSB_TMSHIGH_BUSY)
218 219 220
			brcmf_dbg(ERROR, "core state still busy\n");

		regdata = brcmf_sdcard_reg_read(sdiodev,
221
			CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
222
		if (regdata & SSB_IDLOW_INITIATOR) {
223
			regdata = brcmf_sdcard_reg_read(sdiodev,
224
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4) |
225
				SSB_IMSTATE_REJECT;
226
			brcmf_sdcard_reg_write(sdiodev,
227
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
228 229
				regdata);
			regdata = brcmf_sdcard_reg_read(sdiodev,
230
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
231 232
			udelay(1);
			SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
233
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
234
				SSB_IMSTATE_BUSY), 100000);
235 236 237 238
		}

		/* set reset and reject while enabling the clocks */
		brcmf_sdcard_reg_write(sdiodev,
239
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
240 241
			(SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
			SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
242
		regdata = brcmf_sdcard_reg_read(sdiodev,
243
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
244 245 246 247
		udelay(10);

		/* clear the initiator reject bit */
		regdata = brcmf_sdcard_reg_read(sdiodev,
248
			CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
249
		if (regdata & SSB_IDLOW_INITIATOR) {
250
			regdata = brcmf_sdcard_reg_read(sdiodev,
251
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
252
				~SSB_IMSTATE_REJECT;
253
			brcmf_sdcard_reg_write(sdiodev,
254
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
255 256 257 258 259
				regdata);
		}
	}

	/* leave reset and reject asserted */
260 261
	brcmf_sdcard_reg_write(sdiodev,
		CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
262
		(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
263 264 265
	udelay(1);
}

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
			  struct chip_info *ci, u16 coreid)
{
	u8 idx;
	u32 regdata;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

	/* if core is already in reset, just return */
	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
					4);
	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
		return;

	brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
			       4, 0);
	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
	udelay(10);

	brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
			       4, BCMA_RESET_CTL_RESET);
	udelay(1);
}

293 294 295
static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
			struct chip_info *ci, u16 coreid)
296 297
{
	u32 regdata;
298 299 300
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
301 302 303 304 305

	/*
	 * Must do the disable sequence first to work for
	 * arbitrary current core state.
	 */
306
	brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
307 308 309 310 311 312

	/*
	 * Now do the initialization sequence.
	 * set reset while enabling the clock and
	 * forcing them on throughout the core
	 */
313 314 315
	brcmf_sdcard_reg_write(sdiodev,
			CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
			SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
316 317
	regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
318 319
	udelay(1);

320
	/* clear any serror */
321
	regdata = brcmf_sdcard_reg_read(sdiodev,
322
				CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
323
	if (regdata & SSB_TMSHIGH_SERR)
324
		brcmf_sdcard_reg_write(sdiodev,
325
			CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0);
326 327

	regdata = brcmf_sdcard_reg_read(sdiodev,
328
				CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
329
	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
330 331
		brcmf_sdcard_reg_write(sdiodev,
			CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
332
			regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
333 334

	/* clear reset and allow it to propagate throughout the core */
335 336
	brcmf_sdcard_reg_write(sdiodev,
		CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
337
		SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
338 339
	regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
340 341 342
	udelay(1);

	/* leave clock enabled */
343 344
	brcmf_sdcard_reg_write(sdiodev,
			       CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
345
			       4, SSB_TMSLOW_CLOCK);
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
	regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
	udelay(1);
}

static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
			struct chip_info *ci, u16 coreid)
{
	u8 idx;
	u32 regdata;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

	/* must disable first to work for arbitrary current core state */
	brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);

	/* now do initialization sequence */
	brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
			       4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
	brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
			       4, 0);
	udelay(1);

	brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
			       4, BCMA_IOCTL_CLK);
	regdata = brcmf_sdcard_reg_read(sdiodev,
					ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
376 377 378
	udelay(1);
}

379 380 381 382 383 384 385 386 387 388 389
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.
	 */
390 391
	ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
	ci->c_inf[0].base = regs;
392
	regdata = brcmf_sdcard_reg_read(sdiodev,
393
			CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
394 395
	ci->chip = regdata & CID_ID_MASK;
	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
396
	ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
397 398 399 400 401 402

	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:
403 404 405 406 407 408
		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;
409 410
		ci->ramsize = BCM4329_RAMSIZE;
		break;
F
Franky Lin 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
	case BCM4330_CHIP_ID:
		ci->c_inf[0].wrapbase = 0x18100000;
		ci->c_inf[0].cib = 0x27004211;
		ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
		ci->c_inf[1].base = 0x18002000;
		ci->c_inf[1].wrapbase = 0x18102000;
		ci->c_inf[1].cib = 0x07004211;
		ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
		ci->c_inf[2].base = 0x18004000;
		ci->c_inf[2].wrapbase = 0x18104000;
		ci->c_inf[2].cib = 0x0d080401;
		ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
		ci->c_inf[3].base = 0x18003000;
		ci->c_inf[3].wrapbase = 0x18103000;
		ci->c_inf[3].cib = 0x03004211;
		ci->ramsize = 0x48000;
		break;
428 429 430 431 432
	default:
		brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
		return -ENODEV;
	}

433 434 435
	switch (ci->socitype) {
	case SOCI_SB:
		ci->iscoreup = brcmf_sdio_sb_iscoreup;
436
		ci->corerev = brcmf_sdio_sb_corerev;
437
		ci->coredisable = brcmf_sdio_sb_coredisable;
438
		ci->resetcore = brcmf_sdio_sb_resetcore;
439 440 441
		break;
	case SOCI_AI:
		ci->iscoreup = brcmf_sdio_ai_iscoreup;
442
		ci->corerev = brcmf_sdio_ai_corerev;
443
		ci->coredisable = brcmf_sdio_ai_coredisable;
444
		ci->resetcore = brcmf_sdio_ai_resetcore;
445 446 447 448 449 450
		break;
	default:
		brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype);
		return -ENODEV;
	}

451 452 453
	return 0;
}

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
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;
}

502 503 504 505 506
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
			     struct chip_info *ci)
{
	/* get chipcommon rev */
507
	ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
508 509

	/* get chipcommon capabilites */
510 511 512
	ci->c_inf[0].caps =
		brcmf_sdcard_reg_read(sdiodev,
		CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
513 514

	/* get pmu caps & rev */
515
	if (ci->c_inf[0].caps & CC_CAP_PMU) {
516
		ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
517
			CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
518 519 520
		ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
	}

521
	ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
522 523

	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
524 525
		  ci->c_inf[0].rev, ci->pmurev,
		  ci->c_inf[1].rev, ci->c_inf[1].id);
526 527 528 529 530

	/*
	 * Make sure any on-chip ARM is off (in case strapping is wrong),
	 * or downloaded code was already running.
	 */
531
	ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
532 533
}

534
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
535
			   struct chip_info **ci_ptr, u32 regs)
536
{
537 538 539 540 541 542 543 544 545
	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;
546

547 548
	ret = brcmf_sdio_chip_buscoreprep(sdiodev);
	if (ret != 0)
549
		goto err;
550

551 552
	ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
	if (ret != 0)
553
		goto err;
554

555 556
	brcmf_sdio_chip_buscoresetup(sdiodev, ci);

557
	brcmf_sdcard_reg_write(sdiodev,
558
		CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
559
	brcmf_sdcard_reg_write(sdiodev,
560
		CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
561

562 563 564 565 566
	*ci_ptr = ci;
	return 0;

err:
	kfree(ci);
567 568
	return ret;
}
569 570 571 572 573 574 575 576 577

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

	kfree(*ci_ptr);
	*ci_ptr = NULL;
}
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

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];

597
	if (!(ci->c_inf[0].caps & CC_CAP_PMU))
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
		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;
F
Franky Lin 已提交
617 618 619 620 621
	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
		str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab4_1v8;
		str_mask = 0x00003800;
		str_shift = 11;
		break;
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
	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,
642
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
643 644
			4, 1);
		cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
645
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
646 647 648 649
		cc_data_temp &= ~str_mask;
		drivestrength_sel <<= str_shift;
		cc_data_temp |= drivestrength_sel;
		brcmf_sdcard_reg_write(sdiodev,
650
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
651 652 653 654 655 656
			4, cc_data_temp);

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