diff options
Diffstat (limited to 'drivers/ssb')
| -rw-r--r-- | drivers/ssb/main.c | 30 | ||||
| -rw-r--r-- | drivers/ssb/pci.c | 96 | ||||
| -rw-r--r-- | drivers/ssb/pcihost_wrapper.c | 7 |
3 files changed, 105 insertions, 28 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index c68b3dc19e11..3918d2cc5856 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
| @@ -383,6 +383,35 @@ static int ssb_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 383 | ssb_dev->id.revision); | 383 | ssb_dev->id.revision); |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | #define ssb_config_attr(attrib, field, format_string) \ | ||
| 387 | static ssize_t \ | ||
| 388 | attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 389 | { \ | ||
| 390 | return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \ | ||
| 391 | } | ||
| 392 | |||
| 393 | ssb_config_attr(core_num, core_index, "%u\n") | ||
| 394 | ssb_config_attr(coreid, id.coreid, "0x%04x\n") | ||
| 395 | ssb_config_attr(vendor, id.vendor, "0x%04x\n") | ||
| 396 | ssb_config_attr(revision, id.revision, "%u\n") | ||
| 397 | ssb_config_attr(irq, irq, "%u\n") | ||
| 398 | static ssize_t | ||
| 399 | name_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 400 | { | ||
| 401 | return sprintf(buf, "%s\n", | ||
| 402 | ssb_core_name(dev_to_ssb_dev(dev)->id.coreid)); | ||
| 403 | } | ||
| 404 | |||
| 405 | static struct device_attribute ssb_device_attrs[] = { | ||
| 406 | __ATTR_RO(name), | ||
| 407 | __ATTR_RO(core_num), | ||
| 408 | __ATTR_RO(coreid), | ||
| 409 | __ATTR_RO(vendor), | ||
| 410 | __ATTR_RO(revision), | ||
| 411 | __ATTR_RO(irq), | ||
| 412 | __ATTR_NULL, | ||
| 413 | }; | ||
| 414 | |||
| 386 | static struct bus_type ssb_bustype = { | 415 | static struct bus_type ssb_bustype = { |
| 387 | .name = "ssb", | 416 | .name = "ssb", |
| 388 | .match = ssb_bus_match, | 417 | .match = ssb_bus_match, |
| @@ -392,6 +421,7 @@ static struct bus_type ssb_bustype = { | |||
| 392 | .suspend = ssb_device_suspend, | 421 | .suspend = ssb_device_suspend, |
| 393 | .resume = ssb_device_resume, | 422 | .resume = ssb_device_resume, |
| 394 | .uevent = ssb_device_uevent, | 423 | .uevent = ssb_device_uevent, |
| 424 | .dev_attrs = ssb_device_attrs, | ||
| 395 | }; | 425 | }; |
| 396 | 426 | ||
| 397 | static void ssb_buses_lock(void) | 427 | static void ssb_buses_lock(void) |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 6e88d2b603b4..158449e55044 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
| @@ -406,6 +406,46 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
| 406 | out->antenna_gain.ghz5.a3 = gain; | 406 | out->antenna_gain.ghz5.a3 = gain; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | /* Revs 4 5 and 8 have partially shared layout */ | ||
| 410 | static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) | ||
| 411 | { | ||
| 412 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, | ||
| 413 | SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); | ||
| 414 | SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, | ||
| 415 | SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); | ||
| 416 | SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, | ||
| 417 | SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); | ||
| 418 | SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, | ||
| 419 | SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); | ||
| 420 | |||
| 421 | SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, | ||
| 422 | SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); | ||
| 423 | SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, | ||
| 424 | SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); | ||
| 425 | SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, | ||
| 426 | SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); | ||
| 427 | SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, | ||
| 428 | SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); | ||
| 429 | |||
| 430 | SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, | ||
| 431 | SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); | ||
| 432 | SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, | ||
| 433 | SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); | ||
| 434 | SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, | ||
| 435 | SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); | ||
| 436 | SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, | ||
| 437 | SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); | ||
| 438 | |||
| 439 | SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, | ||
| 440 | SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); | ||
| 441 | SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, | ||
| 442 | SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); | ||
| 443 | SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, | ||
| 444 | SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); | ||
| 445 | SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, | ||
| 446 | SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); | ||
| 447 | } | ||
| 448 | |||
| 409 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | 449 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
| 410 | { | 450 | { |
| 411 | int i; | 451 | int i; |
| @@ -471,6 +511,8 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
| 471 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, | 511 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, |
| 472 | sizeof(out->antenna_gain.ghz5)); | 512 | sizeof(out->antenna_gain.ghz5)); |
| 473 | 513 | ||
| 514 | sprom_extract_r458(out, in); | ||
| 515 | |||
| 474 | /* TODO - get remaining rev 4 stuff needed */ | 516 | /* TODO - get remaining rev 4 stuff needed */ |
| 475 | } | 517 | } |
| 476 | 518 | ||
| @@ -561,6 +603,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
| 561 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, | 603 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, |
| 562 | sizeof(out->antenna_gain.ghz5)); | 604 | sizeof(out->antenna_gain.ghz5)); |
| 563 | 605 | ||
| 606 | sprom_extract_r458(out, in); | ||
| 607 | |||
| 564 | /* TODO - get remaining rev 8 stuff needed */ | 608 | /* TODO - get remaining rev 8 stuff needed */ |
| 565 | } | 609 | } |
| 566 | 610 | ||
| @@ -573,37 +617,34 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
| 573 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); | 617 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); |
| 574 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ | 618 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ |
| 575 | memset(out->et1mac, 0xFF, 6); | 619 | memset(out->et1mac, 0xFF, 6); |
| 620 | |||
| 576 | if ((bus->chip_id & 0xFF00) == 0x4400) { | 621 | if ((bus->chip_id & 0xFF00) == 0x4400) { |
| 577 | /* Workaround: The BCM44XX chip has a stupid revision | 622 | /* Workaround: The BCM44XX chip has a stupid revision |
| 578 | * number stored in the SPROM. | 623 | * number stored in the SPROM. |
| 579 | * Always extract r1. */ | 624 | * Always extract r1. */ |
| 580 | out->revision = 1; | 625 | out->revision = 1; |
| 626 | ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); | ||
| 627 | } | ||
| 628 | |||
| 629 | switch (out->revision) { | ||
| 630 | case 1: | ||
| 631 | case 2: | ||
| 632 | case 3: | ||
| 581 | sprom_extract_r123(out, in); | 633 | sprom_extract_r123(out, in); |
| 582 | } else if (bus->chip_id == 0x4321) { | 634 | break; |
| 583 | /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ | 635 | case 4: |
| 584 | out->revision = 4; | 636 | case 5: |
| 585 | sprom_extract_r45(out, in); | 637 | sprom_extract_r45(out, in); |
| 586 | } else { | 638 | break; |
| 587 | switch (out->revision) { | 639 | case 8: |
| 588 | case 1: | 640 | sprom_extract_r8(out, in); |
| 589 | case 2: | 641 | break; |
| 590 | case 3: | 642 | default: |
| 591 | sprom_extract_r123(out, in); | 643 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" |
| 592 | break; | 644 | " revision %d detected. Will extract" |
| 593 | case 4: | 645 | " v1\n", out->revision); |
| 594 | case 5: | 646 | out->revision = 1; |
| 595 | sprom_extract_r45(out, in); | 647 | sprom_extract_r123(out, in); |
| 596 | break; | ||
| 597 | case 8: | ||
| 598 | sprom_extract_r8(out, in); | ||
| 599 | break; | ||
| 600 | default: | ||
| 601 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" | ||
| 602 | " revision %d detected. Will extract" | ||
| 603 | " v1\n", out->revision); | ||
| 604 | out->revision = 1; | ||
| 605 | sprom_extract_r123(out, in); | ||
| 606 | } | ||
| 607 | } | 648 | } |
| 608 | 649 | ||
| 609 | if (out->boardflags_lo == 0xFFFF) | 650 | if (out->boardflags_lo == 0xFFFF) |
| @@ -618,7 +659,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
| 618 | struct ssb_sprom *sprom) | 659 | struct ssb_sprom *sprom) |
| 619 | { | 660 | { |
| 620 | const struct ssb_sprom *fallback; | 661 | const struct ssb_sprom *fallback; |
| 621 | int err = -ENOMEM; | 662 | int err; |
| 622 | u16 *buf; | 663 | u16 *buf; |
| 623 | 664 | ||
| 624 | if (!ssb_is_sprom_available(bus)) { | 665 | if (!ssb_is_sprom_available(bus)) { |
| @@ -645,7 +686,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
| 645 | 686 | ||
| 646 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); | 687 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
| 647 | if (!buf) | 688 | if (!buf) |
| 648 | goto out; | 689 | return -ENOMEM; |
| 649 | bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; | 690 | bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; |
| 650 | sprom_do_read(bus, buf); | 691 | sprom_do_read(bus, buf); |
| 651 | err = sprom_check_crc(buf, bus->sprom_size); | 692 | err = sprom_check_crc(buf, bus->sprom_size); |
| @@ -655,7 +696,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
| 655 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), | 696 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), |
| 656 | GFP_KERNEL); | 697 | GFP_KERNEL); |
| 657 | if (!buf) | 698 | if (!buf) |
| 658 | goto out; | 699 | return -ENOMEM; |
| 659 | bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; | 700 | bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; |
| 660 | sprom_do_read(bus, buf); | 701 | sprom_do_read(bus, buf); |
| 661 | err = sprom_check_crc(buf, bus->sprom_size); | 702 | err = sprom_check_crc(buf, bus->sprom_size); |
| @@ -677,7 +718,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
| 677 | 718 | ||
| 678 | out_free: | 719 | out_free: |
| 679 | kfree(buf); | 720 | kfree(buf); |
| 680 | out: | ||
| 681 | return err; | 721 | return err; |
| 682 | } | 722 | } |
| 683 | 723 | ||
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c index 6536a041d90d..f6c8c81a0025 100644 --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c | |||
| @@ -59,6 +59,7 @@ static int ssb_pcihost_probe(struct pci_dev *dev, | |||
| 59 | struct ssb_bus *ssb; | 59 | struct ssb_bus *ssb; |
| 60 | int err = -ENOMEM; | 60 | int err = -ENOMEM; |
| 61 | const char *name; | 61 | const char *name; |
| 62 | u32 val; | ||
| 62 | 63 | ||
| 63 | ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); | 64 | ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); |
| 64 | if (!ssb) | 65 | if (!ssb) |
| @@ -74,6 +75,12 @@ static int ssb_pcihost_probe(struct pci_dev *dev, | |||
| 74 | goto err_pci_disable; | 75 | goto err_pci_disable; |
| 75 | pci_set_master(dev); | 76 | pci_set_master(dev); |
| 76 | 77 | ||
| 78 | /* Disable the RETRY_TIMEOUT register (0x41) to keep | ||
| 79 | * PCI Tx retries from interfering with C3 CPU state */ | ||
| 80 | pci_read_config_dword(dev, 0x40, &val); | ||
| 81 | if ((val & 0x0000ff00) != 0) | ||
| 82 | pci_write_config_dword(dev, 0x40, val & 0xffff00ff); | ||
| 83 | |||
| 77 | err = ssb_bus_pcibus_register(ssb, dev); | 84 | err = ssb_bus_pcibus_register(ssb, dev); |
| 78 | if (err) | 85 | if (err) |
| 79 | goto err_pci_release_regions; | 86 | goto err_pci_release_regions; |
