xref: /linux/drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2009-2018, Linux Foundation. All rights reserved.
4  * Copyright (c) 2018-2020, Linaro Limited
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/io.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_graph.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/reset.h>
18 #include <linux/slab.h>
19 
20 /* PHY register and bit definitions */
21 #define PHY_CTRL_COMMON0		0x078
22 #define SIDDQ				BIT(2)
23 #define PHY_IRQ_CMD			0x0d0
24 #define PHY_INTR_MASK0			0x0d4
25 #define PHY_INTR_CLEAR0			0x0dc
26 #define DPDM_MASK			0x1e
27 #define DP_1_0				BIT(4)
28 #define DP_0_1				BIT(3)
29 #define DM_1_0				BIT(2)
30 #define DM_0_1				BIT(1)
31 
32 enum hsphy_voltage {
33 	VOL_NONE,
34 	VOL_MIN,
35 	VOL_MAX,
36 	VOL_NUM,
37 };
38 
39 enum hsphy_vreg {
40 	VDD,
41 	VDDA_1P8,
42 	VDDA_3P3,
43 	VREG_NUM,
44 };
45 
46 struct hsphy_init_seq {
47 	int offset;
48 	int val;
49 	int delay;
50 };
51 
52 struct hsphy_data {
53 	const struct hsphy_init_seq *init_seq;
54 	unsigned int init_seq_num;
55 };
56 
57 struct hsphy_priv {
58 	void __iomem *base;
59 	struct clk_bulk_data *clks;
60 	int num_clks;
61 	struct reset_control *phy_reset;
62 	struct reset_control *por_reset;
63 	struct regulator_bulk_data vregs[VREG_NUM];
64 	const struct hsphy_data *data;
65 	enum phy_mode mode;
66 };
67 
qcom_snps_hsphy_set_mode(struct phy * phy,enum phy_mode mode,int submode)68 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
69 				    int submode)
70 {
71 	struct hsphy_priv *priv = phy_get_drvdata(phy);
72 
73 	priv->mode = PHY_MODE_INVALID;
74 
75 	if (mode > 0)
76 		priv->mode = mode;
77 
78 	return 0;
79 }
80 
qcom_snps_hsphy_enable_hv_interrupts(struct hsphy_priv * priv)81 static void qcom_snps_hsphy_enable_hv_interrupts(struct hsphy_priv *priv)
82 {
83 	u32 val;
84 
85 	/* Clear any existing interrupts before enabling the interrupts */
86 	val = readb(priv->base + PHY_INTR_CLEAR0);
87 	val |= DPDM_MASK;
88 	writeb(val, priv->base + PHY_INTR_CLEAR0);
89 
90 	writeb(0x0, priv->base + PHY_IRQ_CMD);
91 	usleep_range(200, 220);
92 	writeb(0x1, priv->base + PHY_IRQ_CMD);
93 
94 	/* Make sure the interrupts are cleared */
95 	usleep_range(200, 220);
96 
97 	val = readb(priv->base + PHY_INTR_MASK0);
98 	switch (priv->mode) {
99 	case PHY_MODE_USB_HOST_HS:
100 	case PHY_MODE_USB_HOST_FS:
101 	case PHY_MODE_USB_DEVICE_HS:
102 	case PHY_MODE_USB_DEVICE_FS:
103 		val |= DP_1_0 | DM_0_1;
104 		break;
105 	case PHY_MODE_USB_HOST_LS:
106 	case PHY_MODE_USB_DEVICE_LS:
107 		val |= DP_0_1 | DM_1_0;
108 		break;
109 	default:
110 		/* No device connected */
111 		val |= DP_0_1 | DM_0_1;
112 		break;
113 	}
114 	writeb(val, priv->base + PHY_INTR_MASK0);
115 }
116 
qcom_snps_hsphy_disable_hv_interrupts(struct hsphy_priv * priv)117 static void qcom_snps_hsphy_disable_hv_interrupts(struct hsphy_priv *priv)
118 {
119 	u32 val;
120 
121 	val = readb(priv->base + PHY_INTR_MASK0);
122 	val &= ~DPDM_MASK;
123 	writeb(val, priv->base + PHY_INTR_MASK0);
124 
125 	/* Clear any pending interrupts */
126 	val = readb(priv->base + PHY_INTR_CLEAR0);
127 	val |= DPDM_MASK;
128 	writeb(val, priv->base + PHY_INTR_CLEAR0);
129 
130 	writeb(0x0, priv->base + PHY_IRQ_CMD);
131 	usleep_range(200, 220);
132 
133 	writeb(0x1, priv->base + PHY_IRQ_CMD);
134 	usleep_range(200, 220);
135 }
136 
qcom_snps_hsphy_enter_retention(struct hsphy_priv * priv)137 static void qcom_snps_hsphy_enter_retention(struct hsphy_priv *priv)
138 {
139 	u32 val;
140 
141 	val = readb(priv->base + PHY_CTRL_COMMON0);
142 	val |= SIDDQ;
143 	writeb(val, priv->base + PHY_CTRL_COMMON0);
144 }
145 
qcom_snps_hsphy_exit_retention(struct hsphy_priv * priv)146 static void qcom_snps_hsphy_exit_retention(struct hsphy_priv *priv)
147 {
148 	u32 val;
149 
150 	val = readb(priv->base + PHY_CTRL_COMMON0);
151 	val &= ~SIDDQ;
152 	writeb(val, priv->base + PHY_CTRL_COMMON0);
153 }
154 
qcom_snps_hsphy_power_on(struct phy * phy)155 static int qcom_snps_hsphy_power_on(struct phy *phy)
156 {
157 	struct hsphy_priv *priv = phy_get_drvdata(phy);
158 	int ret;
159 
160 	ret = regulator_bulk_enable(VREG_NUM, priv->vregs);
161 	if (ret)
162 		return ret;
163 
164 	qcom_snps_hsphy_disable_hv_interrupts(priv);
165 	qcom_snps_hsphy_exit_retention(priv);
166 
167 	return 0;
168 }
169 
qcom_snps_hsphy_power_off(struct phy * phy)170 static int qcom_snps_hsphy_power_off(struct phy *phy)
171 {
172 	struct hsphy_priv *priv = phy_get_drvdata(phy);
173 
174 	qcom_snps_hsphy_enter_retention(priv);
175 	qcom_snps_hsphy_enable_hv_interrupts(priv);
176 	regulator_bulk_disable(VREG_NUM, priv->vregs);
177 
178 	return 0;
179 }
180 
qcom_snps_hsphy_reset(struct hsphy_priv * priv)181 static int qcom_snps_hsphy_reset(struct hsphy_priv *priv)
182 {
183 	int ret;
184 
185 	ret = reset_control_assert(priv->phy_reset);
186 	if (ret)
187 		return ret;
188 
189 	usleep_range(10, 15);
190 
191 	ret = reset_control_deassert(priv->phy_reset);
192 	if (ret)
193 		return ret;
194 
195 	usleep_range(80, 100);
196 
197 	return 0;
198 }
199 
qcom_snps_hsphy_init_sequence(struct hsphy_priv * priv)200 static void qcom_snps_hsphy_init_sequence(struct hsphy_priv *priv)
201 {
202 	const struct hsphy_data *data = priv->data;
203 	const struct hsphy_init_seq *seq;
204 	int i;
205 
206 	/* Device match data is optional. */
207 	if (!data)
208 		return;
209 
210 	seq = data->init_seq;
211 
212 	for (i = 0; i < data->init_seq_num; i++, seq++) {
213 		writeb(seq->val, priv->base + seq->offset);
214 		if (seq->delay)
215 			usleep_range(seq->delay, seq->delay + 10);
216 	}
217 }
218 
qcom_snps_hsphy_por_reset(struct hsphy_priv * priv)219 static int qcom_snps_hsphy_por_reset(struct hsphy_priv *priv)
220 {
221 	int ret;
222 
223 	ret = reset_control_assert(priv->por_reset);
224 	if (ret)
225 		return ret;
226 
227 	/*
228 	 * The Femto PHY is POR reset in the following scenarios.
229 	 *
230 	 * 1. After overriding the parameter registers.
231 	 * 2. Low power mode exit from PHY retention.
232 	 *
233 	 * Ensure that SIDDQ is cleared before bringing the PHY
234 	 * out of reset.
235 	 */
236 	qcom_snps_hsphy_exit_retention(priv);
237 
238 	/*
239 	 * As per databook, 10 usec delay is required between
240 	 * PHY POR assert and de-assert.
241 	 */
242 	usleep_range(10, 20);
243 	ret = reset_control_deassert(priv->por_reset);
244 	if (ret)
245 		return ret;
246 
247 	/*
248 	 * As per databook, it takes 75 usec for PHY to stabilize
249 	 * after the reset.
250 	 */
251 	usleep_range(80, 100);
252 
253 	return 0;
254 }
255 
qcom_snps_hsphy_init(struct phy * phy)256 static int qcom_snps_hsphy_init(struct phy *phy)
257 {
258 	struct hsphy_priv *priv = phy_get_drvdata(phy);
259 	int ret;
260 
261 	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
262 	if (ret)
263 		return ret;
264 
265 	ret = qcom_snps_hsphy_reset(priv);
266 	if (ret)
267 		goto disable_clocks;
268 
269 	qcom_snps_hsphy_init_sequence(priv);
270 
271 	ret = qcom_snps_hsphy_por_reset(priv);
272 	if (ret)
273 		goto disable_clocks;
274 
275 	return 0;
276 
277 disable_clocks:
278 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
279 	return ret;
280 }
281 
qcom_snps_hsphy_exit(struct phy * phy)282 static int qcom_snps_hsphy_exit(struct phy *phy)
283 {
284 	struct hsphy_priv *priv = phy_get_drvdata(phy);
285 
286 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
287 
288 	return 0;
289 }
290 
291 static const struct phy_ops qcom_snps_hsphy_ops = {
292 	.init = qcom_snps_hsphy_init,
293 	.exit = qcom_snps_hsphy_exit,
294 	.power_on = qcom_snps_hsphy_power_on,
295 	.power_off = qcom_snps_hsphy_power_off,
296 	.set_mode = qcom_snps_hsphy_set_mode,
297 	.owner = THIS_MODULE,
298 };
299 
300 static const char * const qcom_snps_hsphy_clks[] = {
301 	"ref",
302 	"ahb",
303 	"sleep",
304 };
305 
qcom_snps_hsphy_probe(struct platform_device * pdev)306 static int qcom_snps_hsphy_probe(struct platform_device *pdev)
307 {
308 	struct device *dev = &pdev->dev;
309 	struct phy_provider *provider;
310 	struct hsphy_priv *priv;
311 	struct phy *phy;
312 	int ret;
313 	int i;
314 
315 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
316 	if (!priv)
317 		return -ENOMEM;
318 
319 	priv->base = devm_platform_ioremap_resource(pdev, 0);
320 	if (IS_ERR(priv->base))
321 		return PTR_ERR(priv->base);
322 
323 	priv->num_clks = ARRAY_SIZE(qcom_snps_hsphy_clks);
324 	priv->clks = devm_kcalloc(dev, priv->num_clks, sizeof(*priv->clks),
325 				  GFP_KERNEL);
326 	if (!priv->clks)
327 		return -ENOMEM;
328 
329 	for (i = 0; i < priv->num_clks; i++)
330 		priv->clks[i].id = qcom_snps_hsphy_clks[i];
331 
332 	ret = devm_clk_bulk_get(dev, priv->num_clks, priv->clks);
333 	if (ret)
334 		return ret;
335 
336 	priv->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
337 	if (IS_ERR(priv->phy_reset))
338 		return PTR_ERR(priv->phy_reset);
339 
340 	priv->por_reset = devm_reset_control_get_exclusive(dev, "por");
341 	if (IS_ERR(priv->por_reset))
342 		return PTR_ERR(priv->por_reset);
343 
344 	priv->vregs[VDD].supply = "vdd";
345 	priv->vregs[VDDA_1P8].supply = "vdda1p8";
346 	priv->vregs[VDDA_3P3].supply = "vdda3p3";
347 
348 	ret = devm_regulator_bulk_get(dev, VREG_NUM, priv->vregs);
349 	if (ret)
350 		return ret;
351 
352 	/* Get device match data */
353 	priv->data = device_get_match_data(dev);
354 
355 	phy = devm_phy_create(dev, dev->of_node, &qcom_snps_hsphy_ops);
356 	if (IS_ERR(phy))
357 		return PTR_ERR(phy);
358 
359 	phy_set_drvdata(phy, priv);
360 
361 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
362 	if (IS_ERR(provider))
363 		return PTR_ERR(provider);
364 
365 	ret = regulator_set_load(priv->vregs[VDDA_1P8].consumer, 19000);
366 	if (ret < 0)
367 		return ret;
368 
369 	ret = regulator_set_load(priv->vregs[VDDA_3P3].consumer, 16000);
370 	if (ret < 0)
371 		goto unset_1p8_load;
372 
373 	return 0;
374 
375 unset_1p8_load:
376 	regulator_set_load(priv->vregs[VDDA_1P8].consumer, 0);
377 
378 	return ret;
379 }
380 
381 /*
382  * The macro is used to define an initialization sequence.  Each tuple
383  * is meant to program 'value' into phy register at 'offset' with 'delay'
384  * in us followed.
385  */
386 #define HSPHY_INIT_CFG(o, v, d)	{ .offset = o, .val = v, .delay = d, }
387 
388 static const struct hsphy_init_seq init_seq_femtophy[] = {
389 	HSPHY_INIT_CFG(0xc0, 0x01, 0),
390 	HSPHY_INIT_CFG(0xe8, 0x0d, 0),
391 	HSPHY_INIT_CFG(0x74, 0x12, 0),
392 	HSPHY_INIT_CFG(0x98, 0x63, 0),
393 	HSPHY_INIT_CFG(0x9c, 0x03, 0),
394 	HSPHY_INIT_CFG(0xa0, 0x1d, 0),
395 	HSPHY_INIT_CFG(0xa4, 0x03, 0),
396 	HSPHY_INIT_CFG(0x8c, 0x23, 0),
397 	HSPHY_INIT_CFG(0x78, 0x08, 0),
398 	HSPHY_INIT_CFG(0x7c, 0xdc, 0),
399 	HSPHY_INIT_CFG(0x90, 0xe0, 20),
400 	HSPHY_INIT_CFG(0x74, 0x10, 0),
401 	HSPHY_INIT_CFG(0x90, 0x60, 0),
402 };
403 
404 static const struct hsphy_data hsphy_data_femtophy = {
405 	.init_seq = init_seq_femtophy,
406 	.init_seq_num = ARRAY_SIZE(init_seq_femtophy),
407 };
408 
409 static const struct of_device_id qcom_snps_hsphy_match[] = {
410 	{ .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, },
411 	{ },
412 };
413 MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_match);
414 
415 static struct platform_driver qcom_snps_hsphy_driver = {
416 	.probe = qcom_snps_hsphy_probe,
417 	.driver	= {
418 		.name = "qcom,usb-hs-28nm-phy",
419 		.of_match_table = qcom_snps_hsphy_match,
420 	},
421 };
422 module_platform_driver(qcom_snps_hsphy_driver);
423 
424 MODULE_DESCRIPTION("Qualcomm 28nm Hi-Speed USB PHY driver");
425 MODULE_LICENSE("GPL v2");
426