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