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