aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2011-04-01 06:07:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-04 16:20:07 -0400
commit1b1c7acd9709e545399d1b6b89888f025911c0a2 (patch)
treecdc4929cd84d7e80948fac371b59d2c46a70bd8d /drivers
parent6c74608bd479bbe02ce330f83df43c3f535ed200 (diff)
ssb: pci: fix mdio writes on newer cores (rev 10+)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ssb/driver_pcicore.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index e0cf29e57919..08fa6fdfc101 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -444,11 +444,35 @@ static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data)
444 pcicore_write32(pc, 0x134, data); 444 pcicore_write32(pc, 0x134, data);
445} 445}
446 446
447static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy)
448{
449 const u16 mdio_control = 0x128;
450 const u16 mdio_data = 0x12C;
451 u32 v;
452 int i;
453
454 v = (1 << 30); /* Start of Transaction */
455 v |= (1 << 28); /* Write Transaction */
456 v |= (1 << 17); /* Turnaround */
457 v |= (0x1F << 18);
458 v |= (phy << 4);
459 pcicore_write32(pc, mdio_data, v);
460
461 udelay(10);
462 for (i = 0; i < 200; i++) {
463 v = pcicore_read32(pc, mdio_control);
464 if (v & 0x100 /* Trans complete */)
465 break;
466 msleep(1);
467 }
468}
469
447static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, 470static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
448 u8 address, u16 data) 471 u8 address, u16 data)
449{ 472{
450 const u16 mdio_control = 0x128; 473 const u16 mdio_control = 0x128;
451 const u16 mdio_data = 0x12C; 474 const u16 mdio_data = 0x12C;
475 int max_retries = 10;
452 u32 v; 476 u32 v;
453 int i; 477 int i;
454 478
@@ -456,16 +480,22 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
456 v |= 0x2; /* MDIO Clock Divisor */ 480 v |= 0x2; /* MDIO Clock Divisor */
457 pcicore_write32(pc, mdio_control, v); 481 pcicore_write32(pc, mdio_control, v);
458 482
483 if (pc->dev->id.revision >= 10) {
484 max_retries = 200;
485 ssb_pcie_mdio_set_phy(pc, device);
486 }
487
459 v = (1 << 30); /* Start of Transaction */ 488 v = (1 << 30); /* Start of Transaction */
460 v |= (1 << 28); /* Write Transaction */ 489 v |= (1 << 28); /* Write Transaction */
461 v |= (1 << 17); /* Turnaround */ 490 v |= (1 << 17); /* Turnaround */
462 v |= (u32)device << 22; 491 if (pc->dev->id.revision < 10)
492 v |= (u32)device << 22;
463 v |= (u32)address << 18; 493 v |= (u32)address << 18;
464 v |= data; 494 v |= data;
465 pcicore_write32(pc, mdio_data, v); 495 pcicore_write32(pc, mdio_data, v);
466 /* Wait for the device to complete the transaction */ 496 /* Wait for the device to complete the transaction */
467 udelay(10); 497 udelay(10);
468 for (i = 0; i < 10; i++) { 498 for (i = 0; i < max_retries; i++) {
469 v = pcicore_read32(pc, mdio_control); 499 v = pcicore_read32(pc, mdio_control);
470 if (v & 0x100 /* Trans complete */) 500 if (v & 0x100 /* Trans complete */)
471 break; 501 break;