1/* 2 * Copyright (c) 2011 Broadcom Corporation 3 * 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. 7 * 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. 15 */ 16/* ***** SDIO interface chip backplane handle functions ***** */ 17 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 20#include <linux/types.h> 21#include <linux/netdevice.h> 22#include <linux/mmc/card.h> 23#include <linux/ssb/ssb_regs.h> 24#include <linux/bcma/bcma.h> 25 26#include <chipcommon.h> 27#include <brcm_hw_ids.h> 28#include <brcmu_wifi.h> 29#include <brcmu_utils.h> 30#include <soc.h> 31#include "dhd_dbg.h" 32#include "sdio_host.h" 33#include "sdio_chip.h" 34 35/* chip core base & ramsize */ 36/* bcm4329 */ 37/* SDIO device core, ID 0x829 */ 38#define BCM4329_CORE_BUS_BASE 0x18011000 39/* internal memory core, ID 0x80e */ 40#define BCM4329_CORE_SOCRAM_BASE 0x18003000 41/* ARM Cortex M3 core, ID 0x82a */ 42#define BCM4329_CORE_ARM_BASE 0x18002000 43#define BCM4329_RAMSIZE 0x48000 44 45#define SBCOREREV(sbidh) \ 46 ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ 47 ((sbidh) & SSB_IDHIGH_RCLO)) 48 49/* SOC Interconnect types (aka chip types) */ 50#define SOCI_SB 0 51#define SOCI_AI 1 52 53/* EROM CompIdentB */ 54#define CIB_REV_MASK 0xff000000 55#define CIB_REV_SHIFT 24 56 57#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) 58/* SDIO Pad drive strength to select value mappings */ 59struct sdiod_drive_str { 60 u8 strength; /* Pad Drive Strength in mA */ 61 u8 sel; /* Chip-specific select value */ 62}; 63/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */ 64static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = { 65 {32, 0x6}, 66 {26, 0x7}, 67 {22, 0x4}, 68 {16, 0x5}, 69 {12, 0x2}, 70 {8, 0x3}, 71 {4, 0x0}, 72 {0, 0x1} 73}; 74 75u8 76brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) 77{ 78 u8 idx; 79 80 for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++) 81 if (coreid == ci->c_inf[idx].id) 82 return idx; 83 84 return BRCMF_MAX_CORENUM; 85} 86 87static u32 88brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, 89 struct chip_info *ci, u16 coreid) 90{ 91 u32 regdata; 92 u8 idx; 93 94 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 95 96 regdata = brcmf_sdcard_reg_read(sdiodev, 97 CORE_SB(ci->c_inf[idx].base, sbidhigh), 4); 98 return SBCOREREV(regdata); 99} 100 101static u32 102brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev, 103 struct chip_info *ci, u16 coreid) 104{ 105 u8 idx; 106 107 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 108 109 return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT; 110} 111 112static bool 113brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, 114 struct chip_info *ci, u16 coreid) 115{ 116 u32 regdata; 117 u8 idx; 118 119 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 120 121 regdata = brcmf_sdcard_reg_read(sdiodev, 122 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 123 regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | 124 SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); 125 return (SSB_TMSLOW_CLOCK == regdata); 126} 127 128static bool 129brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, 130 struct chip_info *ci, u16 coreid) 131{ 132 u32 regdata; 133 u8 idx; 134 bool ret; 135 136 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 137 138 regdata = brcmf_sdcard_reg_read(sdiodev, 139 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); 140 ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; 141 142 regdata = brcmf_sdcard_reg_read(sdiodev, 143 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, 144 4); 145 ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); 146 147 return ret; 148} 149 150static void 151brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, 152 struct chip_info *ci, u16 coreid) 153{ 154 u32 regdata; 155 u8 idx; 156 157 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 158 159 regdata = brcmf_sdcard_reg_read(sdiodev, 160 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 161 if (regdata & SSB_TMSLOW_RESET) 162 return; 163 164 regdata = brcmf_sdcard_reg_read(sdiodev, 165 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 166 if ((regdata & SSB_TMSLOW_CLOCK) != 0) { 167 /* 168 * set target reject and spin until busy is clear 169 * (preserve core-specific bits) 170 */ 171 regdata = brcmf_sdcard_reg_read(sdiodev, 172 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 173 brcmf_sdcard_reg_write(sdiodev, 174 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 175 4, regdata | SSB_TMSLOW_REJECT); 176 177 regdata = brcmf_sdcard_reg_read(sdiodev, 178 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 179 udelay(1); 180 SPINWAIT((brcmf_sdcard_reg_read(sdiodev, 181 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) & 182 SSB_TMSHIGH_BUSY), 100000); 183 184 regdata = brcmf_sdcard_reg_read(sdiodev, 185 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); 186 if (regdata & SSB_TMSHIGH_BUSY) 187 brcmf_dbg(ERROR, "core state still busy\n"); 188 189 regdata = brcmf_sdcard_reg_read(sdiodev, 190 CORE_SB(ci->c_inf[idx].base, sbidlow), 4); 191 if (regdata & SSB_IDLOW_INITIATOR) { 192 regdata = brcmf_sdcard_reg_read(sdiodev, 193 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) | 194 SSB_IMSTATE_REJECT; 195 brcmf_sdcard_reg_write(sdiodev, 196 CORE_SB(ci->c_inf[idx].base, sbimstate), 4, 197 regdata); 198 regdata = brcmf_sdcard_reg_read(sdiodev, 199 CORE_SB(ci->c_inf[idx].base, sbimstate), 4); 200 udelay(1); 201 SPINWAIT((brcmf_sdcard_reg_read(sdiodev, 202 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & 203 SSB_IMSTATE_BUSY), 100000); 204 } 205 206 /* set reset and reject while enabling the clocks */ 207 brcmf_sdcard_reg_write(sdiodev, 208 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, 209 (SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | 210 SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); 211 regdata = brcmf_sdcard_reg_read(sdiodev, 212 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 213 udelay(10); 214 215 /* clear the initiator reject bit */ 216 regdata = brcmf_sdcard_reg_read(sdiodev, 217 CORE_SB(ci->c_inf[idx].base, sbidlow), 4); 218 if (regdata & SSB_IDLOW_INITIATOR) { 219 regdata = brcmf_sdcard_reg_read(sdiodev, 220 CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & 221 ~SSB_IMSTATE_REJECT; 222 brcmf_sdcard_reg_write(sdiodev, 223 CORE_SB(ci->c_inf[idx].base, sbimstate), 4, 224 regdata); 225 } 226 } 227 228 /* leave reset and reject asserted */ 229 brcmf_sdcard_reg_write(sdiodev, 230 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, 231 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); 232 udelay(1); 233} 234 235static void 236brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, 237 struct chip_info *ci, u16 coreid) 238{ 239 u8 idx; 240 u32 regdata; 241 242 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 243 244 /* if core is already in reset, just return */ 245 regdata = brcmf_sdcard_reg_read(sdiodev, 246 ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, 247 4); 248 if ((regdata & BCMA_RESET_CTL_RESET) != 0) 249 return; 250 251 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 252 4, 0); 253 regdata = brcmf_sdcard_reg_read(sdiodev, 254 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); 255 udelay(10); 256 257 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, 258 4, BCMA_RESET_CTL_RESET); 259 udelay(1); 260} 261 262static void 263brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, 264 struct chip_info *ci, u16 coreid) 265{ 266 u32 regdata; 267 u8 idx; 268 269 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 270 271 /* 272 * Must do the disable sequence first to work for 273 * arbitrary current core state. 274 */ 275 brcmf_sdio_sb_coredisable(sdiodev, ci, coreid); 276 277 /* 278 * Now do the initialization sequence. 279 * set reset while enabling the clock and 280 * forcing them on throughout the core 281 */ 282 brcmf_sdcard_reg_write(sdiodev, 283 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, 284 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET); 285 regdata = brcmf_sdcard_reg_read(sdiodev, 286 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 287 udelay(1); 288 289 /* clear any serror */ 290 regdata = brcmf_sdcard_reg_read(sdiodev, 291 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); 292 if (regdata & SSB_TMSHIGH_SERR) 293 brcmf_sdcard_reg_write(sdiodev, 294 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0); 295 296 regdata = brcmf_sdcard_reg_read(sdiodev, 297 CORE_SB(ci->c_inf[idx].base, sbimstate), 4); 298 if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) 299 brcmf_sdcard_reg_write(sdiodev, 300 CORE_SB(ci->c_inf[idx].base, sbimstate), 4, 301 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO)); 302 303 /* clear reset and allow it to propagate throughout the core */ 304 brcmf_sdcard_reg_write(sdiodev, 305 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, 306 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK); 307 regdata = brcmf_sdcard_reg_read(sdiodev, 308 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 309 udelay(1); 310 311 /* leave clock enabled */ 312 brcmf_sdcard_reg_write(sdiodev, 313 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 314 4, SSB_TMSLOW_CLOCK); 315 regdata = brcmf_sdcard_reg_read(sdiodev, 316 CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); 317 udelay(1); 318} 319 320static void 321brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, 322 struct chip_info *ci, u16 coreid) 323{ 324 u8 idx; 325 u32 regdata; 326 327 idx = brcmf_sdio_chip_getinfidx(ci, coreid); 328 329 /* must disable first to work for arbitrary current core state */ 330 brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); 331 332 /* now do initialization sequence */ 333 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 334 4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); 335 regdata = brcmf_sdcard_reg_read(sdiodev, 336 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); 337 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, 338 4, 0); 339 udelay(1); 340 341 brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 342 4, BCMA_IOCTL_CLK); 343 regdata = brcmf_sdcard_reg_read(sdiodev, 344 ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); 345 udelay(1); 346} 347 348static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, 349 struct chip_info *ci, u32 regs) 350{ 351 u32 regdata; 352 353 /* 354 * Get CC core rev 355 * Chipid is assume to be at offset 0 from regs arg 356 * For different chiptypes or old sdio hosts w/o chipcommon, 357 * other ways of recognition should be added here. 358 */ 359 ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; 360 ci->c_inf[0].base = regs; 361 regdata = brcmf_sdcard_reg_read(sdiodev, 362 CORE_CC_REG(ci->c_inf[0].base, chipid), 4); 363 ci->chip = regdata & CID_ID_MASK; 364 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; 365 ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 366 367 brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); 368 369 /* Address of cores for new chips should be added here */ 370 switch (ci->chip) { 371 case BCM4329_CHIP_ID: 372 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; 373 ci->c_inf[1].base = BCM4329_CORE_BUS_BASE; 374 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; 375 ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE; 376 ci->c_inf[3].id = BCMA_CORE_ARM_CM3; 377 ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; 378 ci->ramsize = BCM4329_RAMSIZE; 379 break; 380 case BCM4330_CHIP_ID: 381 ci->c_inf[0].wrapbase = 0x18100000; 382 ci->c_inf[0].cib = 0x27004211; 383 ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; 384 ci->c_inf[1].base = 0x18002000; 385 ci->c_inf[1].wrapbase = 0x18102000; 386 ci->c_inf[1].cib = 0x07004211; 387 ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; 388 ci->c_inf[2].base = 0x18004000; 389 ci->c_inf[2].wrapbase = 0x18104000; 390 ci->c_inf[2].cib = 0x0d080401; 391 ci->c_inf[3].id = BCMA_CORE_ARM_CM3; 392 ci->c_inf[3].base = 0x18003000; 393 ci->c_inf[3].wrapbase = 0x18103000; 394 ci->c_inf[3].cib = 0x03004211; 395 ci->ramsize = 0x48000; 396 break; 397 default: 398 brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); 399 return -ENODEV; 400 } 401 402 switch (ci->socitype) { 403 case SOCI_SB: 404 ci->iscoreup = brcmf_sdio_sb_iscoreup; 405 ci->corerev = brcmf_sdio_sb_corerev; 406 ci->coredisable = brcmf_sdio_sb_coredisable; 407 ci->resetcore = brcmf_sdio_sb_resetcore; 408 break; 409 case SOCI_AI: 410 ci->iscoreup = brcmf_sdio_ai_iscoreup; 411 ci->corerev = brcmf_sdio_ai_corerev; 412 ci->coredisable = brcmf_sdio_ai_coredisable; 413 ci->resetcore = brcmf_sdio_ai_resetcore; 414 break; 415 default: 416 brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype); 417 return -ENODEV; 418 } 419 420 return 0; 421} 422 423static int 424brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) 425{ 426 int err = 0; 427 u8 clkval, clkset; 428 429 /* Try forcing SDIO core to do ALPAvail request only */ 430 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; 431 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, 432 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); 433 if (err) { 434 brcmf_dbg(ERROR, "error writing for HT off\n"); 435 return err; 436 } 437 438 /* If register supported, wait for ALPAvail and then force ALP */ 439 /* This may take up to 15 milliseconds */ 440 clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, 441 SBSDIO_FUNC1_CHIPCLKCSR, NULL); 442 443 if ((clkval & ~SBSDIO_AVBITS) != clkset) { 444 brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", 445 clkset, clkval); 446 return -EACCES; 447 } 448 449 SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, 450 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), 451 !SBSDIO_ALPAV(clkval)), 452 PMU_MAX_TRANSITION_DLY); 453 if (!SBSDIO_ALPAV(clkval)) { 454 brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n", 455 clkval); 456 return -EBUSY; 457 } 458 459 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; 460 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, 461 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); 462 udelay(65); 463 464 /* Also, disable the extra SDIO pull-ups */ 465 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, 466 SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); 467 468 return 0; 469} 470 471static void 472brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, 473 struct chip_info *ci) 474{ 475 /* get chipcommon rev */ 476 ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); 477 478 /* get chipcommon capabilites */ 479 ci->c_inf[0].caps = 480 brcmf_sdcard_reg_read(sdiodev, 481 CORE_CC_REG(ci->c_inf[0].base, capabilities), 4); 482 483 /* get pmu caps & rev */ 484 if (ci->c_inf[0].caps & CC_CAP_PMU) { 485 ci->pmucaps = brcmf_sdcard_reg_read(sdiodev, 486 CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4); 487 ci->pmurev = ci->pmucaps & PCAP_REV_MASK; 488 } 489 490 ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id); 491 492 brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", 493 ci->c_inf[0].rev, ci->pmurev, 494 ci->c_inf[1].rev, ci->c_inf[1].id); 495 496 /* 497 * Make sure any on-chip ARM is off (in case strapping is wrong), 498 * or downloaded code was already running. 499 */ 500 ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3); 501} 502 503int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, 504 struct chip_info **ci_ptr, u32 regs) 505{ 506 int ret; 507 struct chip_info *ci; 508 509 brcmf_dbg(TRACE, "Enter\n"); 510 511 /* alloc chip_info_t */ 512 ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); 513 if (!ci) 514 return -ENOMEM; 515 516 ret = brcmf_sdio_chip_buscoreprep(sdiodev); 517 if (ret != 0) 518 goto err; 519 520 ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs); 521 if (ret != 0) 522 goto err; 523 524 brcmf_sdio_chip_buscoresetup(sdiodev, ci); 525 526 brcmf_sdcard_reg_write(sdiodev, 527 CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0); 528 brcmf_sdcard_reg_write(sdiodev, 529 CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0); 530 531 *ci_ptr = ci; 532 return 0; 533 534err: 535 kfree(ci); 536 return ret; 537} 538 539void 540brcmf_sdio_chip_detach(struct chip_info **ci_ptr) 541{ 542 brcmf_dbg(TRACE, "Enter\n"); 543 544 kfree(*ci_ptr); 545 *ci_ptr = NULL; 546} 547 548static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len) 549{ 550 const char *fmt; 551 552 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; 553 snprintf(buf, len, fmt, chipid); 554 return buf; 555} 556 557void 558brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, 559 struct chip_info *ci, u32 drivestrength) 560{ 561 struct sdiod_drive_str *str_tab = NULL; 562 u32 str_mask = 0; 563 u32 str_shift = 0; 564 char chn[8]; 565 566 if (!(ci->c_inf[0].caps & CC_CAP_PMU)) 567 return; 568 569 switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { 570 case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): 571 str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8; 572 str_mask = 0x00003800; 573 str_shift = 11; 574 break; 575 default: 576 brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", 577 brcmf_sdio_chip_name(ci->chip, chn, 8), 578 ci->chiprev, ci->pmurev); 579 break; 580 } 581 582 if (str_tab != NULL) { 583 u32 drivestrength_sel = 0; 584 u32 cc_data_temp; 585 int i; 586 587 for (i = 0; str_tab[i].strength != 0; i++) { 588 if (drivestrength >= str_tab[i].strength) { 589 drivestrength_sel = str_tab[i].sel; 590 break; 591 } 592 } 593 594 brcmf_sdcard_reg_write(sdiodev, 595 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 596 4, 1); 597 cc_data_temp = brcmf_sdcard_reg_read(sdiodev, 598 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4); 599 cc_data_temp &= ~str_mask; 600 drivestrength_sel <<= str_shift; 601 cc_data_temp |= drivestrength_sel; 602 brcmf_sdcard_reg_write(sdiodev, 603 CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 604 4, cc_data_temp); 605 606 brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", 607 drivestrength, cc_data_temp); 608 } 609} 610