1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2023-2024, Linaro Limited
4  *
5  * Based on the Linux phy-qcom-snps-eusb2.c driver
6  */
7 
8 #include <clk.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <dm/device_compat.h>
12 #include <dm/devres.h>
13 #include <generic-phy.h>
14 #include <malloc.h>
15 #include <reset.h>
16 
17 #include <asm/io.h>
18 #include <linux/bitops.h>
19 #include <linux/bitfield.h>
20 #include <linux/clk-provider.h>
21 #include <linux/delay.h>
22 
23 #define USB_PHY_UTMI_CTRL0		(0x3c)
24 #define SLEEPM				BIT(0)
25 #define OPMODE_MASK			GENMASK(4, 3)
26 #define OPMODE_NONDRIVING		BIT(3)
27 
28 #define USB_PHY_UTMI_CTRL5		(0x50)
29 #define POR				BIT(1)
30 
31 #define USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
32 #define PHY_ENABLE			BIT(0)
33 #define SIDDQ_SEL			BIT(1)
34 #define SIDDQ				BIT(2)
35 #define RETENABLEN			BIT(3)
36 #define FSEL_MASK			GENMASK(6, 4)
37 #define FSEL_19_2_MHZ_VAL		(0x0)
38 #define FSEL_38_4_MHZ_VAL		(0x4)
39 
40 #define USB_PHY_CFG_CTRL_1		(0x58)
41 #define PHY_CFG_PLL_CPBIAS_CNTRL_MASK	GENMASK(7, 1)
42 
43 #define USB_PHY_CFG_CTRL_2		(0x5c)
44 #define PHY_CFG_PLL_FB_DIV_7_0_MASK	GENMASK(7, 0)
45 #define DIV_7_0_19_2_MHZ_VAL		(0x90)
46 #define DIV_7_0_38_4_MHZ_VAL		(0xc8)
47 
48 #define USB_PHY_CFG_CTRL_3		(0x60)
49 #define PHY_CFG_PLL_FB_DIV_11_8_MASK	GENMASK(3, 0)
50 #define DIV_11_8_19_2_MHZ_VAL		(0x1)
51 #define DIV_11_8_38_4_MHZ_VAL		(0x0)
52 
53 #define PHY_CFG_PLL_REF_DIV		GENMASK(7, 4)
54 #define PLL_REF_DIV_VAL			(0x0)
55 
56 #define USB_PHY_HS_PHY_CTRL2		(0x64)
57 #define VBUSVLDEXT0			BIT(0)
58 #define USB2_SUSPEND_N			BIT(2)
59 #define USB2_SUSPEND_N_SEL		BIT(3)
60 #define VBUS_DET_EXT_SEL		BIT(4)
61 
62 #define USB_PHY_CFG_CTRL_4		(0x68)
63 #define PHY_CFG_PLL_GMP_CNTRL_MASK	GENMASK(1, 0)
64 #define PHY_CFG_PLL_INT_CNTRL_MASK	GENMASK(7, 2)
65 
66 #define USB_PHY_CFG_CTRL_5		(0x6c)
67 #define PHY_CFG_PLL_PROP_CNTRL_MASK	GENMASK(4, 0)
68 #define PHY_CFG_PLL_VREF_TUNE_MASK	GENMASK(7, 6)
69 
70 #define USB_PHY_CFG_CTRL_6		(0x70)
71 #define PHY_CFG_PLL_VCO_CNTRL_MASK	GENMASK(2, 0)
72 
73 #define USB_PHY_CFG_CTRL_7		(0x74)
74 
75 #define USB_PHY_CFG_CTRL_8		(0x78)
76 #define PHY_CFG_TX_FSLS_VREF_TUNE_MASK	GENMASK(1, 0)
77 #define PHY_CFG_TX_FSLS_VREG_BYPASS	BIT(2)
78 #define PHY_CFG_TX_HS_VREF_TUNE_MASK	GENMASK(5, 3)
79 #define PHY_CFG_TX_HS_XV_TUNE_MASK	GENMASK(7, 6)
80 
81 #define USB_PHY_CFG_CTRL_9		(0x7c)
82 #define PHY_CFG_TX_PREEMP_TUNE_MASK	GENMASK(2, 0)
83 #define PHY_CFG_TX_RES_TUNE_MASK	GENMASK(4, 3)
84 #define PHY_CFG_TX_RISE_TUNE_MASK	GENMASK(6, 5)
85 #define PHY_CFG_RCAL_BYPASS		BIT(7)
86 
87 #define USB_PHY_CFG_CTRL_10		(0x80)
88 
89 #define USB_PHY_CFG0			(0x94)
90 #define DATAPATH_CTRL_OVERRIDE_EN	BIT(0)
91 #define CMN_CTRL_OVERRIDE_EN		BIT(1)
92 
93 #define UTMI_PHY_CMN_CTRL0		(0x98)
94 #define TESTBURNIN			BIT(6)
95 
96 #define USB_PHY_FSEL_SEL		(0xb8)
97 #define FSEL_SEL			BIT(0)
98 
99 #define USB_PHY_APB_ACCESS_CMD		(0x130)
100 #define RW_ACCESS			BIT(0)
101 #define APB_START_CMD			BIT(1)
102 #define APB_LOGIC_RESET			BIT(2)
103 
104 #define USB_PHY_APB_ACCESS_STATUS	(0x134)
105 #define ACCESS_DONE			BIT(0)
106 #define TIMED_OUT			BIT(1)
107 #define ACCESS_ERROR			BIT(2)
108 #define ACCESS_IN_PROGRESS		BIT(3)
109 
110 #define USB_PHY_APB_ADDRESS		(0x138)
111 #define APB_REG_ADDR_MASK		GENMASK(7, 0)
112 
113 #define USB_PHY_APB_WRDATA_LSB		(0x13c)
114 #define APB_REG_WRDATA_7_0_MASK		GENMASK(3, 0)
115 
116 #define USB_PHY_APB_WRDATA_MSB		(0x140)
117 #define APB_REG_WRDATA_15_8_MASK	GENMASK(7, 4)
118 
119 #define USB_PHY_APB_RDDATA_LSB		(0x144)
120 #define APB_REG_RDDATA_7_0_MASK		GENMASK(3, 0)
121 
122 #define USB_PHY_APB_RDDATA_MSB		(0x148)
123 #define APB_REG_RDDATA_15_8_MASK	GENMASK(7, 4)
124 
125 struct qcom_snps_eusb2_phy_priv {
126 	void __iomem *base;
127 	struct clk *ref_clk;
128 	struct reset_ctl_bulk resets;
129 };
130 
qcom_snps_eusb2_hsphy_write_mask(void __iomem * base,u32 offset,u32 mask,u32 val)131 static void qcom_snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset,
132 					     u32 mask, u32 val)
133 {
134 	u32 reg;
135 
136 	reg = readl_relaxed(base + offset);
137 	reg &= ~mask;
138 	reg |= val & mask;
139 	writel_relaxed(reg, base + offset);
140 
141 	/* Ensure above write is completed */
142 	readl_relaxed(base + offset);
143 }
144 
qcom_eusb2_default_parameters(struct qcom_snps_eusb2_phy_priv * qcom_snps_eusb2)145 static void qcom_eusb2_default_parameters(struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2)
146 {
147 	/* default parameters: tx pre-emphasis */
148 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_9,
149 					 PHY_CFG_TX_PREEMP_TUNE_MASK,
150 					 FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0));
151 
152 	/* tx rise/fall time */
153 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_9,
154 					 PHY_CFG_TX_RISE_TUNE_MASK,
155 					 FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2));
156 
157 	/* source impedance adjustment */
158 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_9,
159 					 PHY_CFG_TX_RES_TUNE_MASK,
160 					 FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1));
161 
162 	/* dc voltage level adjustement */
163 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_8,
164 					 PHY_CFG_TX_HS_VREF_TUNE_MASK,
165 					 FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3));
166 
167 	/* transmitter HS crossover adjustement */
168 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_8,
169 					 PHY_CFG_TX_HS_XV_TUNE_MASK,
170 					 FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0));
171 }
172 
qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_phy_priv * qcom_snps_eusb2)173 static int qcom_eusb2_ref_clk_init(struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2)
174 {
175 	unsigned long ref_clk_freq = clk_get_rate(qcom_snps_eusb2->ref_clk);
176 
177 	switch (ref_clk_freq) {
178 	case 19200000:
179 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL_COMMON0,
180 						 FSEL_MASK,
181 						 FIELD_PREP(FSEL_MASK, FSEL_19_2_MHZ_VAL));
182 
183 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_2,
184 						 PHY_CFG_PLL_FB_DIV_7_0_MASK,
185 						 DIV_7_0_19_2_MHZ_VAL);
186 
187 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_3,
188 						 PHY_CFG_PLL_FB_DIV_11_8_MASK,
189 						 DIV_11_8_19_2_MHZ_VAL);
190 		break;
191 
192 	case 38400000:
193 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL_COMMON0,
194 						 FSEL_MASK,
195 						 FIELD_PREP(FSEL_MASK, FSEL_38_4_MHZ_VAL));
196 
197 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_2,
198 						 PHY_CFG_PLL_FB_DIV_7_0_MASK,
199 						 DIV_7_0_38_4_MHZ_VAL);
200 
201 		qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_3,
202 						 PHY_CFG_PLL_FB_DIV_11_8_MASK,
203 						 DIV_11_8_38_4_MHZ_VAL);
204 		break;
205 
206 	default:
207 		printf("%s: unsupported ref_clk_freq:%lu\n", __func__, ref_clk_freq);
208 		return -EINVAL;
209 	}
210 
211 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_3,
212 					 PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL);
213 
214 	return 0;
215 }
216 
qcom_snps_eusb2_usb_init(struct phy * phy)217 static int qcom_snps_eusb2_usb_init(struct phy *phy)
218 {
219 	struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2 = dev_get_priv(phy->dev);
220 	int ret;
221 
222 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG0,
223 					 CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN);
224 
225 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_UTMI_CTRL5, POR, POR);
226 
227 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL_COMMON0,
228 					 PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN);
229 
230 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_APB_ACCESS_CMD,
231 					 APB_LOGIC_RESET, APB_LOGIC_RESET);
232 
233 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0);
234 
235 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_FSEL_SEL,
236 					 FSEL_SEL, FSEL_SEL);
237 
238 	/* update ref_clk related registers */
239 	ret = qcom_eusb2_ref_clk_init(qcom_snps_eusb2);
240 	if (ret)
241 		return ret;
242 
243 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_1,
244 					 PHY_CFG_PLL_CPBIAS_CNTRL_MASK,
245 					 FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x1));
246 
247 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_4,
248 					 PHY_CFG_PLL_INT_CNTRL_MASK,
249 					 FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8));
250 
251 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_4,
252 					 PHY_CFG_PLL_GMP_CNTRL_MASK,
253 					 FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1));
254 
255 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_5,
256 					 PHY_CFG_PLL_PROP_CNTRL_MASK,
257 					 FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10));
258 
259 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_6,
260 					 PHY_CFG_PLL_VCO_CNTRL_MASK,
261 					 FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0));
262 
263 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_CFG_CTRL_5,
264 					 PHY_CFG_PLL_VREF_TUNE_MASK,
265 					 FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1));
266 
267 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL2,
268 					 VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL);
269 
270 	/* set default parameters */
271 	qcom_eusb2_default_parameters(qcom_snps_eusb2);
272 
273 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL2,
274 					 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
275 					 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
276 
277 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM);
278 
279 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL_COMMON0,
280 					 SIDDQ_SEL, SIDDQ_SEL);
281 
282 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL_COMMON0,
283 					 SIDDQ, 0);
284 
285 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_UTMI_CTRL5, POR, 0);
286 
287 	qcom_snps_eusb2_hsphy_write_mask(qcom_snps_eusb2->base, USB_PHY_HS_PHY_CTRL2,
288 					 USB2_SUSPEND_N_SEL, 0);
289 
290 	return 0;
291 }
292 
qcom_snps_eusb2_phy_power_on(struct phy * phy)293 static int qcom_snps_eusb2_phy_power_on(struct phy *phy)
294 {
295 	struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2 = dev_get_priv(phy->dev);
296 	int ret;
297 
298 	/* TODO Repeater */
299 
300 	clk_prepare_enable(qcom_snps_eusb2->ref_clk);
301 
302 	ret = reset_deassert_bulk(&qcom_snps_eusb2->resets);
303 	if (ret)
304 		return ret;
305 
306 	ret = qcom_snps_eusb2_usb_init(phy);
307 	if (ret)
308 		return ret;
309 
310 	return 0;
311 }
312 
qcom_snps_eusb2_phy_power_off(struct phy * phy)313 static int qcom_snps_eusb2_phy_power_off(struct phy *phy)
314 {
315 	struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2 = dev_get_priv(phy->dev);
316 
317 	reset_assert_bulk(&qcom_snps_eusb2->resets);
318 	clk_disable_unprepare(qcom_snps_eusb2->ref_clk);
319 
320 	return 0;
321 }
322 
qcom_snps_eusb2_phy_probe(struct udevice * dev)323 static int qcom_snps_eusb2_phy_probe(struct udevice *dev)
324 {
325 	struct qcom_snps_eusb2_phy_priv *qcom_snps_eusb2 = dev_get_priv(dev);
326 	int ret;
327 
328 	qcom_snps_eusb2->base = (void __iomem *)dev_read_addr(dev);
329 	if (IS_ERR(qcom_snps_eusb2->base))
330 		return PTR_ERR(qcom_snps_eusb2->base);
331 
332 	qcom_snps_eusb2->ref_clk = devm_clk_get(dev, "ref");
333 	if (IS_ERR(qcom_snps_eusb2->ref_clk)) {
334 		ret = PTR_ERR(qcom_snps_eusb2->ref_clk);
335 		printf("%s: failed to get ref clk %d\n", __func__, ret);
336 		return ret;
337 	}
338 
339 	ret = reset_get_bulk(dev, &qcom_snps_eusb2->resets);
340 	if (ret < 0) {
341 		printf("failed to get resets, ret = %d\n", ret);
342 		return ret;
343 	}
344 
345 	return 0;
346 }
347 
348 static struct phy_ops qcom_snps_eusb2_phy_ops = {
349 	.power_on = qcom_snps_eusb2_phy_power_on,
350 	.power_off = qcom_snps_eusb2_phy_power_off,
351 };
352 
353 static const struct udevice_id qcom_snps_eusb2_phy_ids[] = {
354 	{
355 		.compatible = "qcom,sm8550-snps-eusb2-phy",
356 	},
357 	{}
358 };
359 
360 U_BOOT_DRIVER(qcom_usb_qcom_snps_eusb2) = {
361 	.name = "qcom-snps-eusb2-hsphy",
362 	.id = UCLASS_PHY,
363 	.of_match = qcom_snps_eusb2_phy_ids,
364 	.ops = &qcom_snps_eusb2_phy_ops,
365 	.probe = qcom_snps_eusb2_phy_probe,
366 	.priv_auto = sizeof(struct qcom_snps_eusb2_phy_priv),
367 };
368