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