For increased DPLL stability use the settings recommended in
the TRM [1] for PHY_RX registers for SATA and USB.
For SATA we need to use spread spectrum settings even
though we don't have spread spectrum enabled. The
suggested non-spread spectrum settings don't work.
[1] DRA75x, DRA74x TRM - http://www.ti.com/lit/ug/sprui30f/sprui30f.pdf
Signed-off-by: Roger Quadros
---
drivers/phy/ti-pipe3-phy.c | 193 +
1 file changed, 193 insertions(+)
diff --git a/drivers/phy/ti-pipe3-phy.c b/drivers/phy/ti-pipe3-phy.c
index 935dc7afb6..b9c8591470 100644
--- a/drivers/phy/ti-pipe3-phy.c
+++ b/drivers/phy/ti-pipe3-phy.c
@@ -50,6 +50,62 @@
#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3
#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0
+/* PHY RX Registers */
+#define PIPE3_PHY_RX_ANA_PROGRAMMABILITY 0x000C
+#define INTERFACE_MASK GENMASK(31, 27)
+#define INTERFACE_SHIFT27
+#define INTERFACE_MODE_USBSS BIT(4)
+#define INTERFACE_MODE_SATA_1P5BIT(3)
+#define INTERFACE_MODE_SATA_3P0BIT(2)
+#define INTERFACE_MODE_PCIEBIT(0)
+
+#define LOSD_MASK GENMASK(17, 14)
+#define LOSD_SHIFT 14
+#define MEM_PLLDIV GENMASK(6, 5)
+
+#define PIPE3_PHY_RX_TRIM 0x001C
+#define MEM_DLL_TRIM_SEL_MASK GENMASK(31, 30)
+#define MEM_DLL_TRIM_SHIFT 30
+
+#define PIPE3_PHY_RX_DLL 0x0024
+#define MEM_DLL_PHINT_RATE_MASKGENMASK(31, 30)
+#define MEM_DLL_PHINT_RATE_SHIFT 30
+
+#define PIPE3_PHY_RX_DIGITAL_MODES 0x0028
+#define MEM_HS_RATE_MASK GENMASK(28, 27)
+#define MEM_HS_RATE_SHIFT 27
+#define MEM_OVRD_HS_RATE BIT(26)
+#define MEM_OVRD_HS_RATE_SHIFT 26
+#define MEM_CDR_FASTLOCK BIT(23)
+#define MEM_CDR_FASTLOCK_SHIFT 23
+#define MEM_CDR_LBW_MASK GENMASK(22, 21)
+#define MEM_CDR_LBW_SHIFT 21
+#define MEM_CDR_STEPCNT_MASK GENMASK(20, 19)
+#define MEM_CDR_STEPCNT_SHIFT 19
+#define MEM_CDR_STL_MASK GENMASK(18, 16)
+#define MEM_CDR_STL_SHIFT 16
+#define MEM_CDR_THR_MASK GENMASK(15, 13)
+#define MEM_CDR_THR_SHIFT 13
+#define MEM_CDR_THR_MODE BIT(12)
+#define MEM_CDR_THR_MODE_SHIFT 12
+#define MEM_CDR_2NDO_SDM_MODE BIT(11)
+#define MEM_CDR_2NDO_SDM_MODE_SHIFT11
+
+#define PIPE3_PHY_RX_EQUALIZER 0x0038
+#define MEM_EQLEV_MASK GENMASK(31, 16)
+#define MEM_EQLEV_SHIFT16
+#define MEM_EQFTC_MASK GENMASK(15, 11)
+#define MEM_EQFTC_SHIFT11
+#define MEM_EQCTL_MASK GENMASK(10, 7)
+#define MEM_EQCTL_SHIFT7
+#define MEM_OVRD_EQLEV BIT(2)
+#define MEM_OVRD_EQLEV_SHIFT 2
+#define MEM_OVRD_EQFTC BIT(1)
+#define MEM_OVRD_EQFTC_SHIFT 1
+
+#define SATA_PHY_RX_IO_AND_A2D_OVERRIDES 0x44
+#define MEM_CDR_LOS_SOURCE_MASKGENMASK(10, 9)
+#define MEM_CDR_LOS_SOURCE_SHIFT 9
#define PLL_IDLE_TIME 100 /* in milliseconds */
#define PLL_LOCK_TIME 100 /* in milliseconds */
@@ -58,12 +114,35 @@ enum pipe3_mode { PIPE3_MODE_PCIE = 1,
PIPE3_MODE_SATA,
PIPE3_MODE_USBSS };
+struct pipe3_settings {
+ u8 ana_interface;
+ u8 ana_losd;
+ u8 dig_fastlock;
+ u8 dig_lbw;
+ u8 dig_stepcnt;
+ u8 dig_stl;
+ u8 dig_thr;
+ u8 dig_thr_mode;
+ u8 dig_2ndo_sdm_mode;
+ u8 dig_hs_rate;
+ u8 dig_ovrd_hs_rate;
+ u8 dll_trim_sel;
+ u8 dll_phint_rate;
+ u8 eq_lev;
+ u8 eq_ftc;
+ u8 eq_ctl;
+ u8 eq_ovrd_lev;
+ u8 eq_ovrd_ftc;
+};
+
struct omap_pipe3 {
void __iomem*pll_ctrl_base;
+ void __iomem*phy_rx;
void __iomem*power_reg;
void __iomem*pll_reset_reg;
struct pipe3_dpll_map *dpll_map;
enum pipe3_mode mode;
+ struct pipe3_settings settings;
};
struct pipe3_dpll_params {
@@ -82,6 +161,7 @@ struct pipe3_dpll_map {
struct pipe3_data {
enum pipe3_mode mode;
struct pipe3_dpll_map *dpll_map;
+ struct pipe3_settings settings;
};
static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
@@ -199,6 +279,60 @@ static void omap_control_pipe3_power(struct omap_pipe3
*pipe3, int on)
writel(val, pipe3->power_reg);
}
+static void ti_pipe3_calibrate(struct omap_pipe3 *phy)
+{
+ u32 val;
+ struct pipe3_settings *s = &phy->settings;
+
+ val = omap_pipe3_readl(phy->phy_rx, PIPE3_PHY_RX_ANA_PROGRAMMABILITY);
+ val &= ~(INTERFACE_MASK | LOSD_MASK | MEM_PLLDIV);
+ va