blob: 494f7cd3b3d266e0c574b83ae585652fcea64294 [file] [log] [blame]
Sandeep Maheswaram6c2b8602021-07-05 11:11:48 +05301/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <soc/usb/qusb_phy.h>
4#include <soc/efuse.h>
5#include <timer.h>
6#include <soc/usb/usb_common.h>
7
8static struct qfprom_corr * const qfprom_corr_efuse = (void *)QFPROM_BASE;
9
10struct hs_usb_phy_reg qusb_phy = {
11 .phy_pll = (void *)QUSB_PRIM_PHY_BASE,
12
13 .phy_dig = (void *)QUSB_PRIM_PHY_DIG_BASE,
14
15 .efuse_offset = 25,
16};
17
18static void qusb2_phy_override_phy_params(struct hs_usb_phy_reg *hs_phy_reg)
19{
20 /* Override preemphasis value */
21 write32(&hs_phy_reg->phy_dig->tune1,
22 hs_phy_reg->board_data->port_tune1);
23
24 /* Override BIAS_CTRL_2 to reduce the TX swing overshooting. */
25 write32(&hs_phy_reg->phy_pll->bias_ctrl_2,
26 hs_phy_reg->board_data->pll_bias_control_2);
27
28 /* Override IMP_RES_OFFSET value */
29 write32(&hs_phy_reg->phy_dig->imp_ctrl1,
30 hs_phy_reg->board_data->imp_ctrl1);
31}
32
33/*
34 * Fetches HS Tx tuning value from efuse register and sets the
35 * QUSB2PHY_PORT_TUNE1/2 register.
36 * For error case, skip setting the value and use the default value.
37 */
38
39static void qusb2_phy_set_tune_param(struct hs_usb_phy_reg *hs_phy_reg)
40{
41 /*
42 * Efuse registers 3 bit value specifies tuning for HSTX
43 * output current in TUNE1 Register. Hence Extract 3 bits from
44 * EFUSE at correct position.
45 */
46
47 const int efuse_bits = 3;
48 int bit_pos = hs_phy_reg->efuse_offset;
49
50 u32 bit_mask = (1 << efuse_bits) - 1;
51 u32 tune_val =
52 (read32(&qfprom_corr_efuse->qusb_hstx_trim_lsb) >> bit_pos)
53 & bit_mask;
54 /*
55 * if efuse reg is updated (i.e non-zero) then use it to program
56 * tune parameters.
57 */
58 if (tune_val)
59 clrsetbits32(&hs_phy_reg->phy_dig->tune1,
60 PORT_TUNE1_MASK, tune_val << 4);
61}
62
63static void tune_phy(struct hs_usb_phy_reg *hs_phy_reg)
64{
65 write32(&hs_phy_reg->phy_dig->pwr_ctrl2, QUSB2PHY_PWR_CTRL2);
66 /* IMP_CTRL1: Control the impedance reduction */
67 write32(&hs_phy_reg->phy_dig->imp_ctrl1, QUSB2PHY_IMP_CTRL1);
68 /* IMP_CTRL2: Impedance offset/mapping slope */
69 write32(&hs_phy_reg->phy_dig->imp_ctrl2, QUSB2PHY_IMP_CTRL1);
70 write32(&hs_phy_reg->phy_dig->chg_ctrl2, QUSB2PHY_IMP_CTRL2);
71 /*
72 * TUNE1: Sets HS Impedance to approx 45 ohms
73 * then override with efuse value.
74 */
75 write32(&hs_phy_reg->phy_dig->tune1, QUSB2PHY_PORT_TUNE1);
76 /* TUNE2: Tuning for HS Disconnect Level */
77 write32(&hs_phy_reg->phy_dig->tune2, QUSB2PHY_PORT_TUNE2);
78 /* TUNE3: Tune squelch range */
79 write32(&hs_phy_reg->phy_dig->tune3, QUSB2PHY_PORT_TUNE3);
80 /* TUNE4: Sets EOP_DLY(Squelch rising edge to linestate falling edge) */
81 write32(&hs_phy_reg->phy_dig->tune4, QUSB2PHY_PORT_TUNE4);
82 write32(&hs_phy_reg->phy_dig->tune5, QUSB2PHY_PORT_TUNE5);
83
84 if (hs_phy_reg->board_data) {
85 /* Override board specific PHY tuning values */
86 qusb2_phy_override_phy_params(hs_phy_reg);
87
88 /* Set efuse value for tuning the PHY */
89 qusb2_phy_set_tune_param(hs_phy_reg);
90 }
91}
92
93void hs_usb_phy_init(void *board_data)
94{
95 struct hs_usb_phy_reg *hs_phy_reg;
96
97 hs_phy_reg = &qusb_phy;
98
99 hs_phy_reg->board_data = (struct usb_board_data *) board_data;
100
101 /* PWR_CTRL: set the power down bit to disable the PHY */
102
103 setbits32(&hs_phy_reg->phy_dig->pwr_ctrl1, POWER_DOWN);
104
105 write32(&hs_phy_reg->phy_pll->analog_controls_two,
106 QUSB2PHY_PLL_ANALOG_CONTROLS_TWO);
107 write32(&hs_phy_reg->phy_pll->clock_inverters,
108 QUSB2PHY_PLL_CLOCK_INVERTERS);
109 write32(&hs_phy_reg->phy_pll->cmode,
110 QUSB2PHY_PLL_CMODE);
111 write32(&hs_phy_reg->phy_pll->lock_delay,
112 QUSB2PHY_PLL_LOCK_DELAY);
113 write32(&hs_phy_reg->phy_pll->dig_tim,
114 QUSB2PHY_PLL_DIGITAL_TIMERS_TWO);
115 write32(&hs_phy_reg->phy_pll->bias_ctrl_1,
116 QUSB2PHY_PLL_BIAS_CONTROL_1);
117 write32(&hs_phy_reg->phy_pll->bias_ctrl_2,
118 QUSB2PHY_PLL_BIAS_CONTROL_2);
119
120 tune_phy(hs_phy_reg);
121
122 /* PWR_CTRL1: Clear the power down bit to enable the PHY */
123 clrbits32(&hs_phy_reg->phy_dig->pwr_ctrl1, POWER_DOWN);
124
125 write32(&hs_phy_reg->phy_dig->debug_ctrl2,
126 DEBUG_CTRL2_MUX_PLL_LOCK_STATUS);
127
128 /*
129 * DEBUG_STAT5: wait for 160uS for PLL lock;
130 * vstatus[0] changes from 0 to 1.
131 */
132 long lock_us = wait_us(160, read32(&hs_phy_reg->phy_dig->debug_stat5) &
133 VSTATUS_PLL_LOCK_STATUS_MASK);
134 if (!lock_us)
Julius Wernere9665952022-01-21 17:06:20 -0800135 printk(BIOS_ERR, "QUSB PHY PLL LOCK fails\n");
Sandeep Maheswaram6c2b8602021-07-05 11:11:48 +0530136 else
137 printk(BIOS_DEBUG, "QUSB PHY initialized and locked in %ldus\n",
138 lock_us);
139}