root/drivers/ssb/pcmcia.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssb_pcmcia_cfg_write
  2. ssb_pcmcia_cfg_read
  3. ssb_pcmcia_switch_coreidx
  4. ssb_pcmcia_switch_core
  5. ssb_pcmcia_switch_segment
  6. select_core_and_segment
  7. ssb_pcmcia_read8
  8. ssb_pcmcia_read16
  9. ssb_pcmcia_read32
  10. ssb_pcmcia_block_read
  11. ssb_pcmcia_write8
  12. ssb_pcmcia_write16
  13. ssb_pcmcia_write32
  14. ssb_pcmcia_block_write
  15. ssb_pcmcia_sprom_command
  16. ssb_pcmcia_sprom_read
  17. ssb_pcmcia_sprom_write
  18. ssb_pcmcia_sprom_read_all
  19. ssb_pcmcia_sprom_write_all
  20. ssb_pcmcia_sprom_check_crc
  21. ssb_pcmcia_get_mac
  22. ssb_pcmcia_do_get_invariants
  23. ssb_pcmcia_get_invariants
  24. ssb_pcmcia_attr_sprom_show
  25. ssb_pcmcia_attr_sprom_store
  26. ssb_pcmcia_cor_setup
  27. ssb_pcmcia_hardware_setup
  28. ssb_pcmcia_exit
  29. ssb_pcmcia_init

   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. */
  71 static 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. */
  83 static 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 
  94 int 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;
 145 error:
 146         pr_err("Failed to switch to core %u\n", coreidx);
 147         return err;
 148 }
 149 
 150 static 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 
 166 int 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;
 191 error:
 192         pr_err("Failed to switch pcmcia segment\n");
 193         return err;
 194 }
 195 
 196 static 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 
 223 static 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 
 239 static 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 
 255 static 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
 274 static 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         }
 326 unlock:
 327         spin_unlock_irqrestore(&bus->bar_lock, flags);
 328 }
 329 #endif /* CONFIG_SSB_BLOCKIO */
 330 
 331 static 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 
 344 static 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 
 357 static 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
 373 static 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         }
 423 unlock:
 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 */
 429 const 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 
 442 static 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 */
 464 static 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 */
 494 static 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. */
 525 static 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. */
 539 static 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 
 583 static 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 
 596 static 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 
 612 static 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 
 690 error:
 691         pr_err("PCMCIA: Failed to fetch device invariants: %s\n",
 692                error_description);
 693         return -ENODEV;
 694 }
 695 
 696 
 697 int 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 
 726 static ssize_t ssb_pcmcia_attr_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 
 742 static ssize_t ssb_pcmcia_attr_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 
 759 static DEVICE_ATTR(ssb_sprom, 0600,
 760                    ssb_pcmcia_attr_sprom_show,
 761                    ssb_pcmcia_attr_sprom_store);
 762 
 763 static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
 764 {
 765         u8 val;
 766         int err;
 767 
 768         err = ssb_pcmcia_cfg_read(bus, cor, &val);
 769         if (err)
 770                 return err;
 771         val &= ~COR_SOFT_RESET;
 772         val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
 773         err = ssb_pcmcia_cfg_write(bus, cor, val);
 774         if (err)
 775                 return err;
 776         msleep(40);
 777 
 778         return 0;
 779 }
 780 
 781 /* Initialize the PCMCIA hardware. This is called on Init and Resume. */
 782 int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
 783 {
 784         int err;
 785 
 786         if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 787                 return 0;
 788 
 789         /* Switch segment to a known state and sync
 790          * bus->mapped_pcmcia_seg with hardware state. */
 791         ssb_pcmcia_switch_segment(bus, 0);
 792         /* Init the COR register. */
 793         err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
 794         if (err)
 795                 return err;
 796         /* Some cards also need this register to get poked. */
 797         err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
 798         if (err)
 799                 return err;
 800 
 801         return 0;
 802 }
 803 
 804 void ssb_pcmcia_exit(struct ssb_bus *bus)
 805 {
 806         if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 807                 return;
 808 
 809         device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 810 }
 811 
 812 int ssb_pcmcia_init(struct ssb_bus *bus)
 813 {
 814         int err;
 815 
 816         if (bus->bustype != SSB_BUSTYPE_PCMCIA)
 817                 return 0;
 818 
 819         err = ssb_pcmcia_hardware_setup(bus);
 820         if (err)
 821                 goto error;
 822 
 823         bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
 824         mutex_init(&bus->sprom_mutex);
 825         err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
 826         if (err)
 827                 goto error;
 828 
 829         return 0;
 830 error:
 831         pr_err("Failed to initialize PCMCIA host device\n");
 832         return err;
 833 }

/* [<][>][^][v][top][bottom][index][help] */