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        mmiowb();
 343        spin_unlock_irqrestore(&bus->bar_lock, flags);
 344}
 345
 346static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 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                writew(value, bus->mmio + offset);
 356        mmiowb();
 357        spin_unlock_irqrestore(&bus->bar_lock, flags);
 358}
 359
 360static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 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 & 0x0000FFFF), bus->mmio + offset);
 370                writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2);
 371        }
 372        mmiowb();
 373        spin_unlock_irqrestore(&bus->bar_lock, flags);
 374}
 375
 376#ifdef CONFIG_SSB_BLOCKIO
 377static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
 378                                   size_t count, u16 offset, u8 reg_width)
 379{
 380        struct ssb_bus *bus = dev->bus;
 381        unsigned long flags;
 382        void __iomem *addr = bus->mmio + offset;
 383        int err;
 384
 385        spin_lock_irqsave(&bus->bar_lock, flags);
 386        err = select_core_and_segment(dev, &offset);
 387        if (unlikely(err))
 388                goto unlock;
 389        switch (reg_width) {
 390        case sizeof(u8): {
 391                const u8 *buf = buffer;
 392
 393                while (count) {
 394                        __raw_writeb(*buf, addr);
 395                        buf++;
 396                        count--;
 397                }
 398                break;
 399        }
 400        case sizeof(u16): {
 401                const __le16 *buf = buffer;
 402
 403                SSB_WARN_ON(count & 1);
 404                while (count) {
 405                        __raw_writew((__force u16)(*buf), addr);
 406                        buf++;
 407                        count -= 2;
 408                }
 409                break;
 410        }
 411        case sizeof(u32): {
 412                const __le16 *buf = buffer;
 413
 414                SSB_WARN_ON(count & 3);
 415                while (count) {
 416                        __raw_writew((__force u16)(*buf), addr);
 417                        buf++;
 418                        __raw_writew((__force u16)(*buf), addr + 2);
 419                        buf++;
 420                        count -= 4;
 421                }
 422                break;
 423        }
 424        default:
 425                SSB_WARN_ON(1);
 426        }
 427unlock:
 428        mmiowb();
 429        spin_unlock_irqrestore(&bus->bar_lock, flags);
 430}
 431#endif /* CONFIG_SSB_BLOCKIO */
 432
 433/* Not "static", as it's used in main.c */
 434const struct ssb_bus_ops ssb_pcmcia_ops = {
 435        .read8          = ssb_pcmcia_read8,
 436        .read16         = ssb_pcmcia_read16,
 437        .read32         = ssb_pcmcia_read32,
 438        .write8         = ssb_pcmcia_write8,
 439        .write16        = ssb_pcmcia_write16,
 440        .write32        = ssb_pcmcia_write32,
 441#ifdef CONFIG_SSB_BLOCKIO
 442        .block_read     = ssb_pcmcia_block_read,
 443        .block_write    = ssb_pcmcia_block_write,
 444#endif
 445};
 446
 447static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
 448{
 449        unsigned int i;
 450        int err;
 451        u8 value;
 452
 453        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
 454        if (err)
 455                return err;
 456        for (i = 0; i < 1000; i++) {
 457                err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
 458                if (err)
 459                        return err;
 460                if (value & SSB_PCMCIA_SPROMCTL_DONE)
 461                        return 0;
 462                udelay(10);
 463        }
 464
 465        return -ETIMEDOUT;
 466}
 467
 468/* offset is the 16bit word offset */
 469static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
 470{
 471        int err;
 472        u8 lo, hi;
 473
 474        offset *= 2; /* Make byte offset */
 475
 476        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
 477                                   (offset & 0x00FF));
 478        if (err)
 479                return err;
 480        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
 481                                   (offset & 0xFF00) >> 8);
 482        if (err)
 483                return err;
 484        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
 485        if (err)
 486                return err;
 487        err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
 488        if (err)
 489                return err;
 490        err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
 491        if (err)
 492                return err;
 493        *value = (lo | (((u16)hi) << 8));
 494
 495        return 0;
 496}
 497
 498/* offset is the 16bit word offset */
 499static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
 500{
 501        int err;
 502
 503        offset *= 2; /* Make byte offset */
 504
 505        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
 506                                   (offset & 0x00FF));
 507        if (err)
 508                return err;
 509        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
 510                                   (offset & 0xFF00) >> 8);
 511        if (err)
 512                return err;
 513        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
 514                                   (value & 0x00FF));
 515        if (err)
 516                return err;
 517        err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
 518                                   (value & 0xFF00) >> 8);
 519        if (err)
 520                return err;
 521        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
 522        if (err)
 523                return err;
 524        msleep(20);
 525
 526        return 0;
 527}
 528
 529/* Read the SPROM image. bufsize is in 16bit words. */
 530static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
 531{
 532        int err, i;
 533
 534        for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
 535                err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
 536                if (err)
 537                        return err;
 538        }
 539
 540        return 0;
 541}
 542
 543/* Write the SPROM image. size is in 16bit words. */
 544static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
 545{
 546        int i, err;
 547        bool failed = 0;
 548        size_t size = SSB_PCMCIA_SPROM_SIZE;
 549
 550        ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 551        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
 552        if (err) {
 553                ssb_notice("Could not enable SPROM write access\n");
 554                return -EBUSY;
 555        }
 556        ssb_notice("[ 0%%");
 557        msleep(500);
 558        for (i = 0; i < size; i++) {
 559                if (i == size / 4)
 560                        ssb_cont("25%%");
 561                else if (i == size / 2)
 562                        ssb_cont("50%%");
 563                else if (i == (size * 3) / 4)
 564                        ssb_cont("75%%");
 565                else if (i % 2)
 566                        ssb_cont(".");
 567                err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
 568                if (err) {
 569                        ssb_notice("Failed to write to SPROM\n");
 570                        failed = 1;
 571                        break;
 572                }
 573        }
 574        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
 575        if (err) {
 576                ssb_notice("Could not disable SPROM write access\n");
 577                failed = 1;
 578        }
 579        msleep(500);
 580        if (!failed) {
 581                ssb_cont("100%% ]\n");
 582                ssb_notice("SPROM written\n");
 583        }
 584
 585        return failed ? -EBUSY : 0;
 586}
 587
 588static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
 589{
 590        //TODO
 591        return 0;
 592}
 593
 594#define GOTO_ERROR_ON(condition, description) do {      \
 595        if (unlikely(condition)) {                      \
 596                error_description = description;        \
 597                goto error;                             \
 598        }                                               \
 599  } while (0)
 600
 601static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,
 602                        tuple_t *tuple,
 603                        void *priv)
 604{
 605        struct ssb_sprom *sprom = priv;
 606
 607        if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
 608                return -EINVAL;
 609        if (tuple->TupleDataLen != ETH_ALEN + 2)
 610                return -EINVAL;
 611        if (tuple->TupleData[1] != ETH_ALEN)
 612                return -EINVAL;
 613        memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN);
 614        return 0;
 615};
 616
 617static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
 618                                        tuple_t *tuple,
 619                                        void *priv)
 620{
 621        struct ssb_init_invariants *iv = priv;
 622        struct ssb_sprom *sprom = &iv->sprom;
 623        struct ssb_boardinfo *bi = &iv->boardinfo;
 624        const char *error_description;
 625
 626        GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1");
 627        switch (tuple->TupleData[0]) {
 628        case SSB_PCMCIA_CIS_ID:
 629                GOTO_ERROR_ON((tuple->TupleDataLen != 5) &&
 630                              (tuple->TupleDataLen != 7),
 631                              "id tpl size");
 632                bi->vendor = tuple->TupleData[1] |
 633                        ((u16)tuple->TupleData[2] << 8);
 634                break;
 635        case SSB_PCMCIA_CIS_BOARDREV:
 636                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 637                        "boardrev tpl size");
 638                sprom->board_rev = tuple->TupleData[1];
 639                break;
 640        case SSB_PCMCIA_CIS_PA:
 641                GOTO_ERROR_ON((tuple->TupleDataLen != 9) &&
 642                        (tuple->TupleDataLen != 10),
 643                        "pa tpl size");
 644                sprom->pa0b0 = tuple->TupleData[1] |
 645                        ((u16)tuple->TupleData[2] << 8);
 646                sprom->pa0b1 = tuple->TupleData[3] |
 647                        ((u16)tuple->TupleData[4] << 8);
 648                sprom->pa0b2 = tuple->TupleData[5] |
 649                        ((u16)tuple->TupleData[6] << 8);
 650                sprom->itssi_a = tuple->TupleData[7];
 651                sprom->itssi_bg = tuple->TupleData[7];
 652                sprom->maxpwr_a = tuple->TupleData[8];
 653                sprom->maxpwr_bg = tuple->TupleData[8];
 654                break;
 655        case SSB_PCMCIA_CIS_OEMNAME:
 656                /* We ignore this. */
 657                break;
 658        case SSB_PCMCIA_CIS_CCODE:
 659                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 660                        "ccode tpl size");
 661                sprom->country_code = tuple->TupleData[1];
 662                break;
 663        case SSB_PCMCIA_CIS_ANTENNA:
 664                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 665                        "ant tpl size");
 666                sprom->ant_available_a = tuple->TupleData[1];
 667                sprom->ant_available_bg = tuple->TupleData[1];
 668                break;
 669        case SSB_PCMCIA_CIS_ANTGAIN:
 670                GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 671                        "antg tpl size");
 672                sprom->antenna_gain.a0 = tuple->TupleData[1];
 673                sprom->antenna_gain.a1 = tuple->TupleData[1];
 674                sprom->antenna_gain.a2 = tuple->TupleData[1];
 675                sprom->antenna_gain.a3 = tuple->TupleData[1];
 676                break;
 677        case SSB_PCMCIA_CIS_BFLAGS:
 678                GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
 679                        (tuple->TupleDataLen != 5),
 680                        "bfl tpl size");
 681                sprom->boardflags_lo = tuple->TupleData[1] |
 682                        ((u16)tuple->TupleData[2] << 8);
 683                break;
 684        case SSB_PCMCIA_CIS_LEDS:
 685                GOTO_ERROR_ON(tuple->TupleDataLen != 5,
 686                        "leds tpl size");
 687                sprom->gpio0 = tuple->TupleData[1];
 688                sprom->gpio1 = tuple->TupleData[2];
 689                sprom->gpio2 = tuple->TupleData[3];
 690                sprom->gpio3 = tuple->TupleData[4];
 691                break;
 692        }
 693        return -ENOSPC; /* continue with next entry */
 694
 695error:
 696        ssb_err(
 697                   "PCMCIA: Failed to fetch device invariants: %s\n",
 698                   error_description);
 699        return -ENODEV;
 700}
 701
 702
 703int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
 704                              struct ssb_init_invariants *iv)
 705{
 706        struct ssb_sprom *sprom = &iv->sprom;
 707        int res;
 708
 709        memset(sprom, 0xFF, sizeof(*sprom));
 710        sprom->revision = 1;
 711        sprom->boardflags_lo = 0;
 712        sprom->boardflags_hi = 0;
 713
 714        /* First fetch the MAC address. */
 715        res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
 716                                ssb_pcmcia_get_mac, sprom);
 717        if (res != 0) {
 718                ssb_err(
 719                        "PCMCIA: Failed to fetch MAC address\n");
 720                return -ENODEV;
 721        }
 722
 723        /* Fetch the vendor specific tuples. */
 724        res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS,
 725                                ssb_pcmcia_do_get_invariants, iv);
 726        if ((res == 0) || (res == -ENOSPC))
 727                return 0;
 728
 729        ssb_err(
 730                        "PCMCIA: Failed to fetch device invariants\n");
 731        return -ENODEV;
 732}
 733
 734static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
 735                                          struct device_attribute *attr,
 736                                          char *buf)
 737{
 738        struct pcmcia_device *pdev =
 739                container_of(pcmciadev, struct pcmcia_device, dev);
 740        struct ssb_bus *bus;
 741
 742        bus = ssb_pcmcia_dev_to_bus(pdev);
 743        if (!bus)
 744                return -ENODEV;
 745
 746        return ssb_attr_sprom_show(bus, buf,
 747                                   ssb_pcmcia_sprom_read_all);
 748}
 749
 750static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
 751                                           struct device_attribute *attr,
 752                                           const char *buf, size_t count)
 753{
 754        struct pcmcia_device *pdev =
 755                container_of(pcmciadev, struct pcmcia_device, dev);
 756        struct ssb_bus *bus;
 757
 758        bus = ssb_pcmcia_dev_to_bus(pdev);
 759        if (!bus)
 760                return -ENODEV;
 761
 762        return ssb_attr_sprom_store(bus, buf, count,
 763                                    ssb_pcmcia_sprom_check_crc,
 764                                    ssb_pcmcia_sprom_write_all);
 765}
 766
 767static DEVICE_ATTR(ssb_sprom, 0600,
 768                   ssb_pcmcia_attr_sprom_show,
 769                   ssb_pcmcia_attr_sprom_store);
 770
 771static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
 772{
 773        u8 val;
 774        int err;
 775
 776        err = ssb_pcmcia_cfg_read(bus, cor, &val);
 777        if (err)
 778                return err;
 779        val &= ~COR_SOFT_RESET;
 780        val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
 781        err = ssb_pcmcia_cfg_write(bus, cor, val);
 782        if (err)
 783                return err;
 784        msleep(40);
 785
 786        return 0;
 787}
 788
 789/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
 790int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
 791{
 792        int err;
 793
 794        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 795                return 0;
 796
 797        /* Switch segment to a known state and sync
 798         * bus->mapped_pcmcia_seg with hardware state. */
 799        ssb_pcmcia_switch_segment(bus, 0);
 800        /* Init the COR register. */
 801        err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
 802        if (err)
 803                return err;
 804        /* Some cards also need this register to get poked. */
 805        err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
 806        if (err)
 807                return err;
 808
 809        return 0;
 810}
 811
 812void ssb_pcmcia_exit(struct ssb_bus *bus)
 813{
 814        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 815                return;
 816
 817        device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 818}
 819
 820int ssb_pcmcia_init(struct ssb_bus *bus)
 821{
 822        int err;
 823
 824        if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 825                return 0;
 826
 827        err = ssb_pcmcia_hardware_setup(bus);
 828        if (err)
 829                goto error;
 830
 831        bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
 832        mutex_init(&bus->sprom_mutex);
 833        err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 834        if (err)
 835                goto error;
 836
 837        return 0;
 838error:
 839        ssb_err("Failed to initialize PCMCIA host device\n");
 840        return err;
 841}
 842