File Index
Files and directories
Sign in
FILE

phy-snps-eusb2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/phy/phy-snps-eusb2.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2023, Linaro Limited
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/clk.h>
  8#include <linux/delay.h>
  9#include <linux/iopoll.h>
 10#include <linux/mod_devicetable.h>
 11#include <linux/phy/phy.h>
 12#include <linux/platform_device.h>
 13#include <linux/regulator/consumer.h>
 14#include <linux/reset.h>
 15
 16#define EXYNOS_USB_PHY_HS_PHY_CTRL_RST	(0x0)
 17#define USB_PHY_RST_MASK		GENMASK(1, 0)
 18#define UTMI_PORT_RST_MASK		GENMASK(5, 4)
 19
 20#define EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON	(0x4)
 21#define RPTR_MODE			BIT(10)
 22#define FSEL_20_MHZ_VAL			(0x1)
 23#define FSEL_24_MHZ_VAL			(0x2)
 24#define FSEL_26_MHZ_VAL			(0x3)
 25#define FSEL_48_MHZ_VAL			(0x2)
 26
 27#define EXYNOS_USB_PHY_CFG_PLLCFG0	(0x8)
 28#define PHY_CFG_PLL_FB_DIV_19_8_MASK	GENMASK(19, 8)
 29#define DIV_19_8_19_2_MHZ_VAL		(0x170)
 30#define DIV_19_8_20_MHZ_VAL		(0x160)
 31#define DIV_19_8_24_MHZ_VAL		(0x120)
 32#define DIV_19_8_26_MHZ_VAL		(0x107)
 33#define DIV_19_8_48_MHZ_VAL		(0x120)
 34
 35#define EXYNOS_USB_PHY_CFG_PLLCFG1	(0xc)
 36#define EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK	GENMASK(11, 8)
 37#define EXYNOS_DIV_11_8_19_2_MHZ_VAL	(0x0)
 38#define EXYNOS_DIV_11_8_20_MHZ_VAL	(0x0)
 39#define EXYNOS_DIV_11_8_24_MHZ_VAL	(0x0)
 40#define EXYNOS_DIV_11_8_26_MHZ_VAL	(0x0)
 41#define EXYNOS_DIV_11_8_48_MHZ_VAL	(0x1)
 42
 43#define EXYNOS_PHY_CFG_TX		(0x14)
 44#define EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK	GENMASK(2, 1)
 45
 46#define EXYNOS_USB_PHY_UTMI_TESTSE	(0x20)
 47#define TEST_IDDQ			BIT(6)
 48
 49#define QCOM_USB_PHY_UTMI_CTRL0		(0x3c)
 50#define SLEEPM				BIT(0)
 51#define OPMODE_MASK			GENMASK(4, 3)
 52#define OPMODE_NONDRIVING		BIT(3)
 53
 54#define QCOM_USB_PHY_UTMI_CTRL5		(0x50)
 55#define POR				BIT(1)
 56
 57#define QCOM_USB_PHY_HS_PHY_CTRL_COMMON0	(0x54)
 58#define PHY_ENABLE			BIT(0)
 59#define SIDDQ_SEL			BIT(1)
 60#define SIDDQ				BIT(2)
 61#define RETENABLEN			BIT(3)
 62#define FSEL_MASK			GENMASK(6, 4)
 63#define FSEL_19_2_MHZ_VAL		(0x0)
 64#define FSEL_38_4_MHZ_VAL		(0x4)
 65
 66#define QCOM_USB_PHY_CFG_CTRL_1		(0x58)
 67#define PHY_CFG_PLL_CPBIAS_CNTRL_MASK	GENMASK(7, 1)
 68
 69#define QCOM_USB_PHY_CFG_CTRL_2		(0x5c)
 70#define PHY_CFG_PLL_FB_DIV_7_0_MASK	GENMASK(7, 0)
 71#define DIV_7_0_19_2_MHZ_VAL		(0x90)
 72#define DIV_7_0_38_4_MHZ_VAL		(0xc8)
 73
 74#define QCOM_USB_PHY_CFG_CTRL_3		(0x60)
 75#define PHY_CFG_PLL_FB_DIV_11_8_MASK	GENMASK(3, 0)
 76#define DIV_11_8_19_2_MHZ_VAL		(0x1)
 77#define DIV_11_8_38_4_MHZ_VAL		(0x0)
 78
 79#define PHY_CFG_PLL_REF_DIV		GENMASK(7, 4)
 80#define PLL_REF_DIV_VAL			(0x0)
 81
 82#define QCOM_USB_PHY_HS_PHY_CTRL2	(0x64)
 83#define VBUSVLDEXT0			BIT(0)
 84#define USB2_SUSPEND_N			BIT(2)
 85#define USB2_SUSPEND_N_SEL		BIT(3)
 86#define VBUS_DET_EXT_SEL		BIT(4)
 87
 88#define QCOM_USB_PHY_CFG_CTRL_4		(0x68)
 89#define PHY_CFG_PLL_GMP_CNTRL_MASK	GENMASK(1, 0)
 90#define PHY_CFG_PLL_INT_CNTRL_MASK	GENMASK(7, 2)
 91
 92#define QCOM_USB_PHY_CFG_CTRL_5		(0x6c)
 93#define PHY_CFG_PLL_PROP_CNTRL_MASK	GENMASK(4, 0)
 94#define PHY_CFG_PLL_VREF_TUNE_MASK	GENMASK(7, 6)
 95
 96#define QCOM_USB_PHY_CFG_CTRL_6		(0x70)
 97#define PHY_CFG_PLL_VCO_CNTRL_MASK	GENMASK(2, 0)
 98
 99#define QCOM_USB_PHY_CFG_CTRL_7		(0x74)
