sdio_chip.c 13.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 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 52 53 54 55 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
#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}
	};

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

98 99 100 101 102 103 104 105 106 107 108
static u32
brcmf_sdio_chip_corerev(struct brcmf_sdio_dev *sdiodev,
			u32 corebase)
{
	u32 regdata;

	regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbidhigh), 4);
	return SBCOREREV(regdata);
}

109 110 111 112 113 114 115 116
bool
brcmf_sdio_chip_iscoreup(struct brcmf_sdio_dev *sdiodev,
			 u32 corebase)
{
	u32 regdata;

	regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4);
117 118 119
	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
	return (SSB_TMSLOW_CLOCK == regdata);
120 121
}

122 123 124 125 126 127 128
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);
129
	if (regdata & SSB_TMSLOW_RESET)
130 131 132 133
		return;

	regdata = brcmf_sdcard_reg_read(sdiodev,
		CORE_SB(corebase, sbtmstatelow), 4);
134
	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
135 136 137 138 139 140 141
		/*
		 * 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),
142
				       4, regdata | SSB_TMSLOW_REJECT);
143 144 145 146 147 148

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4);
		udelay(1);
		SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatehigh), 4) &
149
			SSB_TMSHIGH_BUSY), 100000);
150 151 152

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbtmstatehigh), 4);
153
		if (regdata & SSB_TMSHIGH_BUSY)
154 155 156 157
			brcmf_dbg(ERROR, "core state still busy\n");

		regdata = brcmf_sdcard_reg_read(sdiodev,
			CORE_SB(corebase, sbidlow), 4);
158
		if (regdata & SSB_IDLOW_INITIATOR) {
159 160
			regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4) |
161
				SSB_IMSTATE_REJECT;
162 163 164 165 166 167 168 169
			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) &
170
				SSB_IMSTATE_BUSY), 100000);
171 172 173 174 175
		}

		/* set reset and reject while enabling the clocks */
		brcmf_sdcard_reg_write(sdiodev,
			CORE_SB(corebase, sbtmstatelow), 4,
176 177
			(SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
			SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
178 179 180 181 182 183 184
		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);
185
		if (regdata & SSB_IDLOW_INITIATOR) {
186 187
			regdata = brcmf_sdcard_reg_read(sdiodev,
				CORE_SB(corebase, sbimstate), 4) &
188
				~SSB_IMSTATE_REJECT;
189 190 191 192 193 194 195 196
			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,
197
		(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
198 199 200
	udelay(1);
}

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
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,
218
		SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
219 220 221 222
	udelay(1);

	regdata = brcmf_sdcard_reg_read(sdiodev,
					CORE_SB(corebase, sbtmstatehigh), 4);
223
	if (regdata & SSB_TMSHIGH_SERR)
224 225 226 227 228
		brcmf_sdcard_reg_write(sdiodev,
				       CORE_SB(corebase, sbtmstatehigh), 4, 0);

	regdata = brcmf_sdcard_reg_read(sdiodev,
					CORE_SB(corebase, sbimstate), 4);
229
	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
230
		brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
231
			regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
232 233 234

	/* clear reset and allow it to propagate throughout the core */
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
235
		SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
236 237 238
	udelay(1);

	/* leave clock enabled */
239 240
	brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
			       4, SSB_TMSLOW_CLOCK);
241 242 243
	udelay(1);
}

244 245 246 247 248 249 250 251 252 253 254
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.
	 */
255 256
	ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
	ci->c_inf[0].base = regs;
257
	regdata = brcmf_sdcard_reg_read(sdiodev,
258
			CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
259 260 261 262 263 264 265 266
	ci->chip = regdata & CID_ID_MASK;
	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;

	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:
267 268 269 270 271 272
		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;
273 274 275 276 277 278 279 280 281 282
		ci->ramsize = BCM4329_RAMSIZE;
		break;
	default:
		brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
		return -ENODEV;
	}

	return 0;
}

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
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;
}

331 332 333 334 335
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
			     struct chip_info *ci)
{
	u32 regdata;
336
	u8 idx;
337 338

	/* get chipcommon rev */
339 340
	ci->c_inf[0].rev =
		brcmf_sdio_chip_corerev(sdiodev, ci->c_inf[0].base);
341 342

	/* get chipcommon capabilites */
343 344 345
	ci->c_inf[0].caps =
		brcmf_sdcard_reg_read(sdiodev,
		CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
346 347

	/* get pmu caps & rev */
348
	if (ci->c_inf[0].caps & CC_CAP_PMU) {
349
		ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
350
			CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
351 352 353
		ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
	}

354
	ci->c_inf[1].rev = brcmf_sdio_chip_corerev(sdiodev, ci->c_inf[1].base);
355
	regdata = brcmf_sdcard_reg_read(sdiodev,
356 357
				CORE_SB(ci->c_inf[1].base, sbidhigh), 4);
	ci->c_inf[1].id = (regdata & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
358 359

	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
360 361
		  ci->c_inf[0].rev, ci->pmurev,
		  ci->c_inf[1].rev, ci->c_inf[1].id);
362 363 364 365 366

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

371
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
372
			   struct chip_info **ci_ptr, u32 regs)
373
{
374 375 376 377 378 379 380 381 382
	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;
383

384 385
	ret = brcmf_sdio_chip_buscoreprep(sdiodev);
	if (ret != 0)
386
		goto err;
387

388 389
	ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
	if (ret != 0)
390
		goto err;
391

392 393
	brcmf_sdio_chip_buscoresetup(sdiodev, ci);

394
	brcmf_sdcard_reg_write(sdiodev,
395
		CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
396
	brcmf_sdcard_reg_write(sdiodev,
397
		CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
398

399 400 401 402 403
	*ci_ptr = ci;
	return 0;

err:
	kfree(ci);
404 405
	return ret;
}
406 407 408 409 410 411 412 413 414

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

	kfree(*ci_ptr);
	*ci_ptr = NULL;
}
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433

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

434
	if (!(ci->c_inf[0].caps & CC_CAP_PMU))
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
		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,
474
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
475 476
			4, 1);
		cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
477
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
478 479 480 481
		cc_data_temp &= ~str_mask;
		drivestrength_sel <<= str_shift;
		cc_data_temp |= drivestrength_sel;
		brcmf_sdcard_reg_write(sdiodev,
482
			CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
483 484 485 486 487 488
			4, cc_data_temp);

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