diff options
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/driver_pcicore.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 76cbf96001f1..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. |
@@ -430,6 +456,8 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) | |||
430 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ | 456 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ |
431 | if (!pc->hostmode) | 457 | if (!pc->hostmode) |
432 | ssb_pcicore_init_clientmode(pc); | 458 | ssb_pcicore_init_clientmode(pc); |
459 | |||
460 | ssb_pcicore_serdes_workaround(pc); | ||
433 | } | 461 | } |
434 | 462 | ||
435 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) | 463 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) |
@@ -467,8 +495,6 @@ static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) | |||
467 | } | 495 | } |
468 | } | 496 | } |
469 | 497 | ||
470 | #if 0 | ||
471 | //done but not used yet | ||
472 | static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) | 498 | static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) |
473 | { | 499 | { |
474 | const u16 mdio_control = 0x128; | 500 | const u16 mdio_control = 0x128; |
@@ -508,7 +534,6 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) | |||
508 | pcicore_write32(pc, mdio_control, 0); | 534 | pcicore_write32(pc, mdio_control, 0); |
509 | return ret; | 535 | return ret; |
510 | } | 536 | } |
511 | #endif | ||
512 | 537 | ||
513 | 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, |
514 | u8 address, u16 data) | 539 | u8 address, u16 data) |