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