100
101#define QCOM_USB_PHY_CFG_CTRL_8		(0x78)
102#define PHY_CFG_TX_FSLS_VREF_TUNE_MASK	GENMASK(1, 0)
103#define PHY_CFG_TX_FSLS_VREG_BYPASS	BIT(2)
104#define PHY_CFG_TX_HS_VREF_TUNE_MASK	GENMASK(5, 3)
105#define PHY_CFG_TX_HS_XV_TUNE_MASK	GENMASK(7, 6)
106
107#define QCOM_USB_PHY_CFG_CTRL_9		(0x7c)
108#define PHY_CFG_TX_PREEMP_TUNE_MASK	GENMASK(2, 0)
109#define PHY_CFG_TX_RES_TUNE_MASK	GENMASK(4, 3)
110#define PHY_CFG_TX_RISE_TUNE_MASK	GENMASK(6, 5)
111#define PHY_CFG_RCAL_BYPASS		BIT(7)
112
113#define QCOM_USB_PHY_CFG_CTRL_10	(0x80)
114
115#define QCOM_USB_PHY_CFG0		(0x94)
116#define DATAPATH_CTRL_OVERRIDE_EN	BIT(0)
117#define CMN_CTRL_OVERRIDE_EN		BIT(1)
118
119#define QCOM_UTMI_PHY_CMN_CTRL0		(0x98)
120#define TESTBURNIN			BIT(6)
121
122#define QCOM_USB_PHY_FSEL_SEL		(0xb8)
123#define FSEL_SEL			BIT(0)
124
125#define QCOM_USB_PHY_APB_ACCESS_CMD	(0x130)
126#define RW_ACCESS			BIT(0)
127#define APB_START_CMD			BIT(1)
128#define APB_LOGIC_RESET			BIT(2)
129
130#define QCOM_USB_PHY_APB_ACCESS_STATUS	(0x134)
131#define ACCESS_DONE			BIT(0)
132#define TIMED_OUT			BIT(1)
133#define ACCESS_ERROR			BIT(2)
134#define ACCESS_IN_PROGRESS		BIT(3)
135
136#define QCOM_USB_PHY_APB_ADDRESS	(0x138)
137#define APB_REG_ADDR_MASK		GENMASK(7, 0)
138
139#define QCOM_USB_PHY_APB_WRDATA_LSB	(0x13c)
140#define APB_REG_WRDATA_7_0_MASK		GENMASK(3, 0)
141
142#define QCOM_USB_PHY_APB_WRDATA_MSB	(0x140)
143#define APB_REG_WRDATA_15_8_MASK	GENMASK(7, 4)
144
145#define QCOM_USB_PHY_APB_RDDATA_LSB	(0x144)
146#define APB_REG_RDDATA_7_0_MASK		GENMASK(3, 0)
147
148#define QCOM_USB_PHY_APB_RDDATA_MSB	(0x148)
149#define APB_REG_RDDATA_15_8_MASK	GENMASK(7, 4)
150
151static const char * const eusb2_hsphy_vreg_names[] = {
152	"vdd", "vdda12",
153};
154
155#define EUSB2_NUM_VREGS		ARRAY_SIZE(eusb2_hsphy_vreg_names)
156
157struct snps_eusb2_phy_drvdata {
158	int (*phy_init)(struct phy *p);
159	const char * const *clk_names;
160	int num_clks;
161};
162
163struct snps_eusb2_hsphy {
164	struct phy *phy;
165	void __iomem *base;
166
167	struct clk *ref_clk;
168	struct clk_bulk_data *clks;
169	struct reset_control *phy_reset;
170
171	struct regulator_bulk_data vregs[EUSB2_NUM_VREGS];
172
173	enum phy_mode mode;
174
175	struct phy *repeater;
176
177	const struct snps_eusb2_phy_drvdata *data;
178};
179
180static int snps_eusb2_hsphy_set_mode(struct phy *p, enum phy_mode mode, int submode)
181{
182	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
183
184	phy->mode = mode;
185
186	return phy_set_mode_ext(phy->repeater, mode, submode);
187}
188
189static void snps_eusb2_hsphy_write_mask(void __iomem *base, u32 offset,
190					u32 mask, u32 val)
191{
192	u32 reg;
193
194	reg = readl_relaxed(base + offset);
195	reg &= ~mask;
196	reg |= val & mask;
197	writel_relaxed(reg, base + offset);
198
199	/* Ensure above write is completed */
200	readl_relaxed(base + offset);
201}
202
203static void qcom_eusb2_default_parameters(struct snps_eusb2_hsphy *phy)
204{
205	/* default parameters: tx pre-emphasis */
206	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
207				    PHY_CFG_TX_PREEMP_TUNE_MASK,
208				    FIELD_PREP(PHY_CFG_TX_PREEMP_TUNE_MASK, 0));
209
210	/* tx rise/fall time */
211	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
212				    PHY_CFG_TX_RISE_TUNE_MASK,
213				    FIELD_PREP(PHY_CFG_TX_RISE_TUNE_MASK, 0x2));
214
215	/* source impedance adjustment */
216	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_9,
217				    PHY_CFG_TX_RES_TUNE_MASK,
218				    FIELD_PREP(PHY_CFG_TX_RES_TUNE_MASK, 0x1));
219
220	/* dc voltage level adjustement */
221	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_8,
222				    PHY_CFG_TX_HS_VREF_TUNE_MASK,
223				    FIELD_PREP(PHY_CFG_TX_HS_VREF_TUNE_MASK, 0x3));
224
225	/* transmitter HS crossover adjustement */
226	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_8,
227				    PHY_CFG_TX_HS_XV_TUNE_MASK,
228				    FIELD_PREP(PHY_CFG_TX_HS_XV_TUNE_MASK, 0x0));
229}
230
231struct snps_eusb2_ref_clk {
232	unsigned long freq;
233	u32 fsel_val;
234	u32 div_7_0_val;
235	u32 div_11_8_val;
236};
237
238static const struct snps_eusb2_ref_clk exynos_eusb2_ref_clk[] = {
239	{ 19200000, FSEL_19_2_MHZ_VAL, DIV_19_8_19_2_MHZ_VAL, EXYNOS_DIV_11_8_19_2_MHZ_VAL },
240	{ 20000000, FSEL_20_MHZ_VAL, DIV_19_8_20_MHZ_VAL, EXYNOS_DIV_11_8_20_MHZ_VAL },
241	{ 24000000, FSEL_24_MHZ_VAL, DIV_19_8_24_MHZ_VAL, EXYNOS_DIV_11_8_24_MHZ_VAL },
242	{ 26000000, FSEL_26_MHZ_VAL, DIV_19_8_26_MHZ_VAL, EXYNOS_DIV_11_8_26_MHZ_VAL },
243	{ 48000000, FSEL_48_MHZ_VAL, DIV_19_8_48_MHZ_VAL, EXYNOS_DIV_11_8_48_MHZ_VAL },
244};
245
246static int exynos_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
247{
248	const struct snps_eusb2_ref_clk *config = NULL;
249	unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk);
250
251	for (int i = 0; i < ARRAY_SIZE(exynos_eusb2_ref_clk); i++) {
252		if (exynos_eusb2_ref_clk[i].freq == ref_clk_freq) {
253			config = &exynos_eusb2_ref_clk[i];
254			break;
255		}
256	}
257
258	if (!config) {
259		dev_err(&phy->phy->dev, "unsupported ref_clk_freq: %lu\n", ref_clk_freq);
260		return -EINVAL;
261	}
262
263	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
264				    FSEL_MASK,
265				    FIELD_PREP(FSEL_MASK, config->fsel_val));
266
267	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_CFG_PLLCFG0,
268				    PHY_CFG_PLL_FB_DIV_19_8_MASK,
269				    FIELD_PREP(PHY_CFG_PLL_FB_DIV_19_8_MASK,
270					       config->div_7_0_val));
271
272	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_CFG_PLLCFG1,
273				    EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK,
274				    config->div_11_8_val);
275	return 0;
276}
277
278static const struct snps_eusb2_ref_clk qcom_eusb2_ref_clk[] = {
279	{ 19200000, FSEL_19_2_MHZ_VAL, DIV_7_0_19_2_MHZ_VAL, DIV_11_8_19_2_MHZ_VAL },
280	{ 38400000, FSEL_38_4_MHZ_VAL, DIV_7_0_38_4_MHZ_VAL, DIV_11_8_38_4_MHZ_VAL },
281};
282
283static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
284{
285	const struct snps_eusb2_ref_clk *config = NULL;
286	unsigned long ref_clk_freq = clk_get_rate(phy->ref_clk);
287
288	for (int i = 0; i < ARRAY_SIZE(qcom_eusb2_ref_clk); i++) {
289		if (qcom_eusb2_ref_clk[i].freq == ref_clk_freq) {
290			config = &qcom_eusb2_ref_clk[i];
291			break;
292		}
293	}
294
295	if (!config) {
296		dev_err(&phy->phy->dev, "unsupported ref_clk_freq: %lu\n", ref_clk_freq);
297		return -EINVAL;
298	}
299
300	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
301				    FSEL_MASK,
302				    FIELD_PREP(FSEL_MASK, config->fsel_val));
303
304	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_2,
305				    PHY_CFG_PLL_FB_DIV_7_0_MASK,
306				    config->div_7_0_val);
307
308	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
309				    PHY_CFG_PLL_FB_DIV_11_8_MASK,
310				    config->div_11_8_val);
311
312	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_3,
313				    PHY_CFG_PLL_REF_DIV, PLL_REF_DIV_VAL);
314
315	return 0;
316}
317
318static int exynos_snps_eusb2_hsphy_init(struct phy *p)
319{
320	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
321	int ret;
322
323	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
324				    USB_PHY_RST_MASK | UTMI_PORT_RST_MASK,
325				    USB_PHY_RST_MASK | UTMI_PORT_RST_MASK);
326	fsleep(50); /* required after holding phy in reset */
327
328	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
329				    RPTR_MODE, RPTR_MODE);
330
331	/* update ref_clk related registers */
332	ret = exynos_eusb2_ref_clk_init(phy);
333	if (ret)
334		return ret;
335
336	/* default parameter: tx fsls-vref */
337	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_PHY_CFG_TX,
338				    EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK,
339				    FIELD_PREP(EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK, 0x0));
340
341	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_UTMI_TESTSE,
342				    TEST_IDDQ, 0);
343	fsleep(10); /* required after releasing test_iddq */
344
345	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
346				    USB_PHY_RST_MASK, 0);
347
348	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON,
349				    PHY_ENABLE, PHY_ENABLE);
350
351	snps_eusb2_hsphy_write_mask(phy->base, EXYNOS_USB_PHY_HS_PHY_CTRL_RST,
352				    UTMI_PORT_RST_MASK, 0);
353
354	return 0;
355}
356
357static const char * const exynos_eusb2_hsphy_clock_names[] = {
358	"ref", "bus", "ctrl",
359};
360
361static const struct snps_eusb2_phy_drvdata exynos2200_snps_eusb2_phy = {
362	.phy_init	= exynos_snps_eusb2_hsphy_init,
363	.clk_names	= exynos_eusb2_hsphy_clock_names,
364	.num_clks	= ARRAY_SIZE(exynos_eusb2_hsphy_clock_names),
365};
366
367static int qcom_snps_eusb2_hsphy_init(struct phy *p)
368{
369	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
370	int ret;
371
372	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG0,
373				    CMN_CTRL_OVERRIDE_EN, CMN_CTRL_OVERRIDE_EN);
374
375	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL5, POR, POR);
376
377	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
378				    PHY_ENABLE | RETENABLEN, PHY_ENABLE | RETENABLEN);
379
380	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_APB_ACCESS_CMD,
381				    APB_LOGIC_RESET, APB_LOGIC_RESET);
382
383	snps_eusb2_hsphy_write_mask(phy->base, QCOM_UTMI_PHY_CMN_CTRL0, TESTBURNIN, 0);
384
385	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_FSEL_SEL,
386				    FSEL_SEL, FSEL_SEL);
387
388	/* update ref_clk related registers */
389	ret = qcom_eusb2_ref_clk_init(phy);
390	if (ret)
391		return ret;
392
393	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_1,
394				    PHY_CFG_PLL_CPBIAS_CNTRL_MASK,
395				    FIELD_PREP(PHY_CFG_PLL_CPBIAS_CNTRL_MASK, 0x0));
396
397	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_4,
398				    PHY_CFG_PLL_INT_CNTRL_MASK,
399				    FIELD_PREP(PHY_CFG_PLL_INT_CNTRL_MASK, 0x8));
400
401	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_4,
402				    PHY_CFG_PLL_GMP_CNTRL_MASK,
403				    FIELD_PREP(PHY_CFG_PLL_GMP_CNTRL_MASK, 0x1));
404
405	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_5,
406				    PHY_CFG_PLL_PROP_CNTRL_MASK,
407				    FIELD_PREP(PHY_CFG_PLL_PROP_CNTRL_MASK, 0x10));
408
409	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_6,
410				    PHY_CFG_PLL_VCO_CNTRL_MASK,
411				    FIELD_PREP(PHY_CFG_PLL_VCO_CNTRL_MASK, 0x0));
412
413	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG_CTRL_5,
414				    PHY_CFG_PLL_VREF_TUNE_MASK,
415				    FIELD_PREP(PHY_CFG_PLL_VREF_TUNE_MASK, 0x1));
416
417	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
418				    VBUS_DET_EXT_SEL, VBUS_DET_EXT_SEL);
419
420	/* set default parameters */
421	qcom_eusb2_default_parameters(phy);
422
423	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
424				    USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
425				    USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
426
427	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL0, SLEEPM, SLEEPM);
428
429	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
430				    SIDDQ_SEL, SIDDQ_SEL);
431
432	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL_COMMON0,
433				    SIDDQ, 0);
434
435	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_UTMI_CTRL5, POR, 0);
436
437	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2,
438				    USB2_SUSPEND_N_SEL, 0);
439
440	snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG0,
441				    CMN_CTRL_OVERRIDE_EN, 0);
442
443	return 0;
444}
445
446static const char * const qcom_eusb2_hsphy_clock_names[] = {
447	"ref",
448};
449
450static const struct snps_eusb2_phy_drvdata sm8550_snps_eusb2_phy = {
451	.phy_init	= qcom_snps_eusb2_hsphy_init,
452	.clk_names      = qcom_eusb2_hsphy_clock_names,
453	.num_clks       = ARRAY_SIZE(qcom_eusb2_hsphy_clock_names),
454};
455
456static int snps_eusb2_hsphy_init(struct phy *p)
457{
458	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
459	int ret;
460
461	ret = regulator_bulk_enable(ARRAY_SIZE(phy->vregs), phy->vregs);
462	if (ret)
463		return ret;
464
465	ret = phy_init(phy->repeater);
466	if (ret) {
467		dev_err(&p->dev, "repeater init failed: %d\n", ret);
468		goto disable_vreg;
469	}
470
471	ret = clk_bulk_prepare_enable(phy->data->num_clks, phy->clks);
472	if (ret) {
473		dev_err(&p->dev, "failed to enable ref clock: %d\n", ret);
474		goto exit_repeater;
475	}
476
477	ret = reset_control_assert(phy->phy_reset);
478	if (ret) {
479		dev_err(&p->dev, "failed to assert phy_reset: %d\n", ret);
480		goto disable_clks;
481	}
482
483	usleep_range(100, 150);
484
485	ret = reset_control_deassert(phy->phy_reset);
486	if (ret) {
487		dev_err(&p->dev, "failed to de-assert phy_reset: %d\n", ret);
488		goto disable_clks;
489	}
490
491	ret = phy->data->phy_init(p);
492	if (ret)
493		goto disable_clks;
494
495	return 0;
496
497disable_clks:
498	clk_bulk_disable_unprepare(phy->data->num_clks, phy->clks);
499exit_repeater:
500	phy_exit(phy->repeater);
501disable_vreg:
502	regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs);
503
504	return ret;
505}
506
507static int snps_eusb2_hsphy_exit(struct phy *p)
508{
509	struct snps_eusb2_hsphy *phy = phy_get_drvdata(p);
510
511	clk_bulk_disable_unprepare(phy->data->num_clks, phy->clks);
512
513	regulator_bulk_disable(ARRAY_SIZE(phy->vregs), phy->vregs);
514
515	phy_exit(phy->repeater);
516
517	return 0;
518}
519
520static const struct phy_ops snps_eusb2_hsphy_ops = {
521	.init		= snps_eusb2_hsphy_init,
522	.exit		= snps_eusb2_hsphy_exit,
523	.set_mode	= snps_eusb2_hsphy_set_mode,
524	.owner		= THIS_MODULE,
525};
526
527static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
528{
529	struct device *dev = &pdev->dev;
530	struct device_node *np = dev->of_node;
531	struct snps_eusb2_hsphy *phy;
532	struct phy_provider *phy_provider;
533	struct phy *generic_phy;
534	int ret, i;
535	int num;
536
537	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
538	if (!phy)
539		return -ENOMEM;
540
541	phy->data = device_get_match_data(dev);
542	if (!phy->data)
543		return -EINVAL;
544
545	phy->base = devm_platform_ioremap_resource(pdev, 0);
546	if (IS_ERR(phy->base))
547		return PTR_ERR(phy->base);
548
549	phy->phy_reset = devm_reset_control_get_optional_exclusive(dev, NULL);
550	if (IS_ERR(phy->phy_reset))
551		return PTR_ERR(phy->phy_reset);
552
553	phy->clks = devm_kcalloc(dev, phy->data->num_clks, sizeof(*phy->clks),
554				 GFP_KERNEL);
555	if (!phy->clks)
556		return -ENOMEM;
557
558	for (i = 0; i < phy->data->num_clks; ++i)
559		phy->clks[i].id = phy->data->clk_names[i];
560
561	ret = devm_clk_bulk_get(dev, phy->data->num_clks, phy->clks);
562	if (ret)
563		return dev_err_probe(dev, ret,
564				     "failed to get phy clock(s)\n");
565
566	phy->ref_clk = NULL;
567	for (i = 0; i < phy->data->num_clks; ++i) {
568		if (!strcmp(phy->clks[i].id, "ref")) {
569			phy->ref_clk = phy->clks[i].clk;
570			break;
571		}
572	}
573
574	if (IS_ERR_OR_NULL(phy->ref_clk)) {
575		ret = phy->ref_clk ? PTR_ERR(phy->ref_clk) : -ENOENT;
576		return dev_err_probe(dev, ret,
577				     "failed to get ref clk\n");
578	}
579
580	num = ARRAY_SIZE(phy->vregs);
581	for (i = 0; i < num; i++)
582		phy->vregs[i].supply = eusb2_hsphy_vreg_names[i];
583
584	ret = devm_regulator_bulk_get(dev, num, phy->vregs);
585	if (ret)
586		return dev_err_probe(dev, ret,
587				     "failed to get regulator supplies\n");
588
589	phy->repeater = devm_of_phy_optional_get(dev, np, NULL);
590	if (IS_ERR(phy->repeater))
591		return dev_err_probe(dev, PTR_ERR(phy->repeater),
592				     "failed to get repeater\n");
593
594	generic_phy = devm_phy_create(dev, NULL, &snps_eusb2_hsphy_ops);
595	if (IS_ERR(generic_phy)) {
596		dev_err(dev, "failed to create phy: %d\n", ret);
597		return PTR_ERR(generic_phy);
598	}
599
600	dev_set_drvdata(dev, phy);
601	phy_set_drvdata(generic_phy, phy);
602
603	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
604	if (IS_ERR(phy_provider))
605		return PTR_ERR(phy_provider);
606
607	return 0;
608}
609
610static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
611	{
612		.compatible = "qcom,sm8550-snps-eusb2-phy",
613		.data = &sm8550_snps_eusb2_phy,
614	}, {
615		.compatible = "samsung,exynos2200-eusb2-phy",
616		.data = &exynos2200_snps_eusb2_phy,
617	}, {
618		/* sentinel */
619	}
620};
621MODULE_DEVICE_TABLE(of, snps_eusb2_hsphy_of_match_table);
622
623static struct platform_driver snps_eusb2_hsphy_driver = {
624	.probe		= snps_eusb2_hsphy_probe,
625	.driver = {
626		.name	= "snps-eusb2-hsphy",
627		.of_match_table = snps_eusb2_hsphy_of_match_table,
628	},
629};
630
631module_platform_driver(snps_eusb2_hsphy_driver);
632MODULE_DESCRIPTION("Synopsys eUSB2 HS PHY driver");
633MODULE_LICENSE("GPL");
~/ Read-only file preview.