aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManu Gautam <mgautam@codeaurora.org>2018-05-02 17:06:14 -0400
committerKishon Vijay Abraham I <kishon@ti.com>2018-05-20 12:21:33 -0400
commitef17f6e212caeebcbbb5da9e147eb3739061f4a1 (patch)
tree7865d907e4bacbe2b1396d09d495454cc34e8f78
parenta8b70ccf10e38775785d9cb12ead916474549f99 (diff)
phy: qcom-qusb2: Add QUSB2 PHYs support for sdm845
There are two QUSB2 PHYs present on sdm845. In order to improve eye diagram for both the PHYs some parameters need to be changed. Provide device tree properties to override these from board specific device tree files. Signed-off-by: Manu Gautam <mgautam@codeaurora.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c126
1 files changed, 118 insertions, 8 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 40fdef8b5b75..e70e425f26f5 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -20,6 +20,8 @@
20#include <linux/reset.h> 20#include <linux/reset.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22 22
23#include <dt-bindings/phy/phy-qcom-qusb2.h>
24
23#define QUSB2PHY_PLL_TEST 0x04 25#define QUSB2PHY_PLL_TEST 0x04
24#define CLK_REF_SEL BIT(7) 26#define CLK_REF_SEL BIT(7)
25 27
@@ -60,6 +62,17 @@
60#define CORE_RESET BIT(5) 62#define CORE_RESET BIT(5)
61#define CORE_RESET_MUX BIT(6) 63#define CORE_RESET_MUX BIT(6)
62 64
65/* QUSB2PHY_IMP_CTRL1 register bits */
66#define IMP_RES_OFFSET_MASK GENMASK(5, 0)
67#define IMP_RES_OFFSET_SHIFT 0x0
68
69/* QUSB2PHY_PORT_TUNE1 register bits */
70#define HSTX_TRIM_MASK GENMASK(7, 4)
71#define HSTX_TRIM_SHIFT 0x4
72#define PREEMPH_WIDTH_HALF_BIT BIT(2)
73#define PREEMPHASIS_EN_MASK GENMASK(1, 0)
74#define PREEMPHASIS_EN_SHIFT 0x0
75
63#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04 76#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
64#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c 77#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
65#define QUSB2PHY_PLL_CMODE 0x2c 78#define QUSB2PHY_PLL_CMODE 0x2c
@@ -139,7 +152,7 @@ static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
139 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), 152 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
140}; 153};
141 154
142static const unsigned int qusb2_v2_regs_layout[] = { 155static const unsigned int sdm845_regs_layout[] = {
143 [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8, 156 [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
144 [QUSB2PHY_PLL_STATUS] = 0x1a0, 157 [QUSB2PHY_PLL_STATUS] = 0x1a0,
145 [QUSB2PHY_PORT_TUNE1] = 0x240, 158 [QUSB2PHY_PORT_TUNE1] = 0x240,
@@ -153,7 +166,7 @@ static const unsigned int qusb2_v2_regs_layout[] = {
153 [QUSB2PHY_INTR_CTRL] = 0x230, 166 [QUSB2PHY_INTR_CTRL] = 0x230,
154}; 167};
155 168
156static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { 169static const struct qusb2_phy_init_tbl sdm845_init_tbl[] = {
157 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), 170 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
158 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), 171 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
159 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80), 172 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
@@ -208,10 +221,10 @@ static const struct qusb2_phy_cfg msm8996_phy_cfg = {
208 .autoresume_en = BIT(3), 221 .autoresume_en = BIT(3),
209}; 222};
210 223
211static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { 224static const struct qusb2_phy_cfg sdm845_phy_cfg = {
212 .tbl = qusb2_v2_init_tbl, 225 .tbl = sdm845_init_tbl,
213 .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl), 226 .tbl_num = ARRAY_SIZE(sdm845_init_tbl),
214 .regs = qusb2_v2_regs_layout, 227 .regs = sdm845_regs_layout,
215 228
216 .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN | 229 .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
217 POWER_DOWN), 230 POWER_DOWN),
@@ -241,6 +254,15 @@ static const char * const qusb2_phy_vreg_names[] = {
241 * @tcsr: TCSR syscon register map 254 * @tcsr: TCSR syscon register map
242 * @cell: nvmem cell containing phy tuning value 255 * @cell: nvmem cell containing phy tuning value
243 * 256 *
257 * @override_imp_res_offset: PHY should use different rescode offset
258 * @imp_res_offset_value: rescode offset to be updated in IMP_CTRL1 register
259 * @override_hstx_trim: PHY should use different HSTX o/p current value
260 * @hstx_trim_value: HSTX_TRIM value to be updated in TUNE1 register
261 * @override_preemphasis: PHY should use different pre-amphasis amplitude
262 * @preemphasis_level: Amplitude Pre-Emphasis to be updated in TUNE1 register
263 * @override_preemphasis_width: PHY should use different pre-emphasis duration
264 * @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
265 *
244 * @cfg: phy config data 266 * @cfg: phy config data
245 * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme 267 * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
246 * @phy_initialized: indicate if PHY has been initialized 268 * @phy_initialized: indicate if PHY has been initialized
@@ -259,12 +281,35 @@ struct qusb2_phy {
259 struct regmap *tcsr; 281 struct regmap *tcsr;
260 struct nvmem_cell *cell; 282 struct nvmem_cell *cell;
261 283
284 bool override_imp_res_offset;
285 u8 imp_res_offset_value;
286 bool override_hstx_trim;
287 u8 hstx_trim_value;
288 bool override_preemphasis;
289 u8 preemphasis_level;
290 bool override_preemphasis_width;
291 u8 preemphasis_width;
292
262 const struct qusb2_phy_cfg *cfg; 293 const struct qusb2_phy_cfg *cfg;
263 bool has_se_clk_scheme; 294 bool has_se_clk_scheme;
264 bool phy_initialized; 295 bool phy_initialized;
265 enum phy_mode mode; 296 enum phy_mode mode;
266}; 297};
267 298
299static inline void qusb2_write_mask(void __iomem *base, u32 offset,
300 u32 val, u32 mask)
301{
302 u32 reg;
303
304 reg = readl(base + offset);
305 reg &= ~mask;
306 reg |= val & mask;
307 writel(reg, base + offset);
308
309 /* Ensure above write is completed */
310 readl(base + offset);
311}
312
268static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val) 313static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val)
269{ 314{
270 u32 reg; 315 u32 reg;
@@ -305,6 +350,42 @@ void qcom_qusb2_phy_configure(void __iomem *base,
305} 350}
306 351
307/* 352/*
353 * Update board specific PHY tuning override values if specified from
354 * device tree.
355 */
356static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy)
357{
358 const struct qusb2_phy_cfg *cfg = qphy->cfg;
359
360 if (qphy->override_imp_res_offset)
361 qusb2_write_mask(qphy->base, QUSB2PHY_IMP_CTRL1,
362 qphy->imp_res_offset_value << IMP_RES_OFFSET_SHIFT,
363 IMP_RES_OFFSET_MASK);
364
365 if (qphy->override_hstx_trim)
366 qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
367 qphy->hstx_trim_value << HSTX_TRIM_SHIFT,
368 HSTX_TRIM_MASK);
369
370 if (qphy->override_preemphasis)
371 qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
372 qphy->preemphasis_level << PREEMPHASIS_EN_SHIFT,
373 PREEMPHASIS_EN_MASK);
374
375 if (qphy->override_preemphasis_width) {
376 if (qphy->preemphasis_width ==
377 QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT)
378 qusb2_setbits(qphy->base,
379 cfg->regs[QUSB2PHY_PORT_TUNE1],
380 PREEMPH_WIDTH_HALF_BIT);
381 else
382 qusb2_clrbits(qphy->base,
383 cfg->regs[QUSB2PHY_PORT_TUNE1],
384 PREEMPH_WIDTH_HALF_BIT);
385 }
386}
387
388/*
308 * Fetches HS Tx tuning value from nvmem and sets the 389 * Fetches HS Tx tuning value from nvmem and sets the
309 * QUSB2PHY_PORT_TUNE1/2 register. 390 * QUSB2PHY_PORT_TUNE1/2 register.
310 * For error case, skip setting the value and use the default value. 391 * For error case, skip setting the value and use the default value.
@@ -525,6 +606,9 @@ static int qusb2_phy_init(struct phy *phy)
525 qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl, 606 qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl,
526 cfg->tbl_num); 607 cfg->tbl_num);
527 608
609 /* Override board specific PHY tuning values */
610 qusb2_phy_override_phy_params(qphy);
611
528 /* Set efuse value for tuning the PHY */ 612 /* Set efuse value for tuning the PHY */
529 qusb2_phy_set_tune2_param(qphy); 613 qusb2_phy_set_tune2_param(qphy);
530 614
@@ -647,8 +731,8 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
647 .compatible = "qcom,msm8996-qusb2-phy", 731 .compatible = "qcom,msm8996-qusb2-phy",
648 .data = &msm8996_phy_cfg, 732 .data = &msm8996_phy_cfg,
649 }, {