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