diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2011-04-01 06:07:33 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-04 16:20:07 -0400 |
commit | 1b1c7acd9709e545399d1b6b89888f025911c0a2 (patch) | |
tree | cdc4929cd84d7e80948fac371b59d2c46a70bd8d /drivers | |
parent | 6c74608bd479bbe02ce330f83df43c3f535ed200 (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.c | 34 |
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 | ||
447 | static 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 | |||
447 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | 470 | static 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; |