linux/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
<<
>>
Prefs
   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#include <linux/types.h>
  19#include <linux/netdevice.h>
  20#include <linux/mmc/card.h>
  21#include <linux/ssb/ssb_regs.h>
  22#include <linux/bcma/bcma.h>
  23
  24#include <chipcommon.h>
  25#include <brcm_hw_ids.h>
  26#include <brcmu_wifi.h>
  27#include <brcmu_utils.h>
  28#include <soc.h>
  29#include "dhd_dbg.h"
  30#include "sdio_host.h"
  31#include "sdio_chip.h"
  32
  33/* chip core base & ramsize */
  34/* bcm4329 */
  35/* SDIO device core, ID 0x829 */
  36#define BCM4329_CORE_BUS_BASE           0x18011000
  37/* internal memory core, ID 0x80e */
  38#define BCM4329_CORE_SOCRAM_BASE        0x18003000
  39/* ARM Cortex M3 core, ID 0x82a */
  40#define BCM4329_CORE_ARM_BASE           0x18002000
  41#define BCM4329_RAMSIZE                 0x48000
  42
  43/* bcm43143 */
  44/* SDIO device core */
  45#define BCM43143_CORE_BUS_BASE          0x18002000
  46/* internal memory core */
  47#define BCM43143_CORE_SOCRAM_BASE       0x18004000
  48/* ARM Cortex M3 core, ID 0x82a */
  49#define BCM43143_CORE_ARM_BASE          0x18003000
  50#define BCM43143_RAMSIZE                0x70000
  51
  52#define SBCOREREV(sbidh) \
  53        ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
  54          ((sbidh) & SSB_IDHIGH_RCLO))
  55
  56/* SOC Interconnect types (aka chip types) */
  57#define SOCI_SB         0
  58#define SOCI_AI         1
  59
  60/* EROM CompIdentB */
  61#define CIB_REV_MASK            0xff000000
  62#define CIB_REV_SHIFT           24
  63
  64/* ARM CR4 core specific control flag bits */
  65#define ARMCR4_BCMA_IOCTL_CPUHALT       0x0020
  66
  67#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
  68/* SDIO Pad drive strength to select value mappings */
  69struct sdiod_drive_str {
  70        u8 strength;    /* Pad Drive Strength in mA */
  71        u8 sel;         /* Chip-specific select value */
  72};
  73/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
  74static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
  75        {32, 0x6},
  76        {26, 0x7},
  77        {22, 0x4},
  78        {16, 0x5},
  79        {12, 0x2},
  80        {8, 0x3},
  81        {4, 0x0},
  82        {0, 0x1}
  83};
  84
  85/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
  86static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
  87        {16, 0x7},
  88        {12, 0x5},
  89        {8,  0x3},
  90        {4,  0x1}
  91};
  92
  93u8
  94brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
  95{
  96        u8 idx;
  97
  98        for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
  99                if (coreid == ci->c_inf[idx].id)
 100                        return idx;
 101
 102        return BRCMF_MAX_CORENUM;
 103}
 104
 105static u32
 106brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
 107                      struct chip_info *ci, u16 coreid)
 108{
 109        u32 regdata;
 110        u8 idx;
 111
 112        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 113
 114        regdata = brcmf_sdio_regrl(sdiodev,
 115                                   CORE_SB(ci->c_inf[idx].base, sbidhigh),
 116                                   NULL);
 117        return SBCOREREV(regdata);
 118}
 119
 120static u32
 121brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
 122                      struct chip_info *ci, u16 coreid)
 123{
 124        u8 idx;
 125
 126        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 127
 128        return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
 129}
 130
 131static bool
 132brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
 133                       struct chip_info *ci, u16 coreid)
 134{
 135        u32 regdata;
 136        u8 idx;
 137
 138        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 139
 140        regdata = brcmf_sdio_regrl(sdiodev,
 141                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 142                                   NULL);
 143        regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
 144                    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
 145        return (SSB_TMSLOW_CLOCK == regdata);
 146}
 147
 148static bool
 149brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
 150                       struct chip_info *ci, u16 coreid)
 151{
 152        u32 regdata;
 153        u8 idx;
 154        bool ret;
 155
 156        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 157
 158        regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 159                                   NULL);
 160        ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
 161
 162        regdata = brcmf_sdio_regrl(sdiodev,
 163                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
 164                                   NULL);
 165        ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
 166
 167        return ret;
 168}
 169
 170static void
 171brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
 172                          struct chip_info *ci, u16 coreid, u32 core_bits)
 173{
 174        u32 regdata, base;
 175        u8 idx;
 176
 177        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 178        base = ci->c_inf[idx].base;
 179
 180        regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
 181        if (regdata & SSB_TMSLOW_RESET)
 182                return;
 183
 184        regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
 185        if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
 186                /*
 187                 * set target reject and spin until busy is clear
 188                 * (preserve core-specific bits)
 189                 */
 190                regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
 191                                           NULL);
 192                brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
 193                                 regdata | SSB_TMSLOW_REJECT, NULL);
 194
 195                regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
 196                                           NULL);
 197                udelay(1);
 198                SPINWAIT((brcmf_sdio_regrl(sdiodev,
 199                                           CORE_SB(base, sbtmstatehigh),
 200                                           NULL) &
 201                        SSB_TMSHIGH_BUSY), 100000);
 202
 203                regdata = brcmf_sdio_regrl(sdiodev,
 204                                           CORE_SB(base, sbtmstatehigh),
 205                                           NULL);
 206                if (regdata & SSB_TMSHIGH_BUSY)
 207                        brcmf_err("core state still busy\n");
 208
 209                regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
 210                                           NULL);
 211                if (regdata & SSB_IDLOW_INITIATOR) {
 212                        regdata = brcmf_sdio_regrl(sdiodev,
 213                                                   CORE_SB(base, sbimstate),
 214                                                   NULL);
 215                        regdata |= SSB_IMSTATE_REJECT;
 216                        brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
 217                                         regdata, NULL);
 218                        regdata = brcmf_sdio_regrl(sdiodev,
 219                                                   CORE_SB(base, sbimstate),
 220                                                   NULL);
 221                        udelay(1);
 222                        SPINWAIT((brcmf_sdio_regrl(sdiodev,
 223                                                   CORE_SB(base, sbimstate),
 224                                                   NULL) &
 225                                SSB_IMSTATE_BUSY), 100000);
 226                }
 227
 228                /* set reset and reject while enabling the clocks */
 229                regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
 230                          SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
 231                brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
 232                                 regdata, NULL);
 233                regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
 234                                           NULL);
 235                udelay(10);
 236
 237                /* clear the initiator reject bit */
 238                regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
 239                                           NULL);
 240                if (regdata & SSB_IDLOW_INITIATOR) {
 241                        regdata = brcmf_sdio_regrl(sdiodev,
 242                                                   CORE_SB(base, sbimstate),
 243                                                   NULL);
 244                        regdata &= ~SSB_IMSTATE_REJECT;
 245                        brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
 246                                         regdata, NULL);
 247                }
 248        }
 249
 250        /* leave reset and reject asserted */
 251        brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
 252                         (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
 253        udelay(1);
 254}
 255
 256static void
 257brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
 258                          struct chip_info *ci, u16 coreid, u32 core_bits)
 259{
 260        u8 idx;
 261        u32 regdata;
 262
 263        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 264
 265        /* if core is already in reset, just return */
 266        regdata = brcmf_sdio_regrl(sdiodev,
 267                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
 268                                   NULL);
 269        if ((regdata & BCMA_RESET_CTL_RESET) != 0)
 270                return;
 271
 272        /* ensure no pending backplane operation
 273         * 300uc should be sufficient for backplane ops to be finish
 274         * extra 10ms is taken into account for firmware load stage
 275         * after 10300us carry on disabling the core anyway
 276         */
 277        SPINWAIT(brcmf_sdio_regrl(sdiodev,
 278                                  ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
 279                                  NULL), 10300);
 280        regdata = brcmf_sdio_regrl(sdiodev,
 281                                   ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
 282                                   NULL);
 283        if (regdata)
 284                brcmf_err("disabling core 0x%x with reset status %x\n",
 285                          coreid, regdata);
 286
 287        brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
 288                         BCMA_RESET_CTL_RESET, NULL);
 289        udelay(1);
 290
 291        brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 292                         core_bits, NULL);
 293        regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 294                                   NULL);
 295        usleep_range(10, 20);
 296
 297}
 298
 299static void
 300brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
 301                        struct chip_info *ci, u16 coreid, u32 core_bits)
 302{
 303        u32 regdata;
 304        u8 idx;
 305
 306        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 307
 308        /*
 309         * Must do the disable sequence first to work for
 310         * arbitrary current core state.
 311         */
 312        brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
 313
 314        /*
 315         * Now do the initialization sequence.
 316         * set reset while enabling the clock and
 317         * forcing them on throughout the core
 318         */
 319        brcmf_sdio_regwl(sdiodev,
 320                         CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 321                         SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
 322                         NULL);
 323        regdata = brcmf_sdio_regrl(sdiodev,
 324                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 325                                   NULL);
 326        udelay(1);
 327
 328        /* clear any serror */
 329        regdata = brcmf_sdio_regrl(sdiodev,
 330                                   CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
 331                                   NULL);
 332        if (regdata & SSB_TMSHIGH_SERR)
 333                brcmf_sdio_regwl(sdiodev,
 334                                 CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
 335                                 0, NULL);
 336
 337        regdata = brcmf_sdio_regrl(sdiodev,
 338                                   CORE_SB(ci->c_inf[idx].base, sbimstate),
 339                                   NULL);
 340        if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
 341                brcmf_sdio_regwl(sdiodev,
 342                                 CORE_SB(ci->c_inf[idx].base, sbimstate),
 343                                 regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
 344                                 NULL);
 345
 346        /* clear reset and allow it to propagate throughout the core */
 347        brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 348                         SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
 349        regdata = brcmf_sdio_regrl(sdiodev,
 350                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 351                                   NULL);
 352        udelay(1);
 353
 354        /* leave clock enabled */
 355        brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 356                         SSB_TMSLOW_CLOCK, NULL);
 357        regdata = brcmf_sdio_regrl(sdiodev,
 358                                   CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
 359                                   NULL);
 360        udelay(1);
 361}
 362
 363static void
 364brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
 365                        struct chip_info *ci, u16 coreid, u32 core_bits)
 366{
 367        u8 idx;
 368        u32 regdata;
 369
 370        idx = brcmf_sdio_chip_getinfidx(ci, coreid);
 371
 372        /* must disable first to work for arbitrary current core state */
 373        brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
 374
 375        /* now do initialization sequence */
 376        brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 377                         core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
 378        regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 379                                   NULL);
 380        brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
 381                         0, NULL);
 382        regdata = brcmf_sdio_regrl(sdiodev,
 383                                   ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
 384                                   NULL);
 385        udelay(1);
 386
 387        brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 388                         core_bits | BCMA_IOCTL_CLK, NULL);
 389        regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
 390                                   NULL);
 391        udelay(1);
 392}
 393
 394#ifdef DEBUG
 395/* safety check for chipinfo */
 396static int brcmf_sdio_chip_cichk(struct chip_info *ci)
 397{
 398        u8 core_idx;
 399
 400        /* check RAM core presence for ARM CM3 core */
 401        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
 402        if (BRCMF_MAX_CORENUM != core_idx) {
 403                core_idx = brcmf_sdio_chip_getinfidx(ci,
 404                                                     BCMA_CORE_INTERNAL_MEM);
 405                if (BRCMF_MAX_CORENUM == core_idx) {
 406                        brcmf_err("RAM core not provided with ARM CM3 core\n");
 407                        return -ENODEV;
 408                }
 409        }
 410
 411        /* check RAM base for ARM CR4 core */
 412        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
 413        if (BRCMF_MAX_CORENUM != core_idx) {
 414                if (ci->rambase == 0) {
 415                        brcmf_err("RAM base not provided with ARM CR4 core\n");
 416                        return -ENOMEM;
 417                }
 418        }
 419
 420        return 0;
 421}
 422#else   /* DEBUG */
 423static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
 424{
 425        return 0;
 426}
 427#endif
 428
 429static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
 430                                       struct chip_info *ci, u32 regs)
 431{
 432        u32 regdata;
 433        int ret;
 434
 435        /* Get CC core rev
 436         * Chipid is assume to be at offset 0 from regs arg
 437         * For different chiptypes or old sdio hosts w/o chipcommon,
 438         * other ways of recognition should be added here.
 439         */
 440        ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
 441        ci->c_inf[0].base = regs;
 442        regdata = brcmf_sdio_regrl(sdiodev,
 443                                   CORE_CC_REG(ci->c_inf[0].base, chipid),
 444                                   NULL);
 445        ci->chip = regdata & CID_ID_MASK;
 446        ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
 447        ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
 448
 449        brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
 450
 451        /* Address of cores for new chips should be added here */
 452        switch (ci->chip) {
 453        case BCM43143_CHIP_ID:
 454                ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
 455                ci->c_inf[0].cib = 0x2b000000;
 456                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 457                ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
 458                ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
 459                ci->c_inf[1].cib = 0x18000000;
 460                ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
 461                ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
 462                ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
 463                ci->c_inf[2].cib = 0x14000000;
 464                ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
 465                ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
 466                ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
 467                ci->c_inf[3].cib = 0x07000000;
 468                ci->ramsize = BCM43143_RAMSIZE;
 469                break;
 470        case BCM43241_CHIP_ID:
 471                ci->c_inf[0].wrapbase = 0x18100000;
 472                ci->c_inf[0].cib = 0x2a084411;
 473                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 474                ci->c_inf[1].base = 0x18002000;
 475                ci->c_inf[1].wrapbase = 0x18102000;
 476                ci->c_inf[1].cib = 0x0e004211;
 477                ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
 478                ci->c_inf[2].base = 0x18004000;
 479                ci->c_inf[2].wrapbase = 0x18104000;
 480                ci->c_inf[2].cib = 0x14080401;
 481                ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
 482                ci->c_inf[3].base = 0x18003000;
 483                ci->c_inf[3].wrapbase = 0x18103000;
 484                ci->c_inf[3].cib = 0x07004211;
 485                ci->ramsize = 0x90000;
 486                break;
 487        case BCM4329_CHIP_ID:
 488                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 489                ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
 490                ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
 491                ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
 492                ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
 493                ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
 494                ci->ramsize = BCM4329_RAMSIZE;
 495                break;
 496        case BCM4330_CHIP_ID:
 497                ci->c_inf[0].wrapbase = 0x18100000;
 498                ci->c_inf[0].cib = 0x27004211;
 499                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 500                ci->c_inf[1].base = 0x18002000;
 501                ci->c_inf[1].wrapbase = 0x18102000;
 502                ci->c_inf[1].cib = 0x07004211;
 503                ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
 504                ci->c_inf[2].base = 0x18004000;
 505                ci->c_inf[2].wrapbase = 0x18104000;
 506                ci->c_inf[2].cib = 0x0d080401;
 507                ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
 508                ci->c_inf[3].base = 0x18003000;
 509                ci->c_inf[3].wrapbase = 0x18103000;
 510                ci->c_inf[3].cib = 0x03004211;
 511                ci->ramsize = 0x48000;
 512                break;
 513        case BCM4334_CHIP_ID:
 514                ci->c_inf[0].wrapbase = 0x18100000;
 515                ci->c_inf[0].cib = 0x29004211;
 516                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 517                ci->c_inf[1].base = 0x18002000;
 518                ci->c_inf[1].wrapbase = 0x18102000;
 519                ci->c_inf[1].cib = 0x0d004211;
 520                ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
 521                ci->c_inf[2].base = 0x18004000;
 522                ci->c_inf[2].wrapbase = 0x18104000;
 523                ci->c_inf[2].cib = 0x13080401;
 524                ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
 525                ci->c_inf[3].base = 0x18003000;
 526                ci->c_inf[3].wrapbase = 0x18103000;
 527                ci->c_inf[3].cib = 0x07004211;
 528                ci->ramsize = 0x80000;
 529                break;
 530        case BCM4335_CHIP_ID:
 531                ci->c_inf[0].wrapbase = 0x18100000;
 532                ci->c_inf[0].cib = 0x2b084411;
 533                ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
 534                ci->c_inf[1].base = 0x18005000;
 535                ci->c_inf[1].wrapbase = 0x18105000;
 536                ci->c_inf[1].cib = 0x0f004211;
 537                ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
 538                ci->c_inf[2].base = 0x18002000;
 539                ci->c_inf[2].wrapbase = 0x18102000;
 540                ci->c_inf[2].cib = 0x01084411;
 541                ci->ramsize = 0xc0000;
 542                ci->rambase = 0x180000;
 543                break;
 544        default:
 545                brcmf_err("chipid 0x%x is not supported\n", ci->chip);
 546                return -ENODEV;
 547        }
 548
 549        ret = brcmf_sdio_chip_cichk(ci);
 550        if (ret)
 551                return ret;
 552
 553        switch (ci->socitype) {
 554        case SOCI_SB:
 555                ci->iscoreup = brcmf_sdio_sb_iscoreup;
 556                ci->corerev = brcmf_sdio_sb_corerev;
 557                ci->coredisable = brcmf_sdio_sb_coredisable;
 558                ci->resetcore = brcmf_sdio_sb_resetcore;
 559                break;
 560        case SOCI_AI:
 561                ci->iscoreup = brcmf_sdio_ai_iscoreup;
 562                ci->corerev = brcmf_sdio_ai_corerev;
 563                ci->coredisable = brcmf_sdio_ai_coredisable;
 564                ci->resetcore = brcmf_sdio_ai_resetcore;
 565                break;
 566        default:
 567                brcmf_err("socitype %u not supported\n", ci->socitype);
 568                return -ENODEV;
 569        }
 570
 571        return 0;
 572}
 573
 574static int
 575brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
 576{
 577        int err = 0;
 578        u8 clkval, clkset;
 579
 580        /* Try forcing SDIO core to do ALPAvail request only */
 581        clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
 582        brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
 583        if (err) {
 584                brcmf_err("error writing for HT off\n");
 585                return err;
 586        }
 587
 588        /* If register supported, wait for ALPAvail and then force ALP */
 589        /* This may take up to 15 milliseconds */
 590        clkval = brcmf_sdio_regrb(sdiodev,
 591                                  SBSDIO_FUNC1_CHIPCLKCSR, NULL);
 592
 593        if ((clkval & ~SBSDIO_AVBITS) != clkset) {
 594                brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
 595                          clkset, clkval);
 596                return -EACCES;
 597        }
 598
 599        SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev,
 600                                             SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
 601                        !SBSDIO_ALPAV(clkval)),
 602                        PMU_MAX_TRANSITION_DLY);
 603        if (!SBSDIO_ALPAV(clkval)) {
 604                brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
 605                          clkval);
 606                return -EBUSY;
 607        }
 608
 609        clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
 610        brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
 611        udelay(65);
 612
 613        /* Also, disable the extra SDIO pull-ups */
 614        brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
 615
 616        return 0;
 617}
 618
 619static void
 620brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
 621                             struct chip_info *ci)
 622{
 623        u32 base = ci->c_inf[0].base;
 624
 625        /* get chipcommon rev */
 626        ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
 627
 628        /* get chipcommon capabilites */
 629        ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev,
 630                                             CORE_CC_REG(base, capabilities),
 631                                             NULL);
 632
 633        /* get pmu caps & rev */
 634        if (ci->c_inf[0].caps & CC_CAP_PMU) {
 635                ci->pmucaps =
 636                        brcmf_sdio_regrl(sdiodev,
 637                                         CORE_CC_REG(base, pmucapabilities),
 638                                         NULL);
 639                ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
 640        }
 641
 642        ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
 643
 644        brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
 645                  ci->c_inf[0].rev, ci->pmurev,
 646                  ci->c_inf[1].rev, ci->c_inf[1].id);
 647
 648        /*
 649         * Make sure any on-chip ARM is off (in case strapping is wrong),
 650         * or downloaded code was already running.
 651         */
 652        ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
 653}
 654
 655int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
 656                           struct chip_info **ci_ptr, u32 regs)
 657{
 658        int ret;
 659        struct chip_info *ci;
 660
 661        brcmf_dbg(TRACE, "Enter\n");
 662
 663        /* alloc chip_info_t */
 664        ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
 665        if (!ci)
 666                return -ENOMEM;
 667
 668        ret = brcmf_sdio_chip_buscoreprep(sdiodev);
 669        if (ret != 0)
 670                goto err;
 671
 672        ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
 673        if (ret != 0)
 674                goto err;
 675
 676        brcmf_sdio_chip_buscoresetup(sdiodev, ci);
 677
 678        brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
 679                         0, NULL);
 680        brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
 681                         0, NULL);
 682
 683        *ci_ptr = ci;
 684        return 0;
 685
 686err:
 687        kfree(ci);
 688        return ret;
 689}
 690
 691void
 692brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
 693{
 694        brcmf_dbg(TRACE, "Enter\n");
 695
 696        kfree(*ci_ptr);
 697        *ci_ptr = NULL;
 698}
 699
 700static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
 701{
 702        const char *fmt;
 703
 704        fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
 705        snprintf(buf, len, fmt, chipid);
 706        return buf;
 707}
 708
 709void
 710brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
 711                                  struct chip_info *ci, u32 drivestrength)
 712{
 713        const struct sdiod_drive_str *str_tab = NULL;
 714        u32 str_mask;
 715        u32 str_shift;
 716        char chn[8];
 717        u32 base = ci->c_inf[0].base;
 718        u32 i;
 719        u32 drivestrength_sel = 0;
 720        u32 cc_data_temp;
 721        u32 addr;
 722
 723        if (!(ci->c_inf[0].caps & CC_CAP_PMU))
 724                return;
 725
 726        switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
 727        case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
 728                str_tab = sdiod_drvstr_tab1_1v8;
 729                str_mask = 0x00003800;
 730                str_shift = 11;
 731                break;
 732        case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
 733                /* note: 43143 does not support tristate */
 734                i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
 735                if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
 736                        str_tab = sdiod_drvstr_tab2_3v3;
 737                        str_mask = 0x00000007;
 738                        str_shift = 0;
 739                } else
 740                        brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
 741                                  brcmf_sdio_chip_name(ci->chip, chn, 8),
 742                                  drivestrength);
 743                break;
 744        default:
 745                brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
 746                          brcmf_sdio_chip_name(ci->chip, chn, 8),
 747                          ci->chiprev, ci->pmurev);
 748                break;
 749        }
 750
 751        if (str_tab != NULL) {
 752                for (i = 0; str_tab[i].strength != 0; i++) {
 753                        if (drivestrength >= str_tab[i].strength) {
 754                                drivestrength_sel = str_tab[i].sel;
 755                                break;
 756                        }
 757                }
 758                addr = CORE_CC_REG(base, chipcontrol_addr);
 759                brcmf_sdio_regwl(sdiodev, addr, 1, NULL);
 760                cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL);
 761                cc_data_temp &= ~str_mask;
 762                drivestrength_sel <<= str_shift;
 763                cc_data_temp |= drivestrength_sel;
 764                brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL);
 765
 766                brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
 767                          str_tab[i].strength, drivestrength, cc_data_temp);
 768        }
 769}
 770
 771#ifdef DEBUG
 772static bool
 773brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
 774                            char *nvram_dat, uint nvram_sz)
 775{
 776        char *nvram_ularray;
 777        int err;
 778        bool ret = true;
 779
 780        /* read back and verify */
 781        brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
 782        nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
 783        /* do not proceed while no memory but  */
 784        if (!nvram_ularray)
 785                return true;
 786
 787        /* Upload image to verify downloaded contents. */
 788        memset(nvram_ularray, 0xaa, nvram_sz);
 789
 790        /* Read the vars list to temp buffer for comparison */
 791        err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
 792                               nvram_sz);
 793        if (err) {
 794                brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
 795                          err, nvram_sz, nvram_addr);
 796        } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
 797                brcmf_err("Downloaded NVRAM image is corrupted\n");
 798                ret = false;
 799        }
 800        kfree(nvram_ularray);
 801
 802        return ret;
 803}
 804#else   /* DEBUG */
 805static inline bool
 806brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
 807                            char *nvram_dat, uint nvram_sz)
 808{
 809        return true;
 810}
 811#endif  /* DEBUG */
 812
 813static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
 814                                       struct chip_info *ci,
 815                                       char *nvram_dat, uint nvram_sz)
 816{
 817        int err;
 818        u32 nvram_addr;
 819        u32 token;
 820        __le32 token_le;
 821
 822        nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
 823
 824        /* Write the vars list */
 825        err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
 826        if (err) {
 827                brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
 828                          err, nvram_sz, nvram_addr);
 829                return false;
 830        }
 831
 832        if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
 833                                         nvram_dat, nvram_sz))
 834                return false;
 835
 836        /* generate token:
 837         * nvram size, converted to words, in lower 16-bits, checksum
 838         * in upper 16-bits.
 839         */
 840        token = nvram_sz / 4;
 841        token = (~token << 16) | (token & 0x0000FFFF);
 842        token_le = cpu_to_le32(token);
 843
 844        brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
 845        brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
 846                  nvram_addr, nvram_sz, token);
 847
 848        /* Write the length token to the last word */
 849        if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
 850                             (u8 *)&token_le, 4))
 851                return false;
 852
 853        return true;
 854}
 855
 856static void
 857brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
 858                            struct chip_info *ci)
 859{
 860        u32 zeros = 0;
 861
 862        ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
 863        ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
 864
 865        /* clear length token */
 866        brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
 867}
 868
 869static bool
 870brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
 871                           char *nvram_dat, uint nvram_sz)
 872{
 873        u8 core_idx;
 874        u32 reg_addr;
 875
 876        if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
 877                brcmf_err("SOCRAM core is down after reset?\n");
 878                return false;
 879        }
 880
 881        if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
 882                return false;
 883
 884        /* clear all interrupts */
 885        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
 886        reg_addr = ci->c_inf[core_idx].base;
 887        reg_addr += offsetof(struct sdpcmd_regs, intstatus);
 888        brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
 889
 890        ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
 891
 892        return true;
 893}
 894
 895static inline void
 896brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
 897                            struct chip_info *ci)
 898{
 899        ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
 900                      ARMCR4_BCMA_IOCTL_CPUHALT);
 901}
 902
 903static bool
 904brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
 905                           char *nvram_dat, uint nvram_sz)
 906{
 907        u8 core_idx;
 908        u32 reg_addr;
 909
 910        if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
 911                return false;
 912
 913        /* clear all interrupts */
 914        core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
 915        reg_addr = ci->c_inf[core_idx].base;
 916        reg_addr += offsetof(struct sdpcmd_regs, intstatus);
 917        brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
 918
 919        /* Write reset vector to address 0 */
 920        brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
 921                         sizeof(ci->rst_vec));
 922
 923        /* restore ARM */
 924        ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
 925
 926        return true;
 927}
 928
 929void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
 930                                    struct chip_info *ci)
 931{
 932        u8 arm_core_idx;
 933
 934        arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
 935        if (BRCMF_MAX_CORENUM != arm_core_idx) {
 936                brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
 937                return;
 938        }
 939
 940        brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
 941}
 942
 943bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
 944                                   struct chip_info *ci, char *nvram_dat,
 945                                   uint nvram_sz)
 946{
 947        u8 arm_core_idx;
 948
 949        arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
 950        if (BRCMF_MAX_CORENUM != arm_core_idx)
 951                return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
 952                                                  nvram_sz);
 953
 954        return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
 955}
 956