1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk.h>
7#include <linux/delay.h>
8#include <linux/err.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_device.h>
14#include <linux/phy/phy.h>
15#include <linux/platform_device.h>
16#include <linux/regmap.h>
17#include <linux/regulator/consumer.h>
18#include <linux/reset.h>
19#include <linux/slab.h>
20
21#define USB2_PHY_USB_PHY_UTMI_CTRL0		(0x3c)
22#define SLEEPM					BIT(0)
23#define OPMODE_MASK				GENMASK(4, 3)
24#define OPMODE_NORMAL				(0x00)
25#define OPMODE_NONDRIVING			BIT(3)
26#define TERMSEL					BIT(5)
27
28#define USB2_PHY_USB_PHY_UTMI_CTRL1		(0x40)
29#define XCVRSEL					BIT(0)
30
31#define USB2_PHY_USB_PHY_UTMI_CTRL5		(0x50)
32#define POR					BIT(1)
33
34#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
35#define RETENABLEN				BIT(3)
36#define FSEL_MASK				GENMASK(6, 4)
37#define FSEL_DEFAULT				(0x3 << 4)
38
39#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1	(0x58)
40#define VBUSVLDEXTSEL0				BIT(4)
41#define PLLBTUNE				BIT(5)
42
43#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2	(0x5c)
44#define VREGBYPASS				BIT(0)
45
46#define USB2_PHY_USB_PHY_HS_PHY_CTRL1		(0x60)
47#define VBUSVLDEXT0				BIT(0)
48
49#define USB2_PHY_USB_PHY_HS_PHY_CTRL2		(0x64)
50#define USB2_AUTO_RESUME			BIT(0)
51#define USB2_SUSPEND_N				BIT(2)
52#define USB2_SUSPEND_N_SEL			BIT(3)
53
54#define USB2_PHY_USB_PHY_CFG0			(0x94)
55#define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN	BIT(0)
56#define UTMI_PHY_CMN_CTRL_OVERRIDE_EN		BIT(1)
57
58#define USB2_PHY_USB_PHY_REFCLK_CTRL		(0xa0)
59#define REFCLK_SEL_MASK				GENMASK(1, 0)
60#define REFCLK_SEL_DEFAULT			(0x2 << 0)
61
62static const char * const qcom_snps_hsphy_vreg_names[] = {
63	"vdda-pll", "vdda33", "vdda18",
64};
65
66#define SNPS_HS_NUM_VREGS		ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
67
68/**
69 * struct qcom_snps_hsphy - snps hs phy attributes
70 *
71 * @dev: device structure
72 *
73 * @phy: generic phy
74 * @base: iomapped memory space for snps hs phy
75 *
76 * @num_clks: number of clocks
77 * @clks: array of clocks
78 * @phy_reset: phy reset control
79 * @vregs: regulator supplies bulk data
80 * @phy_initialized: if PHY has been initialized correctly
81 * @mode: contains the current mode the PHY is in
82 * @update_seq_cfg: tuning parameters for phy init
83 */
84struct qcom_snps_hsphy {
85	struct device *dev;
86
87	struct phy *phy;
88	void __iomem *base;
89
90	int num_clks;
91	struct clk_bulk_data *clks;
92	struct reset_control *phy_reset;
93	struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
94
95	bool phy_initialized;
96	enum phy_mode mode;
97};
98
99static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
100{
101	struct device *dev = hsphy->dev;
102
103	hsphy->num_clks = 2;
104	hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
105	if (!hsphy->clks)
106		return -ENOMEM;
107
108	/*
109	 * TODO: Currently no device tree instantiation of the PHY is using the clock.
110	 * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
111	 */
112	hsphy->clks[0].id = "cfg_ahb";
113	hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
114	if (IS_ERR(hsphy->clks[0].clk))
115		return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
116				     "failed to get cfg_ahb clk\n");
117
118	hsphy->clks[1].id = "ref";
119	hsphy->clks[1].clk = devm_clk_get(dev, "ref");
120	if (IS_ERR(hsphy->clks[1].clk))
121		return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
122				     "failed to get ref clk\n");
123
124	return 0;
125}
126
127static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
128						u32 mask, u32 val)
129{
130	u32 reg;
131
132	reg = readl_relaxed(base + offset);
133	reg &= ~mask;
134	reg |= val & mask;
135	writel_relaxed(reg, base + offset);
136
137	/* Ensure above write is completed */
138	readl_relaxed(base + offset);
139}
140
141static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
142{
143	dev_dbg(&hsphy->phy->dev, "Suspend QCOM SNPS PHY\n");
144
145	if (hsphy->mode == PHY_MODE_USB_HOST) {
146		/* Enable auto-resume to meet remote wakeup timing */
147		qcom_snps_hsphy_write_mask(hsphy->base,
148					   USB2_PHY_USB_PHY_HS_PHY_CTRL2,
149					   USB2_AUTO_RESUME,
150					   USB2_AUTO_RESUME);
151		usleep_range(500, 1000);
152		qcom_snps_hsphy_write_mask(hsphy->base,
153					   USB2_PHY_USB_PHY_HS_PHY_CTRL2,
154					   0, USB2_AUTO_RESUME);
155	}
156
157	return 0;
158}
159
160static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
161{
162	dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
163
164	return 0;
165}
166
167static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
168{
169	struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
170
171	if (!hsphy->phy_initialized)
172		return 0;
173
174	return qcom_snps_hsphy_suspend(hsphy);
175}
176
177static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
178{
179	struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
180
181	if (!hsphy->phy_initialized)
182		return 0;
183
184	return qcom_snps_hsphy_resume(hsphy);
185}
186
187static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
188				    int submode)
189{
190	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
191
192	hsphy->mode = mode;
193	return 0;
194}
195
196static int qcom_snps_hsphy_init(struct phy *phy)
197{
198	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
199	int ret;
200
201	dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
202
203	ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
204	if (ret)
205		return ret;
206
207	ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
208	if (ret) {
209		dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
210		goto poweroff_phy;
211	}
212
213	ret = reset_control_assert(hsphy->phy_reset);
214	if (ret) {
215		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
216		goto disable_clks;
217	}
218
219	usleep_range(100, 150);
220
221	ret = reset_control_deassert(hsphy->phy_reset);
222	if (ret) {
223		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
224		goto disable_clks;
225	}
226
227	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
228					UTMI_PHY_CMN_CTRL_OVERRIDE_EN,
229					UTMI_PHY_CMN_CTRL_OVERRIDE_EN);
230	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
231							POR, POR);
232	qcom_snps_hsphy_write_mask(hsphy->base,
233					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
234					FSEL_MASK, 0);
235	qcom_snps_hsphy_write_mask(hsphy->base,
236					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
237					PLLBTUNE, PLLBTUNE);
238	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL,
239					REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK);
240	qcom_snps_hsphy_write_mask(hsphy->base,
241					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
242					VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
243	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
244					VBUSVLDEXT0, VBUSVLDEXT0);
245
246	qcom_snps_hsphy_write_mask(hsphy->base,
247					USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
248					VREGBYPASS, VREGBYPASS);
249
250	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
251					USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
252					USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
253
254	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0,
255					SLEEPM, SLEEPM);
256
257	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
258					POR, 0);
259
260	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
261					USB2_SUSPEND_N_SEL, 0);
262
263	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
264					UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0);
265
266	hsphy->phy_initialized = true;
267
268	return 0;
269
270disable_clks:
271	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
272poweroff_phy:
273	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
274
275	return ret;
276}
277
278static int qcom_snps_hsphy_exit(struct phy *phy)
279{
280	struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
281
282	reset_control_assert(hsphy->phy_reset);
283	clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
284	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
285	hsphy->phy_initialized = false;
286
287	return 0;
288}
289
290static const struct phy_ops qcom_snps_hsphy_gen_ops = {
291	.init		= qcom_snps_hsphy_init,
292	.exit		= qcom_snps_hsphy_exit,
293	.set_mode	= qcom_snps_hsphy_set_mode,
294	.owner		= THIS_MODULE,
295};
296
297static const struct of_device_id qcom_snps_hsphy_of_match_table[] = {
298	{ .compatible	= "qcom,sm8150-usb-hs-phy", },
299	{ .compatible	= "qcom,usb-snps-hs-7nm-phy", },
300	{ .compatible	= "qcom,usb-snps-femto-v2-phy",	},
301	{ }
302};
303MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table);
304
305static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = {
306	SET_RUNTIME_PM_OPS(qcom_snps_hsphy_runtime_suspend,
307			   qcom_snps_hsphy_runtime_resume, NULL)
308};
309
310static int qcom_snps_hsphy_probe(struct platform_device *pdev)
311{
312	struct device *dev = &pdev->dev;
313	struct qcom_snps_hsphy *hsphy;
314	struct phy_provider *phy_provider;
315	struct phy *generic_phy;
316	int ret, i;
317	int num;
318
319	hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL);
320	if (!hsphy)
321		return -ENOMEM;
322
323	hsphy->dev = dev;
324
325	hsphy->base = devm_platform_ioremap_resource(pdev, 0);
326	if (IS_ERR(hsphy->base))
327		return PTR_ERR(hsphy->base);
328
329	ret = qcom_snps_hsphy_clk_init(hsphy);
330	if (ret)
331		return dev_err_probe(dev, ret, "failed to initialize clocks\n");
332
333	hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
334	if (IS_ERR(hsphy->phy_reset)) {
335		dev_err(dev, "failed to get phy core reset\n");
336		return PTR_ERR(hsphy->phy_reset);
337	}
338
339	num = ARRAY_SIZE(hsphy->vregs);
340	for (i = 0; i < num; i++)
341		hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i];
342
343	ret = devm_regulator_bulk_get(dev, num, hsphy->vregs);
344	if (ret)
345		return dev_err_probe(dev, ret,
346				     "failed to get regulator supplies\n");
347
348	pm_runtime_set_active(dev);
349	pm_runtime_enable(dev);
350	/*
351	 * Prevent runtime pm from being ON by default. Users can enable
352	 * it using power/control in sysfs.
353	 */
354	pm_runtime_forbid(dev);
355
356	generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops);
357	if (IS_ERR(generic_phy)) {
358		ret = PTR_ERR(generic_phy);
359		dev_err(dev, "failed to create phy, %d\n", ret);
360		return ret;
361	}
362	hsphy->phy = generic_phy;
363
364	dev_set_drvdata(dev, hsphy);
365	phy_set_drvdata(generic_phy, hsphy);
366
367	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
368	if (!IS_ERR(phy_provider))
369		dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
370	else
371		pm_runtime_disable(dev);
372
373	return PTR_ERR_OR_ZERO(phy_provider);
374}
375
376static struct platform_driver qcom_snps_hsphy_driver = {
377	.probe		= qcom_snps_hsphy_probe,
378	.driver = {
379		.name	= "qcom-snps-hs-femto-v2-phy",
380		.pm = &qcom_snps_hsphy_pm_ops,
381		.of_match_table = qcom_snps_hsphy_of_match_table,
382	},
383};
384
385module_platform_driver(qcom_snps_hsphy_driver);
386
387MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver");
388MODULE_LICENSE("GPL v2");
389