• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Meson G12A USB3+PCIE Combo PHY driver
4  *
5  * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
6  * Copyright (C) 2019 BayLibre, SAS
7  * Author: Neil Armstrong <narmstron@baylibre.com>
8  */
9 
10 #include <common.h>
11 #include <clk.h>
12 #include <dm.h>
13 #include <regmap.h>
14 #include <errno.h>
15 #include <asm/io.h>
16 #include <reset.h>
17 #include <bitfield.h>
18 #include <generic-phy.h>
19 
20 #include <linux/bitops.h>
21 #include <linux/compat.h>
22 #include <linux/bitfield.h>
23 
24 #define PHY_R0							0x00
25 	#define PHY_R0_PCIE_POWER_STATE				GENMASK(4, 0)
26 	#define PHY_R0_PCIE_USB3_SWITCH				GENMASK(6, 5)
27 
28 #define PHY_R1							0x04
29 	#define PHY_R1_PHY_TX1_TERM_OFFSET			GENMASK(4, 0)
30 	#define PHY_R1_PHY_TX0_TERM_OFFSET			GENMASK(9, 5)
31 	#define PHY_R1_PHY_RX1_EQ				GENMASK(12, 10)
32 	#define PHY_R1_PHY_RX0_EQ				GENMASK(15, 13)
33 	#define PHY_R1_PHY_LOS_LEVEL				GENMASK(20, 16)
34 	#define PHY_R1_PHY_LOS_BIAS				GENMASK(23, 21)
35 	#define PHY_R1_PHY_REF_CLKDIV2				BIT(24)
36 	#define PHY_R1_PHY_MPLL_MULTIPLIER			GENMASK(31, 25)
37 
38 #define PHY_R2							0x08
39 	#define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB			GENMASK(5, 0)
40 	#define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB			GENMASK(11, 6)
41 	#define PHY_R2_PCS_TX_DEEMPH_GEN1			GENMASK(17, 12)
42 	#define PHY_R2_PHY_TX_VBOOST_LVL			GENMASK(20, 18)
43 
44 #define PHY_R4							0x10
45 	#define PHY_R4_PHY_CR_WRITE				BIT(0)
46 	#define PHY_R4_PHY_CR_READ				BIT(1)
47 	#define PHY_R4_PHY_CR_DATA_IN				GENMASK(17, 2)
48 	#define PHY_R4_PHY_CR_CAP_DATA				BIT(18)
49 	#define PHY_R4_PHY_CR_CAP_ADDR				BIT(19)
50 
51 #define PHY_R5							0x14
52 	#define PHY_R5_PHY_CR_DATA_OUT				GENMASK(15, 0)
53 	#define PHY_R5_PHY_CR_ACK				BIT(16)
54 	#define PHY_R5_PHY_BS_OUT				BIT(17)
55 
56 struct phy_g12a_usb3_pcie_priv {
57 	struct regmap		*regmap;
58 #if CONFIG_IS_ENABLED(CLK)
59 	struct clk		clk;
60 #endif
61 	struct reset_ctl_bulk	resets;
62 };
63 
phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv * priv,unsigned int addr)64 static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv,
65 					  unsigned int addr)
66 {
67 	unsigned int val, reg;
68 	int ret;
69 
70 	reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr);
71 
72 	regmap_write(priv->regmap, PHY_R4, reg);
73 	regmap_write(priv->regmap, PHY_R4, reg);
74 
75 	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR);
76 
77 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
78 				       (val & PHY_R5_PHY_CR_ACK),
79 				       5, 1000);
80 	if (ret)
81 		return ret;
82 
83 	regmap_write(priv->regmap, PHY_R4, reg);
84 
85 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
86 				       !(val & PHY_R5_PHY_CR_ACK),
87 				       5, 1000);
88 	if (ret)
89 		return ret;
90 
91 	return 0;
92 }
93 
94 static int
phy_g12a_usb3_pcie_cr_bus_read(struct phy_g12a_usb3_pcie_priv * priv,unsigned int addr,unsigned int * data)95 phy_g12a_usb3_pcie_cr_bus_read(struct phy_g12a_usb3_pcie_priv *priv,
96 			       unsigned int addr, unsigned int *data)
97 {
98 	unsigned int val;
99 	int ret;
100 
101 	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
102 	if (ret)
103 		return ret;
104 
105 	regmap_write(priv->regmap, PHY_R4, 0);
106 	regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ);
107 
108 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
109 				       (val & PHY_R5_PHY_CR_ACK),
110 				       5, 1000);
111 	if (ret)
112 		return ret;
113 
114 	*data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val);
115 
116 	regmap_write(priv->regmap, PHY_R4, 0);
117 
118 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
119 				       !(val & PHY_R5_PHY_CR_ACK),
120 				       5, 1000);
121 	if (ret)
122 		return ret;
123 
124 	return 0;
125 }
126 
127 static int
phy_g12a_usb3_pcie_cr_bus_write(struct phy_g12a_usb3_pcie_priv * priv,unsigned int addr,unsigned int data)128 phy_g12a_usb3_pcie_cr_bus_write(struct phy_g12a_usb3_pcie_priv *priv,
129 			        unsigned int addr, unsigned int data)
130 {
131 	unsigned int val, reg;
132 	int ret;
133 
134 	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
135 	if (ret)
136 		return ret;
137 
138 	reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data);
139 
140 	regmap_write(priv->regmap, PHY_R4, reg);
141 	regmap_write(priv->regmap, PHY_R4, reg);
142 
143 	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA);
144 
145 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
146 				       (val & PHY_R5_PHY_CR_ACK),
147 				       5, 1000);
148 	if (ret)
149 		return ret;
150 
151 	regmap_write(priv->regmap, PHY_R4, reg);
152 
153 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
154 				       (val & PHY_R5_PHY_CR_ACK) == 0,
155 				       5, 1000);
156 	if (ret)
157 		return ret;
158 
159 	regmap_write(priv->regmap, PHY_R4, reg);
160 
161 	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE);
162 
163 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
164 				       (val & PHY_R5_PHY_CR_ACK),
165 				       5, 1000);
166 	if (ret)
167 		return ret;
168 
169 	regmap_write(priv->regmap, PHY_R4, reg);
170 
171 	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
172 				       (val & PHY_R5_PHY_CR_ACK) == 0,
173 				       5, 1000);
174 	if (ret)
175 		return ret;
176 
177 	return 0;
178 }
179 
180 static int
phy_g12a_usb3_pcie_cr_bus_update_bits(struct phy_g12a_usb3_pcie_priv * priv,uint offset,uint mask,uint val)181 phy_g12a_usb3_pcie_cr_bus_update_bits(struct phy_g12a_usb3_pcie_priv *priv,
182 				      uint offset, uint mask, uint val)
183 {
184 	uint reg;
185 	int ret;
186 
187 	ret = phy_g12a_usb3_pcie_cr_bus_read(priv, offset, &reg);
188 	if (ret)
189 		return ret;
190 
191 	reg &= ~mask;
192 
193 	return phy_g12a_usb3_pcie_cr_bus_write(priv, offset, reg | val);
194 }
195 
phy_meson_g12a_usb3_init(struct phy * phy)196 static int phy_meson_g12a_usb3_init(struct phy *phy)
197 {
198 	struct udevice *dev = phy->dev;
199 	struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(dev);
200 	unsigned int data;
201 	int ret;
202 
203 	/* TOFIX Handle PCIE mode */
204 
205 	ret = reset_assert_bulk(&priv->resets);
206 	udelay(1);
207 	ret |= reset_deassert_bulk(&priv->resets);
208 	if (ret)
209 		return ret;
210 
211 	/* Switch PHY to USB3 */
212 	regmap_update_bits(priv->regmap, PHY_R0,
213 			   PHY_R0_PCIE_USB3_SWITCH,
214 			   PHY_R0_PCIE_USB3_SWITCH);
215 
216 	/*
217 	 * WORKAROUND: There is SSPHY suspend bug due to
218 	 * which USB enumerates
219 	 * in HS mode instead of SS mode. Workaround it by asserting
220 	 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus
221 	 * mode
222 	 */
223 	ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x102d,
224 						    BIT(7), BIT(7));
225 	if (ret)
226 		return ret;
227 
228 	ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x1010, 0xff0, 20);
229 	if (ret)
230 		return ret;
231 
232 	/*
233 	 * Fix RX Equalization setting as follows
234 	 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
235 	 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
236 	 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
237 	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
238 	 */
239 	ret = phy_g12a_usb3_pcie_cr_bus_read(priv, 0x1006, &data);
240 	if (ret)
241 		return ret;
242 
243 	data &= ~BIT(6);
244 	data |= BIT(7);
245 	data &= ~(0x7 << 8);
246 	data |= (0x3 << 8);
247 	data |= (1 << 11);
248 	ret = phy_g12a_usb3_pcie_cr_bus_write(priv, 0x1006, data);
249 	if (ret)
250 		return ret;
251 
252 	/*
253 	 * Set EQ and TX launch amplitudes as follows
254 	 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
255 	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
256 	 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
257 	 */
258 	ret = phy_g12a_usb3_pcie_cr_bus_read(priv, 0x1002, &data);
259 	if (ret)
260 		return ret;
261 
262 	data &= ~0x3f80;
263 	data |= (0x16 << 7);
264 	data &= ~0x7f;
265 	data |= (0x7f | BIT(14));
266 	ret = phy_g12a_usb3_pcie_cr_bus_write(priv, 0x1002, data);
267 	if (ret)
268 		return ret;
269 
270 	/*
271 	 * MPLL_LOOP_CTL.PROP_CNTRL = 8
272 	 */
273 	ret = phy_g12a_usb3_pcie_cr_bus_update_bits(priv, 0x30,
274 						    0xf << 4, 8 << 4);
275 	if (ret)
276 		return ret;
277 
278 	regmap_update_bits(priv->regmap, PHY_R2,
279 			PHY_R2_PHY_TX_VBOOST_LVL,
280 			FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4));
281 
282 	regmap_update_bits(priv->regmap, PHY_R1,
283 			PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL,
284 			FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) |
285 			FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9));
286 
287 	return ret;
288 }
289 
phy_meson_g12a_usb3_exit(struct phy * phy)290 static int phy_meson_g12a_usb3_exit(struct phy *phy)
291 {
292 	struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(phy->dev);
293 
294 	return reset_assert_bulk(&priv->resets);
295 }
296 
297 struct phy_ops meson_g12a_usb3_pcie_phy_ops = {
298 	.init = phy_meson_g12a_usb3_init,
299 	.exit = phy_meson_g12a_usb3_exit,
300 };
301 
meson_g12a_usb3_pcie_phy_probe(struct udevice * dev)302 int meson_g12a_usb3_pcie_phy_probe(struct udevice *dev)
303 {
304 	struct phy_g12a_usb3_pcie_priv *priv = dev_get_priv(dev);
305 	int ret;
306 
307 	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
308 	if (ret)
309 		return ret;
310 
311 	ret = reset_get_bulk(dev, &priv->resets);
312 	if (ret == -ENOTSUPP)
313 		return 0;
314 	else if (ret)
315 		return ret;
316 
317 #if CONFIG_IS_ENABLED(CLK)
318 	ret = clk_get_by_index(dev, 0, &priv->clk);
319 	if (ret < 0)
320 		return ret;
321 
322 	ret = clk_enable(&priv->clk);
323 	if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
324 		pr_err("failed to enable PHY clock\n");
325 		clk_free(&priv->clk);
326 		return ret;
327 	}
328 #endif
329 
330 	return 0;
331 }
332 
333 static const struct udevice_id meson_g12a_usb3_pcie_phy_ids[] = {
334 	{ .compatible = "amlogic,g12a-usb3-pcie-phy" },
335 	{ }
336 };
337 
338 U_BOOT_DRIVER(meson_g12a_usb3_pcie_phy) = {
339 	.name = "meson_g12a_usb3_pcie_phy",
340 	.id = UCLASS_PHY,
341 	.of_match = meson_g12a_usb3_pcie_phy_ids,
342 	.probe = meson_g12a_usb3_pcie_phy_probe,
343 	.ops = &meson_g12a_usb3_pcie_phy_ops,
344 	.priv_auto_alloc_size = sizeof(struct phy_g12a_usb3_pcie_priv),
345 };
346