1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Stefan Roese <sr@denx.de>
4 *
5 * Derived from linux/drivers/phy/ralink/phy-ralink-usb.c
6 *     Copyright (C) 2017 John Crispin <john@phrozen.org>
7 */
8
9#include <clk.h>
10#include <dm.h>
11#include <generic-phy.h>
12#include <log.h>
13#include <reset.h>
14#include <asm/io.h>
15#include <linux/bitops.h>
16#include <linux/delay.h>
17
18#define OFS_U2_PHY_AC0			0x800
19#define USBPLL_FBDIV_S			16
20#define USBPLL_FBDIV_M			GENMASK(22, 16)
21#define BG_TRIM_S			8
22#define BG_TRIM_M			GENMASK(11, 8)
23#define BG_RBSEL_S			6
24#define BG_RBSEL_M			GENMASK(7, 6)
25#define BG_RASEL_S			4
26#define BG_RASEL_M			GENMASK(5, 4)
27#define BGR_DIV_S			2
28#define BGR_DIV_M			GENMASK(3, 2)
29#define CHP_EN				BIT(1)
30
31#define OFS_U2_PHY_AC1			0x804
32#define VRT_VREF_SEL_S			28
33#define VRT_VREF_SEL_M			GENMASK(30, 28)
34#define TERM_VREF_SEL_S			24
35#define TERM_VREF_SEL_M			GENMASK(26, 24)
36#define USBPLL_RSVD			BIT(4)
37#define USBPLL_ACCEN			BIT(3)
38#define USBPLL_LF			BIT(2)
39
40#define OFS_U2_PHY_AC2			0x808
41
42#define OFS_U2_PHY_ACR0			0x810
43#define HSTX_SRCAL_EN			BIT(23)
44#define HSTX_SRCTRL_S			16
45#define HSTX_SRCTRL_M			GENMASK(18, 16)
46
47#define OFS_U2_PHY_ACR3			0x81C
48#define HSTX_DBIST_S			28
49#define HSTX_DBIST_M			GENMASK(31, 28)
50#define HSRX_BIAS_EN_SEL_S		20
51#define HSRX_BIAS_EN_SEL_M		GENMASK(21, 20)
52
53#define OFS_U2_PHY_DCR0			0x860
54#define PHYD_RESERVE_S			8
55#define PHYD_RESERVE_M			GENMASK(23, 8)
56#define CDR_FILT_S			0
57#define CDR_FILT_M			GENMASK(3, 0)
58
59#define OFS_U2_PHY_DTM0			0x868
60#define FORCE_USB_CLKEN			BIT(25)
61
62#define OFS_FM_CR0			0xf00
63#define FREQDET_EN			BIT(24)
64#define CYCLECNT_S			0
65#define CYCLECNT_M			GENMASK(23, 0)
66
67#define OFS_FM_MONR0			0xf0c
68
69#define OFS_FM_MONR1			0xf10
70#define FRCK_EN				BIT(8)
71
72#define U2_SR_COEF_7628			32
73
74struct mt76x8_usb_phy {
75	void __iomem		*base;
76	struct clk		cg;	/* for clock gating */
77	struct reset_ctl	rst_phy;
78};
79
80static void phy_w32(struct mt76x8_usb_phy *phy, u32 reg, u32 val)
81{
82	writel(val, phy->base + reg);
83}
84
85static u32 phy_r32(struct mt76x8_usb_phy *phy, u32 reg)
86{
87	return readl(phy->base + reg);
88}
89
90static void phy_rmw32(struct mt76x8_usb_phy *phy, u32 reg, u32 clr, u32 set)
91{
92	clrsetbits_32(phy->base + reg, clr, set);
93}
94
95static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy)
96{
97	phy_r32(phy, OFS_U2_PHY_AC2);
98	phy_r32(phy, OFS_U2_PHY_ACR0);
99	phy_r32(phy, OFS_U2_PHY_DCR0);
100
101	phy_w32(phy, OFS_U2_PHY_DCR0,
102		(0xffff << PHYD_RESERVE_S) | (2 << CDR_FILT_S));
103	phy_r32(phy, OFS_U2_PHY_DCR0);
104
105	phy_w32(phy, OFS_U2_PHY_DCR0,
106		(0x5555 << PHYD_RESERVE_S) | (2 << CDR_FILT_S));
107	phy_r32(phy, OFS_U2_PHY_DCR0);
108
109	phy_w32(phy, OFS_U2_PHY_DCR0,
110		(0xaaaa << PHYD_RESERVE_S) | (2 << CDR_FILT_S));
111	phy_r32(phy, OFS_U2_PHY_DCR0);
112
113	phy_w32(phy, OFS_U2_PHY_DCR0,
114		(4 << PHYD_RESERVE_S) | (2 << CDR_FILT_S));
115	phy_r32(phy, OFS_U2_PHY_DCR0);
116
117	phy_w32(phy, OFS_U2_PHY_AC0,
118		(0x48 << USBPLL_FBDIV_S) | (8 << BG_TRIM_S) |
119		(1 << BG_RBSEL_S) | (2 << BG_RASEL_S) | (2 << BGR_DIV_S) |
120		CHP_EN);
121
122	phy_w32(phy, OFS_U2_PHY_AC1,
123		(4 << VRT_VREF_SEL_S) | (4 << TERM_VREF_SEL_S) | USBPLL_RSVD |
124		USBPLL_ACCEN | USBPLL_LF);
125
126	phy_w32(phy, OFS_U2_PHY_ACR3,
127		(12 << HSTX_DBIST_S) | (2 << HSRX_BIAS_EN_SEL_S));
128
129	phy_w32(phy, OFS_U2_PHY_DTM0, FORCE_USB_CLKEN);
130}
131
132static void mt76x8_usb_phy_sr_calibrate(struct mt76x8_usb_phy *phy)
133{
134	u32 fmout, tmp = 4;
135	int i;
136
137	/* Enable HS TX SR calibration */
138	phy_rmw32(phy, OFS_U2_PHY_ACR0, 0, HSTX_SRCAL_EN);
139	mdelay(1);
140
141	/* Enable free run clock */
142	phy_rmw32(phy, OFS_FM_MONR1, 0, FRCK_EN);
143
144	/* Set cycle count = 0x400 */
145	phy_rmw32(phy, OFS_FM_CR0, CYCLECNT_M, 0x400 << CYCLECNT_S);
146
147	/* Enable frequency meter */
148	phy_rmw32(phy, OFS_FM_CR0, 0, FREQDET_EN);
149
150	/* Wait for FM detection done, set timeout to 10ms */
151	for (i = 0; i < 10; i++) {
152		fmout = phy_r32(phy, OFS_FM_MONR0);
153
154		if (fmout)
155			break;
156
157		mdelay(1);
158	}
159
160	/* Disable frequency meter */
161	phy_rmw32(phy, OFS_FM_CR0, FREQDET_EN, 0);
162
163	/* Disable free run clock */
164	phy_rmw32(phy, OFS_FM_MONR1, FRCK_EN, 0);
165
166	/* Disable HS TX SR calibration */
167	phy_rmw32(phy, OFS_U2_PHY_ACR0, HSTX_SRCAL_EN, 0);
168	mdelay(1);
169
170	if (fmout) {
171		/*
172		 * set reg = (1024 / FM_OUT) * 25 * 0.028
173		 * (round to the nearest digits)
174		 */
175		tmp = (((1024 * 25 * U2_SR_COEF_7628) / fmout) + 500) / 1000;
176	}
177
178	phy_rmw32(phy, OFS_U2_PHY_ACR0, HSTX_SRCTRL_M,
179		  (tmp << HSTX_SRCTRL_S) & HSTX_SRCTRL_M);
180}
181
182static int mt76x8_usb_phy_power_on(struct phy *_phy)
183{
184	struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
185
186	clk_enable(&phy->cg);
187
188	reset_deassert(&phy->rst_phy);
189
190	/*
191	 * The SDK kernel had a delay of 100ms. however on device
192	 * testing showed that 10ms is enough
193	 */
194	mdelay(10);
195
196	mt76x8_usb_phy_init(phy);
197	mt76x8_usb_phy_sr_calibrate(phy);
198
199	return 0;
200}
201
202static int mt76x8_usb_phy_power_off(struct phy *_phy)
203{
204	struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
205
206	clk_disable(&phy->cg);
207
208	reset_assert(&phy->rst_phy);
209
210	return 0;
211}
212
213static int mt76x8_usb_phy_probe(struct udevice *dev)
214{
215	struct mt76x8_usb_phy *phy = dev_get_priv(dev);
216	int ret;
217
218	phy->base = dev_read_addr_ptr(dev);
219	if (!phy->base)
220		return -EINVAL;
221
222	/* clock gate */
223	ret = clk_get_by_name(dev, "cg", &phy->cg);
224	if (ret)
225		return ret;
226
227	ret = reset_get_by_name(dev, "phy", &phy->rst_phy);
228	if (ret)
229		return ret;
230
231	return 0;
232}
233
234static struct phy_ops mt76x8_usb_phy_ops = {
235	.power_on = mt76x8_usb_phy_power_on,
236	.power_off = mt76x8_usb_phy_power_off,
237};
238
239static const struct udevice_id mt76x8_usb_phy_ids[] = {
240	{ .compatible = "mediatek,mt7628-usbphy" },
241	{ }
242};
243
244U_BOOT_DRIVER(mt76x8_usb_phy) = {
245	.name		= "mt76x8_usb_phy",
246	.id		= UCLASS_PHY,
247	.of_match	= mt76x8_usb_phy_ids,
248	.ops		= &mt76x8_usb_phy_ops,
249	.probe		= mt76x8_usb_phy_probe,
250	.priv_auto	= sizeof(struct mt76x8_usb_phy),
251};
252