diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
commit | 252f4bf400df1712408fe83ba199a66a1b57ab1d (patch) | |
tree | e07fa00abdd55b31e22567786c78635f32c6a66c /drivers/ssb | |
parent | 6ba1037c3d871ab70e342631516dbf841c35b086 (diff) | |
parent | b37e3b6d64358604960b35e8ecbb7aed22e0926e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/phy.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/driver_pcicore.c | 104 | ||||
-rw-r--r-- | drivers/ssb/scan.c | 2 |
2 files changed, 101 insertions, 5 deletions
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 0e8d35224614..1ba9f0ee6f94 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -15,6 +15,11 @@ | |||
15 | 15 | ||
16 | #include "ssb_private.h" | 16 | #include "ssb_private.h" |
17 | 17 | ||
18 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address); | ||
19 | static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data); | ||
20 | static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); | ||
21 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | ||
22 | u8 address, u16 data); | ||
18 | 23 | ||
19 | static inline | 24 | static inline |
20 | u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) | 25 | u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) |
@@ -403,6 +408,27 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) | |||
403 | } | 408 | } |
404 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ | 409 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ |
405 | 410 | ||
411 | /************************************************** | ||
412 | * Workarounds. | ||
413 | **************************************************/ | ||
414 | |||
415 | static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) | ||
416 | { | ||
417 | return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; | ||
418 | } | ||
419 | |||
420 | static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) | ||
421 | { | ||
422 | const u8 serdes_pll_device = 0x1D; | ||
423 | const u8 serdes_rx_device = 0x1F; | ||
424 | u16 tmp; | ||
425 | |||
426 | ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, | ||
427 | ssb_pcicore_polarity_workaround(pc)); | ||
428 | tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); | ||
429 | if (tmp & 0x4000) | ||
430 | ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); | ||
431 | } | ||
406 | 432 | ||
407 | /************************************************** | 433 | /************************************************** |
408 | * Generic and Clientmode operation code. | 434 | * Generic and Clientmode operation code. |
@@ -417,11 +443,9 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) | |||
417 | void ssb_pcicore_init(struct ssb_pcicore *pc) | 443 | void ssb_pcicore_init(struct ssb_pcicore *pc) |
418 | { | 444 | { |
419 | struct ssb_device *dev = pc->dev; | 445 | struct ssb_device *dev = pc->dev; |
420 | struct ssb_bus *bus; | ||
421 | 446 | ||
422 | if (!dev) | 447 | if (!dev) |
423 | return; | 448 | return; |
424 | bus = dev->bus; | ||
425 | if (!ssb_device_is_enabled(dev)) | 449 | if (!ssb_device_is_enabled(dev)) |
426 | ssb_device_enable(dev, 0); | 450 | ssb_device_enable(dev, 0); |
427 | 451 | ||
@@ -432,6 +456,8 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) | |||
432 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ | 456 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ |
433 | if (!pc->hostmode) | 457 | if (!pc->hostmode) |
434 | ssb_pcicore_init_clientmode(pc); | 458 | ssb_pcicore_init_clientmode(pc); |
459 | |||
460 | ssb_pcicore_serdes_workaround(pc); | ||
435 | } | 461 | } |
436 | 462 | ||
437 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) | 463 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) |
@@ -446,11 +472,75 @@ static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data) | |||
446 | pcicore_write32(pc, 0x134, data); | 472 | pcicore_write32(pc, 0x134, data); |
447 | } | 473 | } |
448 | 474 | ||
475 | static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) | ||
476 | { | ||
477 | const u16 mdio_control = 0x128; | ||
478 | const u16 mdio_data = 0x12C; | ||
479 | u32 v; | ||
480 | int i; | ||
481 | |||
482 | v = (1 << 30); /* Start of Transaction */ | ||
483 | v |= (1 << 28); /* Write Transaction */ | ||
484 | v |= (1 << 17); /* Turnaround */ | ||
485 | v |= (0x1F << 18); | ||
486 | v |= (phy << 4); | ||
487 | pcicore_write32(pc, mdio_data, v); | ||
488 | |||
489 | udelay(10); | ||
490 | for (i = 0; i < 200; i++) { | ||
491 | v = pcicore_read32(pc, mdio_control); | ||
492 | if (v & 0x100 /* Trans complete */) | ||
493 | break; | ||
494 | msleep(1); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) | ||
499 | { | ||
500 | const u16 mdio_control = 0x128; | ||
501 | const u16 mdio_data = 0x12C; | ||
502 | int max_retries = 10; | ||
503 | u16 ret = 0; | ||
504 | u32 v; | ||
505 | int i; | ||
506 | |||
507 | v = 0x80; /* Enable Preamble Sequence */ | ||
508 | v |= 0x2; /* MDIO Clock Divisor */ | ||
509 | pcicore_write32(pc, mdio_control, v); | ||
510 | |||
511 | if (pc->dev->id.revision >= 10) { | ||
512 | max_retries = 200; | ||
513 | ssb_pcie_mdio_set_phy(pc, device); | ||
514 | } | ||
515 | |||
516 | v = (1 << 30); /* Start of Transaction */ | ||
517 | v |= (1 << 29); /* Read Transaction */ | ||
518 | v |= (1 << 17); /* Turnaround */ | ||
519 | if (pc->dev->id.revision < 10) | ||
520 | v |= (u32)device << 22; | ||
521 | v |= (u32)address << 18; | ||
522 | pcicore_write32(pc, mdio_data, v); | ||
523 | /* Wait for the device to complete the transaction */ | ||
524 | udelay(10); | ||
525 | for (i = 0; i < 200; i++) { | ||
526 | v = pcicore_read32(pc, mdio_control); | ||
527 | if (v & 0x100 /* Trans complete */) { | ||
528 | udelay(10); | ||
529 | ret = pcicore_read32(pc, mdio_data); | ||
530 | break; | ||
531 | } | ||
532 | msleep(1); | ||
533 | } | ||
534 | pcicore_write32(pc, mdio_control, 0); | ||
535 | return ret; | ||
536 | } | ||
537 | |||
449 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | 538 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, |
450 | u8 address, u16 data) | 539 | u8 address, u16 data) |
451 | { | 540 | { |
452 | const u16 mdio_control = 0x128; | 541 | const u16 mdio_control = 0x128; |
453 | const u16 mdio_data = 0x12C; | 542 | const u16 mdio_data = 0x12C; |
543 | int max_retries = 10; | ||
454 | u32 v; | 544 | u32 v; |
455 | int i; | 545 | int i; |
456 | 546 | ||
@@ -458,16 +548,22 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | |||
458 | v |= 0x2; /* MDIO Clock Divisor */ | 548 | v |= 0x2; /* MDIO Clock Divisor */ |
459 | pcicore_write32(pc, mdio_control, v); | 549 | pcicore_write32(pc, mdio_control, v); |
460 | 550 | ||
551 | if (pc->dev->id.revision >= 10) { | ||
552 | max_retries = 200; | ||
553 | ssb_pcie_mdio_set_phy(pc, device); | ||
554 | } | ||
555 | |||
461 | v = (1 << 30); /* Start of Transaction */ | 556 | v = (1 << 30); /* Start of Transaction */ |
462 | v |= (1 << 28); /* Write Transaction */ | 557 | v |= (1 << 28); /* Write Transaction */ |
463 | v |= (1 << 17); /* Turnaround */ | 558 | v |= (1 << 17); /* Turnaround */ |
464 | v |= (u32)device << 22; | 559 | if (pc->dev->id.revision < 10) |
560 | v |= (u32)device << 22; | ||
465 | v |= (u32)address << 18; | 561 | v |= (u32)address << 18; |
466 | v |= data; | 562 | v |= data; |
467 | pcicore_write32(pc, mdio_data, v); | 563 | pcicore_write32(pc, mdio_data, v); |
468 | /* Wait for the device to complete the transaction */ | 564 | /* Wait for the device to complete the transaction */ |
469 | udelay(10); | 565 | udelay(10); |
470 | for (i = 0; i < 10; i++) { | 566 | for (i = 0; i < max_retries; i++) { |
471 | v = pcicore_read32(pc, mdio_control); | 567 | v = pcicore_read32(pc, mdio_control); |
472 | if (v & 0x100 /* Trans complete */) | 568 | if (v & 0x100 /* Trans complete */) |
473 | break; | 569 | break; |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 29884c00c4d5..7dca719fbcfb 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -307,7 +307,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
307 | } else { | 307 | } else { |
308 | if (bus->bustype == SSB_BUSTYPE_PCI) { | 308 | if (bus->bustype == SSB_BUSTYPE_PCI) { |
309 | bus->chip_id = pcidev_to_chipid(bus->host_pci); | 309 | bus->chip_id = pcidev_to_chipid(bus->host_pci); |
310 | pci_read_config_word(bus->host_pci, PCI_REVISION_ID, | 310 | pci_read_config_byte(bus->host_pci, PCI_REVISION_ID, |
311 | &bus->chip_rev); | 311 | &bus->chip_rev); |
312 | bus->chip_package = 0; | 312 | bus->chip_package = 0; |
313 | } else { | 313 | } else { |