aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2011-04-01 07:26:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-04 16:20:07 -0400
commitccc7c28af205888798b51b6cbc0b557ac1170a49 (patch)
tree327d8442a68447cf4cdf8425e2e6713c77e6328a /drivers/ssb
parentba91d1a1bcccd90247b5b9703c1a236cc2e95698 (diff)
ssb: pci: implement serdes workaround
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb')
-rw-r--r--drivers/ssb/driver_pcicore.c31
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
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.
@@ -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
435static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) 463static 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
472static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) 498static 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
513static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, 538static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
514 u8 address, u16 data) 539 u8 address, u16 data)