sdio_chip.c 25.2 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
#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

43 44 45 46 47 48 49 50 51
/* bcm43143 */
/* SDIO device core */
#define BCM43143_CORE_BUS_BASE		0x18002000
/* internal memory core */
#define BCM43143_CORE_SOCRAM_BASE	0x18004000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM43143_CORE_ARM_BASE		0x18003000
#define BCM43143_RAMSIZE		0x70000

52
#define	SBCOREREV(sbidh) \
53 54
	((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
	  ((sbidh) & SSB_IDHIGH_RCLO))
55

56 57 58 59
/* SOC Interconnect types (aka chip types) */
#define SOCI_SB		0
#define SOCI_AI		1

60 61 62 63
/* EROM CompIdentB */
#define CIB_REV_MASK		0xff000000
#define CIB_REV_SHIFT		24

64 65 66
/* ARM CR4 core specific control flag bits */
#define ARMCR4_BCMA_IOCTL_CPUHALT	0x0020

67 68 69 70 71 72
#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 */
};
F
Franky Lin 已提交
73
/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
74
static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
F
Franky Lin 已提交
75 76 77 78 79 80 81 82 83 84
	{32, 0x6},
	{26, 0x7},
	{22, 0x4},
	{16, 0x5},
	{12, 0x2},
	{8, 0x3},
	{4, 0x0},
	{0, 0x1}
};

85 86 87 88 89 90 91 92 93 94 95 96
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;
}

97
static u32
98 99
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
		      struct chip_info *ci, u16 coreid)
100 101
{
	u32 regdata;
102 103 104
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
105

106 107 108
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_SB(ci->c_inf[idx].base, sbidhigh),
				   NULL);
109 110 111
	return SBCOREREV(regdata);
}

112 113 114 115 116 117 118 119 120 121 122
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;
}

123 124 125
static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
		       struct chip_info *ci, u16 coreid)
126 127
{
	u32 regdata;
128 129 130
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
131

132 133 134
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
				   NULL);
135 136 137
	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
	return (SSB_TMSLOW_CLOCK == regdata);
138 139
}

140 141 142 143 144 145 146 147 148 149
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);

150 151
	regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
				   NULL);
152 153
	ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;

154 155 156
	regdata = brcmf_sdio_regrl(sdiodev,
				   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
				   NULL);
157 158 159 160 161
	ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);

	return ret;
}

162 163
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
164
			  struct chip_info *ci, u16 coreid, u32 core_bits)
165
{
166
	u32 regdata, base;
167 168 169
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
170
	base = ci->c_inf[idx].base;
171

172
	regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
173
	if (regdata & SSB_TMSLOW_RESET)
174 175
		return;

176
	regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
177
	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
178 179 180 181
		/*
		 * set target reject and spin until busy is clear
		 * (preserve core-specific bits)
		 */
182 183
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
184 185
		brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
				 regdata | SSB_TMSLOW_REJECT, NULL);
186

187 188
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
189
		udelay(1);
190 191 192
		SPINWAIT((brcmf_sdio_regrl(sdiodev,
					   CORE_SB(base, sbtmstatehigh),
					   NULL) &
193
			SSB_TMSHIGH_BUSY), 100000);
194

195 196 197
		regdata = brcmf_sdio_regrl(sdiodev,
					   CORE_SB(base, sbtmstatehigh),
					   NULL);
198
		if (regdata & SSB_TMSHIGH_BUSY)
199
			brcmf_err("core state still busy\n");
200

201 202
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
					   NULL);
203
		if (regdata & SSB_IDLOW_INITIATOR) {
204 205 206 207
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
			regdata |= SSB_IMSTATE_REJECT;
208 209
			brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
					 regdata, NULL);
210 211 212
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
213
			udelay(1);
214 215 216
			SPINWAIT((brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL) &
217
				SSB_IMSTATE_BUSY), 100000);
218 219 220
		}

		/* set reset and reject while enabling the clocks */
221 222 223 224
		regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
			  SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
		brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
				 regdata, NULL);
225 226
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
227 228 229
		udelay(10);

		/* clear the initiator reject bit */
230 231
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
					   NULL);
232
		if (regdata & SSB_IDLOW_INITIATOR) {
233 234 235 236
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
			regdata &= ~SSB_IMSTATE_REJECT;
237 238
			brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
					 regdata, NULL);
239 240 241 242
		}
	}

	/* leave reset and reject asserted */
243 244
	brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
			 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
245 246 247
	udelay(1);
}

248 249
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
250
			  struct chip_info *ci, u16 coreid, u32 core_bits)
