aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
commit252f4bf400df1712408fe83ba199a66a1b57ab1d (patch)
treee07fa00abdd55b31e22567786c78635f32c6a66c /drivers/ssb
parent6ba1037c3d871ab70e342631516dbf841c35b086 (diff)
parentb37e3b6d64358604960b35e8ecbb7aed22e0926e (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.c104
-rw-r--r--drivers/ssb/scan.c2
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
18static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address);
19static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data);
20static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address);
21static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
22 u8 address, u16 data);
18 23
19static inline 24static inline
20u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) 25u32 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
415static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc)
416{
417 return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
418}
419
420static 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)
417void ssb_pcicore_init(struct ssb_pcicore *pc) 443void 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
437static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) 463static 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
475static 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
498static 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
449static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, 538static 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 {