linux/drivers/ssb/pcmcia.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * PCMCIA-Hostbus related functions
   4 *
   5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
   6 * Copyright 2007-2008 Michael Buesch <m@bues.ch>
   7 *
   8 * Licensed under the GNU/GPL. See COPYING for details.
   9 */
  10
  11#include <linux/ssb/ssb.h>
  12#include <linux/delay.h>
  13#include <linux/io.h>
  14#include <linux/etherdevice.h>
  15
  16#include <pcmcia/cistpl.h>
  17#include <pcmcia/ciscode.h>
  18#include <pcmcia/ds.h>
  19#include <pcmcia/cisreg.h>
  20
  21#include "ssb_private.h"
  22
  23
  24/* Define the following to 1 to enable a printk on each coreswitch. */
  25#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG              0
  26
  27
  28/* PCMCIA configuration registers */
  29#define SSB_PCMCIA_ADDRESS0             0x2E
  30#define SSB_PCMCIA_ADDRESS1             0x30
  31#define SSB_PCMCIA_ADDRESS2             0x32
  32#define SSB_PCMCIA_MEMSEG               0x34
  33#define SSB_PCMCIA_SPROMCTL             0x36
  34#define  SSB_PCMCIA_SPROMCTL_IDLE       0
  35#define  SSB_PCMCIA_SPROMCTL_WRITE      1
  36#define  SSB_PCMCIA_SPROMCTL_READ       2
  37#define  SSB_PCMCIA_SPROMCTL_WRITEEN    4
  38#define  SSB_PCMCIA_SPROMCTL_WRITEDIS   7
  39#define  SSB_PCMCIA_SPROMCTL_DONE       8
  40#define SSB_PCMCIA_SPROM_DATALO         0x38
  41#define SSB_PCMCIA_SPROM_DATAHI         0x3A
  42#define SSB_PCMCIA_SPROM_ADDRLO         0x3C
  43#define SSB_PCMCIA_SPROM_ADDRHI         0x3E
  44
  45/* Hardware invariants CIS tuples */
  46#define SSB_PCMCIA_CIS                  0x80
  47#define  SSB_PCMCIA_CIS_ID              0x01
  48#define  SSB_PCMCIA_CIS_BOARDREV        0x02
  49#define  SSB_PCMCIA_CIS_PA              0x03
  50#define   SSB_PCMCIA_CIS_PA_PA0B0_LO    0
  51#define   SSB_PCMCIA_CIS_PA_PA0B0_HI    1
  52#define   SSB_PCMCIA_CIS_PA_PA0B1_LO    2
  53#define   SSB_PCMCIA_CIS_PA_PA0B1_HI    3
  54#define   SSB_PCMCIA_CIS_PA_PA0B2_LO    4
  55#define   SSB_PCMCIA_CIS_PA_PA0B2_HI    5
  56#define   SSB_PCMCIA_CIS_PA_ITSSI       6
  57#define   SSB_PCMCIA_CIS_PA_MAXPOW      7
  58#define  SSB_PCMCIA_CIS_OEMNAME         0x04
  59#define  SSB_PCMCIA_CIS_CCODE           0x05
  60#define  SSB_PCMCIA_CIS_ANTENNA         0x06
  61#define  SSB_PCMCIA_CIS_ANTGAIN         0x07
  62#define  SSB_PCMCIA_CIS_BFLAGS          0x08
  63#define  SSB_PCMCIA_CIS_LEDS            0x09
  64
  65/* PCMCIA SPROM size. */
  66#define SSB_PCMCIA_SPROM_SIZE           256
  67#define SSB_PCMCIA_SPROM_SIZE_BYTES     (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
  68
  69
  70/* Write to a PCMCIA configuration register. */
  71static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
  72{
  73        int res;
  74
  75        res = pcmcia_write_config_byte(bus->host_pcmcia, offset, value);
  76        if (unlikely(res != 0))
  77                return -EBUSY;
  78
  79        return 0;
  80}
  81
  82/* Read from a PCMCIA configuration register. */
  83static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
  84{
  85        int res;
  86
  87        res = pcmcia_read_config_byte(bus->host_pcmcia, offset, value);
  88        if (unlikely(res != 0))
  89                return -EBUSY;
  90
  91        return 0;
  92}
  93
  94int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
  95                              u8 coreidx)
  96{
  97        int err;
  98        int attempts = 0;
  99        u32 cur_core;
 100        u32 addr;
 101        u32 read_addr;
 102        u8 val;
 103
 104        addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
 105        while (1) {
 106                err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
 107                                           (addr & 0x0000F000) >> 12);
 108                if (err)
 109                        goto error;
 110                err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
 111                                           (addr & 0x00FF0000) >> 16);
 112                if (err)
 113                        goto error;
 114                err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
 115                                           (addr & 0xFF000000) >> 24);
 116                if (err)
 117                        goto error;
 118
 119                read_addr = 0;
 120
 121                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
 122                if (err)
 123                        goto error;
 124                read_addr |= ((u32)(val & 0x0F)) << 12;
 125                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
 126                if (err)
 127                        goto error;
 128                read_addr |= ((u32)val) << 16;
 129                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
 130                if (err)
 131                        goto error;
 132                read_addr |= ((u32)val) << 24;
 133
 134                cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
 135                if (cur_core == coreidx)
 136                        break;
 137
 138                err = -ETIMEDOUT;
 139                if (attempts++ > SSB_BAR0_MAX_RETRIES)
 140                        goto error;
 141                udelay(10);
 142        }
 143
 144        return 0;
 145error:
 146        ssb_err("Failed to switch to core %u\n", coreidx);
 147        return err;
 148}
 149
 150static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
 151{
 152        int err;
 153
 154#if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
 155        ssb_info("Switching to %s core, index %d\n",
 156                 ssb_core_name(dev->id.coreid),
 157                 dev->core_index);
 158#endif
 159
 160        err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
 161        if (!err)
 162                bus->mapped_device = dev;
 163
 164        return err;
 165}
 166
 167int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
 168{
 169        int attempts = 0;
 170        int err;
 171        u8 val;
 172
 173        SSB_WARN_ON((seg != 0) && (seg != 1));
 174        while (1) {
 175                err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
 176                if (err)
 177                        goto error;
 178                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
 179                if (err)
 180                        goto error;
 181                if (val == seg)
 182                        break;
 183
 184                err = -ETIMEDOUT;
 185                if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
 186                        goto error;
 187                udelay(10);
 188        }
 189        bus->mapped_pcmcia_seg = seg;
 190
 191        return 0;
 192error:
 193        ssb_err("Failed to switch pcmcia segment\n");
 194        return err;
 195}
 196
 197static int select_core_and_segment(struct ssb_device *dev,
 198                                   u16 *offset)
 199{
 200        struct ssb_bus *bus = dev->bus;
 201        int err;
 202        u8 need_segment;
 203
 204        if (*offset >= 0x800) {
 205                *offset -= 0x800;
 206                need_segment = 1;
 207        } else
 208                need_segment = 0;
 209
 210        if (unlikely(dev != bus->mapped_device)) {
 211                err = ssb_pcmcia_switch_core(bus, dev);
 212                if (unlikely(err))
 213                        return err;
 214        }
 215        if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
 216                err = ssb_pcmcia_switch_segment(bus, need_segment);
 217                if (unlikely(err))
 218                        return err;
 219        }
 220
 221        return 0;
 222}
 223
 224static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
 225{
 226        struct ssb_bus *bus = dev->bus;
 227        unsigned long flags;
 228        int err;
 229        u8 value = 0xFF;
 230
 231        spin_lock_irqsave(&bus->bar_lock, flags);
 232        err = select_core_and_segment(dev, &offset);
 233        if (likely(!err))
 234                value = readb(bus->mmio + offset);
 235        spin_unlock_irqrestore(&bus->bar_lock, flags);
 236
 237        return value;
 238}
 239
 240static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
 241{
 242        struct ssb_bus *bus = dev->bus;
 243        unsigned long flags;
 244        int err;
 245        u16 value = 0xFFFF;
 246
 247        spin_lock_irqsave(&bus->bar_lock, flags);
 248        err = select_core_and_segment(dev, &offset);
 249        if (likely(!err))
 250                value = readw(bus->mmio + offset);
 251        spin_unlock_irqrestore(&bus->bar_lock, flags);
 252
 253        return value;
 254}
 255
 256static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
 257{
 258        struct ssb_bus *bus = dev->bus;
 259        unsigned long flags;
 260        int err;
 261        u32 lo = 0xFFFFFFFF, hi = 0xFFFFFFFF;
 262
 263        spin_lock_irqsave(&bus->bar_lock, flags);
 264        err = select_core_and_segment(dev, &offset);
 265        if (likely(!err)) {
 266                lo = readw(bus->mmio + offset);
 267                hi = readw(bus->mmio + offset + 2);
 268        }
 269        spin_unlock_irqrestore(&bus->bar_lock, flags);
 270
 271        return (lo | (hi << 16));
 272}
 273
 274#ifdef CONFIG_SSB_BLOCKIO
 275static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
 276                                  size_t count, u16 offset, u8 reg_width)
 277{
 278        struct ssb_bus *bus = dev->bus;
 279        unsigned long flags;
 280        void __iomem *addr = bus->mmio + offset;
 281        int err;
 282
 283        spin_lock_irqsave(&bus->bar_lock, flags);
 284        err = select_core_and_segment(dev, &offset);
 285        if (unlikely(err)) {
 286                memset(buffer, 0xFF, count);
 287                goto unlock;
 288        }
 289        switch (reg_width) {
 290        case sizeof(u8): {
 291                u8 *buf = buffer;
 292
 293                while (count) {
 294                        *buf = __raw_readb(addr);
 295                        buf++;
 296                        count--;
 297                }
 298                break;
 299        }
 300        case sizeof(u16): {
 301                __le16 *buf = buffer;
 302
 303                SSB_WARN_ON(count & 1);
 304                while (count) {
 305                        *buf = (__force __le16)__raw_readw(addr);
 306                        buf++;
 307                        count -= 2;
 308                }
 309                break;
 310        }
 311        case sizeof(u32): {
 312                __le16 *buf = buffer;
 313
 314                SSB_WARN_ON(count & 3);
 315                while (count) {
 316                        *buf = (__force __le16)__raw_readw(addr);
 317                        buf++;
 318                        *buf = (__force __le16)__raw_readw(addr + 2);
 319                        buf++;
 320                        count -= 4;
 321                }
 322                break;
 323        }
 324        default:
 325                SSB_WARN_ON(1);
 326        }
 327unlock:
 328        spin_unlock_irqrestore(&bus->bar_lock, flags);
 329}
 330#endif /* CONFIG_SSB_BLOCKIO */
 331
 332static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
 333{
 334        struct ssb_bus *bus = dev->bus;
 335        unsigned long flags;
 336        int err;
 337
 338        spin_lock_irqsave(&bus->bar_lock, flags);
 339        err = select_core_and_segment(dev, &offset);
 340        if (likely(!err))
 341                writeb(value, bus->mmio + offset);
 342        spin_unlock_irqrestore(&bus->bar_lock, flags);
 343}
 344
 345static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
 346{
 347        struct ssb_bus *bus = dev->bus;
 348        unsigned long flags;
 349        int err;
 350
 351        spin_lock_irqsave(&bus->bar_lock, flags);
 352        err = select_core_and_segment(dev, &offset);
 353        if (likely(!err))
 354                writew(value, bus->mmio + offset);
 355        spin_unlock_irqrestore(&bus->bar_lock, flags);
 356}
 357
 358static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
 359{
 360        struct ssb_bus *bus = dev->bus;
 361        unsigned long flags;
 362        int err;
 363
 364        spin_lock_irqsave(&bus->bar_lock, flags);
 365        err = select_core_and_segment(dev, &offset);
 366        if (likely(!err)) {
 367                writew((value & 0x0000FFFF), bus->mmio + offset);
 368                writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2);
 369        }
 370        spin_unlock_irqrestore(&bus->bar_lock, flags);
 371}
 372
 373#ifdef CONFIG_SSB_BLOCKIO
 374static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
 375                                   size_t count, u16 offset, u8 reg_width)
 376{
 377        struct ssb_bus *bus = dev->bus;
 378        unsigned long flags;
 379        void __iomem *addr = bus->mmio + offset;
 380        int err;
 381
 382        spin_lock_irqsave(&bus->bar_lock, flags);
 383        err = select_core_and_segment(dev, &offset);
 384        if (unlikely(err))
 385                goto unlock;
 386        switch (reg_width) {
 387        case sizeof(u8): {
 388                const u8 *buf = buffer;
 389
 390                while (count) {
 391                        __raw_writeb(*buf, addr);
 392                        buf++;
 393                        count--;
 394                }
 395                break;
 396        }
 397        case sizeof(u16): {
 398                const __le16 *buf = buffer;
 399
 400                SSB_WARN_ON(count & 1);
 401                while (count) {
 402                        __raw_writew((__force u16)(*buf), addr);
 403                        buf++;
 404                        count -= 2;
 405                }
 406                break;
 407        }
 408        case sizeof(u32): {
 409                const __le16 *buf = buffer;
 410
 411                SSB_WARN_ON(count & 3);
 412                while (count) {
 413                        __raw_writew((__force u16)(*buf), addr);
 414                        buf++;
 415                        __raw_writew((__force u16)(*buf), addr + 2);
 416                        buf++;
 417                        count -= 4;
 418                }
 419                break;
 420        }
 421        default:
 422                SSB_WARN_ON(1);
 423        }
 424unlock:
 425        spin_unlock_irqrestore(&bus->bar_lock, flags);
 426}
 427#endif /* CONFIG_SSB_BLOCKIO */
 428
 429/* Not "static", as it's used in main.c */
 430const struct ssb_bus_ops ssb_pcmcia_ops = {
 431        .read8          = ssb_pcmcia_read8,
 432        .read16         = ssb_pcmcia_read16,
 433        .read32         = ssb_pcmcia_read32,
 434        .write8         = ssb_pcmcia_write8,
 435        .write16        = ssb_pcmcia_write16,
 436        .write32        = ssb_pcmcia_write32,
 437#ifdef CONFIG_SSB_BLOCKIO
 438        .block_read     = ssb_pcmcia_block_read,
 439        .block_write    = ssb_pcmcia_block_write,
 440#endif
 441};
 442
 443static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
 444{
 445        unsigned int i;
 446        int err;
 447        u8 value;
 448
 449        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
 450        if (err)
 451                return err;
 452        for (i = 0; i < 1000; i++) {
 453                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
 454                if (err)
 455                        return err;
 456                if (value & SSB_PCMCIA_SPROMCTL_DONE)
 457                        return 0;
 458                udelay(10);
 459        }
 460
 461        return -ETIMEDOUT;
 462}
 463
 464/* offset is the 16bit word offset */
 465static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
 466{
 467        int err;
 468        u8 lo, hi;
 469
 470        offset *= 2; /* Make byte offset */
 471
 472        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
 473                                   (offset & 0x00FF));
 474        if (err)
 475                return err;
 476        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
 477                                   (offset & 0xFF00) >> 8);
 478        if (err)
 479                return err;
 480        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
 481        if (err)
 482                return err;
 483        err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
 484        if (err)
 485                return err;
 486        err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
 487        if (err)
 488                return err;
 489        *value = (lo | (((u16)hi) << 8));
 490
 491        return 0;
 492}
 493
 494/* offset is the 16bit word offset */
 495static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
 496{
 497        int err;
 498
 499        offset *= 2; /* Make byte offset */
 500
 501        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
 502                                   (offset & 0x00FF));
 503        if (err)
 504                return err;
 505        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
 506                                   (offset & 0xFF00) >> 8);
 507        if (err)
 508                return err;
 509        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
 510                                   (value & 0x00FF));
 511        if (err)
 512                return err;
 513        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
 514                                   (value & 0xFF00) >> 8);
 515        if (err)
 516                return err;
 517        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
 518        if (err)
 519                return err;
 520        msleep(20);
 521
 522        return 0;
 523}
 524
 525/* Read the SPROM image. bufsize is in 16bit words. */
 526static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
 527{
 528        int err, i;
 529
 530        for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
 531                err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
 532                if (err)
 533                        return err;
 534        }
 535
 536        return 0;
 537}
 538
 539/* Write the SPROM image. size is in 16bit words. */
 540static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
 541{
 542        int i, err;
 543        bool failed = 0;
 544        size_t size = SSB_PCMCIA_SPROM_SIZE;
 545
 546        ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 547        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
 548        if (err) {
 549                ssb_notice("Could not enable SPROM write access\n");
 550                return -EBUSY;
 551        }
 552        ssb_notice("[ 0%%");
 553        msleep(500);
 554        for (i = 0; i < size; i++) {
 555                if (i == size / 4)
 556                        ssb_cont("25%%");
 557                else if (i == size / 2)
 558                        ssb_cont("50%%");
 559                else if (i == (size * 3) / 4)
 560                        ssb_cont("75%%");
 561                else if (i % 2)
 562                        ssb_cont(".");
 563                err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
 564                if (err) {
 565                        ssb_notice("Failed to write to SPROM\n");
 566                        failed = 1;
 567                        break;
 568                }
 569        }
 570        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
 571        if (err) {
 572                ssb_notice("Could not disable SPROM write access\n");
 573                failed = 1;
 574        }
 575        msleep(500);
 576        if (!failed) {
 577                ssb_cont("100%% ]\n");
 578                ssb_notice("SPROM written\n");
 579        }
 580
 581        return failed ? -EBUSY : 0;
 582}
 583
 584static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
 585{
 586        //TODO
 587        return 0;
 588}
 589
 590#define GOTO_ERROR_ON(condition, description) do {      \
 591        if (unlikely(condition)) {                      \
 592                error_description = description;        \
 593                goto error;                             \
 594        }                                               \
 595  } while (0)
 596
 597static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,
 598                        tuple_t *tuple,
 599                        void *priv)
 600{
 601        struct ssb_sprom *sprom = priv;
 602
 603        if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
 604                return -EINVAL;
 605        if (tuple->TupleDataLen != ETH_ALEN + 2)
 606                return -EINVAL;
 607        if (tuple->TupleData[1] != ETH_ALEN)
 608                return -EINVAL;
 609        memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN);
 610        return 0;
 611};
 612
 613static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
 614                                        tuple_t *tuple,
 615                                        void *priv)
 616{
 617        struct ssb_init_invariants *iv = priv;
 618        struct ssb_sprom *sprom = &iv->sprom;
 619        struct ssb_boardinfo *bi = &iv->boardinfo;
 620        const char *error_description;
 621
 622        GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1");
 623        switch (tuple->TupleData[0]) {
 624        case SSB_PCMCIA_CIS_ID:
 625                GOTO_ERROR_ON((tuple->TupleDataLen != 5) &&
 626                              (tuple->TupleDataLen != 7),
 627                              "id tpl size");
 628                bi->vendor = tuple->TupleData[1] |
 629                        ((u16)tuple->TupleData[2] << 8);
 630                break;
 631        case SSB_PCMCIA_CIS_BOARDREV:
 632                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 633                        "boardrev tpl size");
 634                sprom->board_rev = tuple->TupleData[1];
 635                break;
 636        case SSB_PCMCIA_CIS_PA:
 637                GOTO_ERROR_ON((tuple->TupleDataLen != 9) &&
 638                        (tuple->TupleDataLen != 10),
 639                        "pa tpl size");
 640                sprom->pa0b0 = tuple->TupleData[1] |
 641                        ((u16)tuple->TupleData[2] << 8);
 642                sprom->pa0b1 = tuple->TupleData[3] |
 643                        ((u16)tuple->TupleData[4] << 8);
 644                sprom->pa0b2 = tuple->TupleData[5] |
 645                        ((u16)tuple->TupleData[6] << 8);
 646                sprom->itssi_a = tuple->TupleData[7];
 647                sprom->itssi_bg = tuple->TupleData[7];
 648                sprom->maxpwr_a = tuple->TupleData[8];
 649                sprom->maxpwr_bg = tuple->TupleData[8];
 650                break;
 651        case SSB_PCMCIA_CIS_OEMNAME:
 652                /* We ignore this. */
 653                break;
 654        case SSB_PCMCIA_CIS_CCODE:
 655                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 656                        "ccode tpl size");
 657                sprom->country_code = tuple->TupleData[1];
 658                break;
 659        case SSB_PCMCIA_CIS_ANTENNA:
 660                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 661                        "ant tpl size");
 662                sprom->ant_available_a = tuple->TupleData[1];
 663                sprom->ant_available_bg = tuple->TupleData[1];
 664                break;
 665        case SSB_PCMCIA_CIS_ANTGAIN:
 666                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 667                        "antg tpl size");
 668                sprom->antenna_gain.a0 = tuple->TupleData[1];
 669                sprom->antenna_gain.a1 = tuple->TupleData[1];
 670                sprom->antenna_gain.a2 = tuple->TupleData[1];
 671                sprom->antenna_gain.a3 = tuple->TupleData[1];
 672                break;
 673        case SSB_PCMCIA_CIS_BFLAGS:
 674                GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
 675                        (tuple->TupleDataLen != 5),
 676                        "bfl tpl size");
 677                sprom->boardflags_lo = tuple->TupleData[1] |
 678                        ((u16)tuple->TupleData[2] << 8);
 679                break;
 680        case SSB_PCMCIA_CIS_LEDS:
 681                GOTO_ERROR_ON(tuple->TupleDataLen != 5,
 682                        "leds tpl size");
 683                sprom->gpio0 = tuple->TupleData[1];
 684                sprom->gpio1 = tuple->TupleData[2];
 685                sprom->gpio2 = tuple->TupleData[3];
 686                sprom->gpio3 = tuple->TupleData[4];
 687                break;
 688        }
 689        return -ENOSPC; /* continue with next entry */
 690
 691error:
 692        ssb_err(
 693                   "PCMCIA: Failed to fetch device invariants: %s\n",
 694                   error_description);
 695        return -ENODEV;
 696}
 697
 698
 699int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
 700                              struct ssb_init_invariants *iv)
 701{
 702        struct ssb_sprom *sprom = &iv->sprom;
 703        int res;
 704
 705        memset(sprom, 0xFF, sizeof(*sprom));
 706        sprom->revision = 1;
 707        sprom->boardflags_lo = 0;
 708        sprom->boardflags_hi = 0;
 709
 710        /* First fetch the MAC address. */
 711        res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
 712                                ssb_pcmcia_get_mac, sprom);
 713        if (res != 0) {
 714                ssb_err(
 715                        "PCMCIA: Failed to fetch MAC address\n");
 716                return -ENODEV;
 717        }
 718
 719        /* Fetch the vendor specific tuples. */
 720        res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS,
 721                                ssb_pcmcia_do_get_invariants, iv);
 722        if ((res == 0) || (res == -ENOSPC))
 723                return 0;
 724
 725        ssb_err(
 726                        "PCMCIA: Failed to fetch device invariants\n");
 727        return -ENODEV;
 728}
 729
 730static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
 731                                          struct device_attribute *attr,
 732                                          char *buf)
 733{
 734        struct pcmcia_device *pdev =
 735                container_of(pcmciadev, struct pcmcia_device, dev);
 736        struct ssb_bus *bus;
 737
 738        bus = ssb_pcmcia_dev_to_bus(pdev);
 739        if (!bus)
 740                return -ENODEV;
 741
 742        return ssb_attr_sprom_show(bus, buf,
 743                                   ssb_pcmcia_sprom_read_all);
 744}
 745
 746static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
 747                                           struct device_attribute *attr,
 748                                           const char *buf, size_t count)
 749{
 750        struct pcmcia_device *pdev =
 751                container_of(pcmciadev, struct pcmcia_device, dev);
 752        struct ssb_bus *bus;
 753
 754        bus = ssb_pcmcia_dev_to_bus(pdev);
 755        if (!bus)
 756                return -ENODEV;
 757
 758        return ssb_attr_sprom_store(bus, buf, count,
 759                                    ssb_pcmcia_sprom_check_crc,
 760                                    ssb_pcmcia_sprom_write_all);
 761}
 762
 763static DEVICE_ATTR(ssb_sprom, 0600,
 764                   ssb_pcmcia_attr_sprom_show,
 765                   ssb_pcmcia_attr_sprom_store);
 766
 767static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
 768{
 769        u8 val;
 770        int err;
 771
 772        err = ssb_pcmcia_cfg_read(bus, cor, &val);
 773        if (err)
 774                return err;
 775        val &= ~COR_SOFT_RESET;
 776        val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
 777        err = ssb_pcmcia_cfg_write(bus, cor, val);
 778        if (err)
 779                return err;
 780        msleep(40);
 781
 782        return 0;
 783}
 784
 785/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
 786int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
 787{
 788        int err;
 789
 790        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 791                return 0;
 792
 793        /* Switch segment to a known state and sync
 794         * bus->mapped_pcmcia_seg with hardware state. */
 795        ssb_pcmcia_switch_segment(bus, 0);
 796        /* Init the COR register. */
 797        err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
 798        if (err)
 799                return err;
 800        /* Some cards also need this register to get poked. */
 801        err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
 802        if (err)
 803                return err;
 804
 805        return 0;
 806}
 807
 808void ssb_pcmcia_exit(struct ssb_bus *bus)
 809{
 810        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 811                return;
 812
 813        device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 814}
 815
 816int ssb_pcmcia_init(struct ssb_bus *bus)
 817{
 818        int err;
 819
 820        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 821                return 0;
 822
 823        err = ssb_pcmcia_hardware_setup(bus);
 824        if (err)
 825                goto error;
 826
 827        bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
 828        mutex_init(&bus->sprom_mutex);
 829        err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 830        if (err)
 831                goto error;
 832
 833        return 0;
 834error:
 835        ssb_err("Failed to initialize PCMCIA host device\n");
 836        return err;
 837}
 838