251 252 253 254 255 256 257
{
	u8 idx;
	u32 regdata;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

	/* if core is already in reset, just return */
258 259 260
	regdata = brcmf_sdio_regrl(sdiodev,
				   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
				   NULL);
261 262 263
	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
		return;

264 265 266 267 268 269 270 271 272 273
	/* ensure no pending backplane operation
	 * 300uc should be sufficient for backplane ops to be finish
	 * extra 10ms is taken into account for firmware load stage
	 * after 10300us carry on disabling the core anyway
	 */
	SPINWAIT(brcmf_sdio_regrl(sdiodev,
				  ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
				  NULL), 10300);
	regdata = brcmf_sdio_regrl(sdiodev,
				   ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
274
				   NULL);
275 276 277
	if (regdata)
		brcmf_err("disabling core 0x%x with reset status %x\n",
			  coreid, regdata);
278

279 280
	brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
			 BCMA_RESET_CTL_RESET, NULL);
281
	udelay(1);
282 283 284 285 286 287 288

	brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
			 core_bits, NULL);
	regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
				   NULL);
	usleep_range(10, 20);

289 290
}

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

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
299 300 301 302 303

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

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

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

329 330 331
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_SB(ci->c_inf[idx].base, sbimstate),
				   NULL);
332
	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
333 334 335 336
		brcmf_sdio_regwl(sdiodev,
				 CORE_SB(ci->c_inf[idx].base, sbimstate),
				 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
				 NULL);
337 338

	/* clear reset and allow it to propagate throughout the core */
339 340
	brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
			 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
341 342 343
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
				   NULL);
344 345 346
	udelay(1);

	/* leave clock enabled */
347 348
	brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
			 SSB_TMSLOW_CLOCK, NULL);
349 350 351
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
				   NULL);
352 353 354 355 356
	udelay(1);
}

static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
357
			struct chip_info *ci, u16 coreid, u32 core_bits)
358 359 360 361 362 363 364
{
	u8 idx;
	u32 regdata;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);

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

	/* now do initialization sequence */
368
	brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
369
			 core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
370 371
	regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
				   NULL);
372 373
	brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
			 0, NULL);
374 375 376
	regdata = brcmf_sdio_regrl(sdiodev,
				   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
				   NULL);
377 378
	udelay(1);

379
	brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
380
			 core_bits | BCMA_IOCTL_CLK, NULL);
381 382
	regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
				   NULL);
383 384 385
	udelay(1);
}

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
#ifdef DEBUG
/* safety check for chipinfo */
static int brcmf_sdio_chip_cichk(struct chip_info *ci)
{
	u8 core_idx;

	/* check RAM core presence for ARM CM3 core */
	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
	if (BRCMF_MAX_CORENUM != core_idx) {
		core_idx = brcmf_sdio_chip_getinfidx(ci,
						     BCMA_CORE_INTERNAL_MEM);
		if (BRCMF_MAX_CORENUM == core_idx) {
			brcmf_err("RAM core not provided with ARM CM3 core\n");
			return -ENODEV;
		}
	}

	/* check RAM base for ARM CR4 core */
	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
	if (BRCMF_MAX_CORENUM != core_idx) {
		if (ci->rambase == 0) {
			brcmf_err("RAM base not provided with ARM CR4 core\n");
			return -ENOMEM;
		}
	}

	return 0;
}
#else	/* DEBUG */
static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
{
	return 0;
}
#endif

421 422 423 424
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
				       struct chip_info *ci, u32 regs)
{
	u32 regdata;
425
	int ret;
426

427
	/* Get CC core rev
428 429 430 431
	 * 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.
	 */
432 433
	ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
	ci->c_inf[0].base = regs;
434 435 436
	regdata = brcmf_sdio_regrl(sdiodev,
				   CORE_CC_REG(ci->c_inf[0].base, chipid),
				   NULL);
437 438
	ci->chip = regdata & CID_ID_MASK;
	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
439
	ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
440 441 442 443 444

	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) {
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
	case BCM43143_CHIP_ID:
		ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
		ci->c_inf[0].cib = 0x2b000000;
		ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
		ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
		ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
		ci->c_inf[1].cib = 0x18000000;
		ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
		ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
		ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
		ci->c_inf[2].cib = 0x14000000;
		ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
		ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
		ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
		ci->c_inf[3].cib = 0x07000000;
		ci->ramsize = BCM43143_RAMSIZE;
		break;
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	case BCM43241_CHIP_ID:
		ci->c_inf[0].wrapbase = 0x18100000;
		ci->c_inf[0].cib = 0x2a084411;
		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 = 0x0e004211;
		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 = 0x14080401;
		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 = 0x07004211;
		ci->ramsize = 0x90000;
		break;
479
	case BCM4329_CHIP_ID:
480 481 482 483 484 485
		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;
486 487
		ci->ramsize = BCM4329_RAMSIZE;
		break;
F
Franky Lin 已提交
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
	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;
F
Franky Lin 已提交
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
	case BCM4334_CHIP_ID:
		ci->c_inf[0].wrapbase = 0x18100000;
		ci->c_inf[0].cib = 0x29004211;
		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 = 0x0d004211;
		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 = 0x13080401;
		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 = 0x07004211;
		ci->ramsize = 0x80000;
		break;
522 523 524 525 526 527 528 529 530 531 532 533 534 535
	case BCM4335_CHIP_ID:
		ci->c_inf[0].wrapbase = 0x18100000;
		ci->c_inf[0].cib = 0x2b084411;
		ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
		ci->c_inf[1].base = 0x18005000;
		ci->c_inf[1].wrapbase = 0x18105000;
		ci->c_inf[1].cib = 0x0f004211;
		ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
		ci->c_inf[2].base = 0x18002000;
		ci->c_inf[2].wrapbase = 0x18102000;
		ci->c_inf[2].cib = 0x01084411;
		ci->ramsize = 0xc0000;
		ci->rambase = 0x180000;
		break;
536
	default:
537
		brcmf_err("chipid 0x%x is not supported\n", ci->chip);
538 539 540
		return -ENODEV;
	}

