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