541 542 543 544
	ret = brcmf_sdio_chip_cichk(ci);
	if (ret)
		return ret;

545 546 547
	switch (ci->socitype) {
	case SOCI_SB:
		ci->iscoreup = brcmf_sdio_sb_iscoreup;
548
		ci->corerev = brcmf_sdio_sb_corerev;
549
		ci->coredisable = brcmf_sdio_sb_coredisable;
550
		ci->resetcore = brcmf_sdio_sb_resetcore;
551 552 553
		break;
	case SOCI_AI:
		ci->iscoreup = brcmf_sdio_ai_iscoreup;
554
		ci->corerev = brcmf_sdio_ai_corerev;
555
		ci->coredisable = brcmf_sdio_ai_coredisable;
556
		ci->resetcore = brcmf_sdio_ai_resetcore;
557 558
		break;
	default:
559
		brcmf_err("socitype %u not supported\n", ci->socitype);
560 561 562
		return -ENODEV;
	}

563 564 565
	return 0;
}

566 567 568 569 570 571 572 573
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;
574
	brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
575
	if (err) {
576
		brcmf_err("error writing for HT off\n");
577 578 579 580 581
		return err;
	}

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

	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
586
		brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
587 588 589 590
			  clkset, clkval);
		return -EACCES;
	}

591 592
	SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev,
					     SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
593 594 595
			!SBSDIO_ALPAV(clkval)),
			PMU_MAX_TRANSITION_DLY);
	if (!SBSDIO_ALPAV(clkval)) {
596
		brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
597 598 599 600 601
			  clkval);
		return -EBUSY;
	}

	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
602
	brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
603 604 605
	udelay(65);

	/* Also, disable the extra SDIO pull-ups */
606
	brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
607 608 609 610

	return 0;
}

611 612 613 614
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
			     struct chip_info *ci)
{
615 616
	u32 base = ci->c_inf[0].base;

617
	/* get chipcommon rev */
618
	ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
619 620

	/* get chipcommon capabilites */
621 622 623
	ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev,
					     CORE_CC_REG(base, capabilities),
					     NULL);
624 625

	/* get pmu caps & rev */
626
	if (ci->c_inf[0].caps & CC_CAP_PMU) {
627 628 629 630
		ci->pmucaps =
			brcmf_sdio_regrl(sdiodev,
					 CORE_CC_REG(base, pmucapabilities),
					 NULL);
631 632 633
		ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
	}

634
	ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
635 636

	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
637 638
		  ci->c_inf[0].rev, ci->pmurev,
		  ci->c_inf[1].rev, ci->c_inf[1].id);
639 640 641 642 643

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

647
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
648
			   struct chip_info **ci_ptr, u32 regs)
649
{
650 651 652 653 654 655 656 657 658
	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;
659

660 661
	ret = brcmf_sdio_chip_buscoreprep(sdiodev);
	if (ret != 0)
662
		goto err;
663

664 665
	ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
	if (ret != 0)
666
		goto err;
667

668 669
	brcmf_sdio_chip_buscoresetup(sdiodev, ci);

670 671 672 673
	brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
			 0, NULL);
	brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
			 0, NULL);
674

675 676 677 678 679
	*ci_ptr = ci;
	return 0;

err:
	kfree(ci);
680 681
	return ret;
}
682 683 684 685 686 687 688 689 690

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

	kfree(*ci_ptr);
	*ci_ptr = NULL;
}
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708

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];
709
	u32 base = ci->c_inf[0].base;
710

711
	if (!(ci->c_inf[0].caps & CC_CAP_PMU))
712 713 714
		return;

	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
F
Franky Lin 已提交
715
	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
716
		str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
F
Franky Lin 已提交
717 718 719
		str_mask = 0x00003800;
		str_shift = 11;
		break;
720
	default:
721
		brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
			  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;
			}
		}

739 740
		brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
				 1, NULL);
741 742 743 744
		cc_data_temp =
			brcmf_sdio_regrl(sdiodev,
					 CORE_CC_REG(base, chipcontrol_addr),
					 NULL);
745 746 747
		cc_data_temp &= ~str_mask;
		drivestrength_sel <<= str_shift;
		cc_data_temp |= drivestrength_sel;
748 749
		brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
				 cc_data_temp, NULL);
750 751 752 753 754

		brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
			  drivestrength, cc_data_temp);
	}
}
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806

#ifdef DEBUG
static bool
brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
			    char *nvram_dat, uint nvram_sz)
{
	char *nvram_ularray;
	int err;
	bool ret = true;

	/* read back and verify */
	brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
	nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
	/* do not proceed while no memory but  */
	if (!nvram_ularray)
		return true;

	/* Upload image to verify downloaded contents. */
	memset(nvram_ularray, 0xaa, nvram_sz);

	/* Read the vars list to temp buffer for comparison */
	err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
			       nvram_sz);
	if (err) {
		brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
			  err, nvram_sz, nvram_addr);
	} else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
		brcmf_err("Downloaded NVRAM image is corrupted\n");
		ret = false;
	}
	kfree(nvram_ularray);

	return ret;
}
#else	/* DEBUG */
static inline bool
brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
			    char *nvram_dat, uint nvram_sz)
{
	return true;
}
#endif	/* DEBUG */

static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
				       struct chip_info *ci,
				       char *nvram_dat, uint nvram_sz)
{
	int err;
	u32 nvram_addr;
	u32 token;
	__le32 token_le;

807
	nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833

	/* Write the vars list */
	err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
	if (err) {
		brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
			  err, nvram_sz, nvram_addr);
		return false;
	}

	if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
					 nvram_dat, nvram_sz))
		return false;

	/* generate token:
	 * nvram size, converted to words, in lower 16-bits, checksum
	 * in upper 16-bits.
	 */
	token = nvram_sz / 4;
	token = (~token << 16) | (token & 0x0000FFFF);
	token_le = cpu_to_le32(token);

	brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
	brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
		  nvram_addr, nvram_sz, token);

	/* Write the length token to the last word */
834
	if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
835 836 837 838 839 840 841 842 843 844 845 846
			     (u8 *)&token_le, 4))
		return false;

	return true;
}

static void
brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
			    struct chip_info *ci)
{
	u32 zeros = 0;

847 848
	ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
	ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874

	/* clear length token */
	brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
}

static bool
brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
			   char *nvram_dat, uint nvram_sz)
{
	u8 core_idx;
	u32 reg_addr;

	if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
		brcmf_err("SOCRAM core is down after reset?\n");
		return false;
	}

	if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
		return false;

	/* clear all interrupts */
	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
	reg_addr = ci->c_inf[core_idx].base;
	reg_addr += offsetof(struct sdpcmd_regs, intstatus);
	brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);

875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);

	return true;
}

static inline void
brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
			    struct chip_info *ci)
{
	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
		      ARMCR4_BCMA_IOCTL_CPUHALT);
}

static bool
brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
			   char *nvram_dat, uint nvram_sz)
{
	u8 core_idx;
	u32 reg_addr;

	if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
		return false;

	/* clear all interrupts */
	core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
	reg_addr = ci->c_inf[core_idx].base;
	reg_addr += offsetof(struct sdpcmd_regs, intstatus);
	brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);

	/* Write reset vector to address 0 */
	brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
			 sizeof(ci->rst_vec));

	/* restore ARM */
	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
910 911 912 913 914 915 916

	return true;
}

void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
				    struct chip_info *ci)
{
917 918 919 920 921 922 923 924 925
	u8 arm_core_idx;

	arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
	if (BRCMF_MAX_CORENUM != arm_core_idx) {
		brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
		return;
	}

	brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
926 927 928 929 930 931
}

bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
				   struct chip_info *ci, char *nvram_dat,
				   uint nvram_sz)
{
932 933 934 935 936 937 938 939
	u8 arm_core_idx;

	arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
	if (BRCMF_MAX_CORENUM != arm_core_idx)
		return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
						  nvram_sz);

	return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
940
}