1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Meson GXL USB3 PHY and OTG mode detection driver
4  *
5  * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/bitops.h>
10 #include <linux/clk.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/phy/phy.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16 #include <linux/platform_device.h>
17 
18 #define USB_R0							0x00
19 	#define USB_R0_P30_FSEL_MASK				GENMASK(5, 0)
20 	#define USB_R0_P30_PHY_RESET				BIT(6)
21 	#define USB_R0_P30_TEST_POWERDOWN_HSP			BIT(7)
22 	#define USB_R0_P30_TEST_POWERDOWN_SSP			BIT(8)
23 	#define USB_R0_P30_ACJT_LEVEL_MASK			GENMASK(13, 9)
24 	#define USB_R0_P30_TX_BOOST_LEVEL_MASK			GENMASK(16, 14)
25 	#define USB_R0_P30_LANE0_TX2RX_LOOPBACK			BIT(17)
26 	#define USB_R0_P30_LANE0_EXT_PCLK_REQ			BIT(18)
27 	#define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK		GENMASK(28, 19)
28 	#define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK		GENMASK(30, 29)
29 	#define USB_R0_U2D_ACT					BIT(31)
30 
31 #define USB_R1							0x04
32 	#define USB_R1_U3H_BIGENDIAN_GS				BIT(0)
33 	#define USB_R1_U3H_PME_ENABLE				BIT(1)
34 	#define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK		GENMASK(6, 2)
35 	#define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK		GENMASK(11, 7)
36 	#define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK		GENMASK(15, 12)
37 	#define USB_R1_U3H_HOST_U3_PORT_DISABLE			BIT(16)
38 	#define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT	BIT(17)
39 	#define USB_R1_U3H_HOST_MSI_ENABLE			BIT(18)
40 	#define USB_R1_U3H_FLADJ_30MHZ_REG_MASK			GENMASK(24, 19)
41 	#define USB_R1_P30_PCS_TX_SWING_FULL_MASK		GENMASK(31, 25)
42 
43 #define USB_R2							0x08
44 	#define USB_R2_P30_CR_DATA_IN_MASK			GENMASK(15, 0)
45 	#define USB_R2_P30_CR_READ				BIT(16)
46 	#define USB_R2_P30_CR_WRITE				BIT(17)
47 	#define USB_R2_P30_CR_CAP_ADDR				BIT(18)
48 	#define USB_R2_P30_CR_CAP_DATA				BIT(19)
49 	#define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK		GENMASK(25, 20)
50 	#define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK		GENMASK(31, 26)
51 
52 #define USB_R3							0x0c
53 	#define USB_R3_P30_SSC_ENABLE				BIT(0)
54 	#define USB_R3_P30_SSC_RANGE_MASK			GENMASK(3, 1)
55 	#define USB_R3_P30_SSC_REF_CLK_SEL_MASK			GENMASK(12, 4)
56 	#define USB_R3_P30_REF_SSP_EN				BIT(13)
57 	#define USB_R3_P30_LOS_BIAS_MASK			GENMASK(18, 16)
58 	#define USB_R3_P30_LOS_LEVEL_MASK			GENMASK(23, 19)
59 	#define USB_R3_P30_MPLL_MULTIPLIER_MASK			GENMASK(30, 24)
60 
61 #define USB_R4							0x10
62 	#define USB_R4_P21_PORT_RESET_0				BIT(0)
63 	#define USB_R4_P21_SLEEP_M0				BIT(1)
64 	#define USB_R4_MEM_PD_MASK				GENMASK(3, 2)
65 	#define USB_R4_P21_ONLY					BIT(4)
66 
67 #define USB_R5							0x14
68 	#define USB_R5_ID_DIG_SYNC				BIT(0)
69 	#define USB_R5_ID_DIG_REG				BIT(1)
70 	#define USB_R5_ID_DIG_CFG_MASK				GENMASK(3, 2)
71 	#define USB_R5_ID_DIG_EN_0				BIT(4)
72 	#define USB_R5_ID_DIG_EN_1				BIT(5)
73 	#define USB_R5_ID_DIG_CURR				BIT(6)
74 	#define USB_R5_ID_DIG_IRQ				BIT(7)
75 	#define USB_R5_ID_DIG_TH_MASK				GENMASK(15, 8)
76 	#define USB_R5_ID_DIG_CNT_MASK				GENMASK(23, 16)
77 
78 /* read-only register */
79 #define USB_R6							0x18
80 	#define USB_R6_P30_CR_DATA_OUT_MASK			GENMASK(15, 0)
81 	#define USB_R6_P30_CR_ACK				BIT(16)
82 
83 struct phy_meson_gxl_usb3_priv {
84 	struct regmap		*regmap;
85 	enum phy_mode		mode;
86 	struct clk		*clk_phy;
87 	struct clk		*clk_peripheral;
88 	struct reset_control	*reset;
89 };
90 
91 static const struct regmap_config phy_meson_gxl_usb3_regmap_conf = {
92 	.reg_bits = 8,
93 	.val_bits = 32,
94 	.reg_stride = 4,
95 	.max_register = USB_R6,
96 };
97 
phy_meson_gxl_usb3_power_on(struct phy * phy)98 static int phy_meson_gxl_usb3_power_on(struct phy *phy)
99 {
100 	struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy);
101 
102 	regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_0,
103 			   USB_R5_ID_DIG_EN_0);
104 	regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_1,
105 			   USB_R5_ID_DIG_EN_1);
106 	regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_TH_MASK,
107 			   FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff));
108 
109 	return 0;
110 }
111 
phy_meson_gxl_usb3_power_off(struct phy * phy)112 static int phy_meson_gxl_usb3_power_off(struct phy *phy)
113 {
114 	struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy);
115 
116 	regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_0, 0);
117 	regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_1, 0);
118 
119 	return 0;
120 }
121 
phy_meson_gxl_usb3_set_mode(struct phy * phy,enum phy_mode mode)122 static int phy_meson_gxl_usb3_set_mode(struct phy *phy, enum phy_mode mode)
123 {
124 	struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy);
125 
126 	switch (mode) {
127 	case PHY_MODE_USB_HOST:
128 		regmap_update_bits(priv->regmap, USB_R0, USB_R0_U2D_ACT, 0);
129 		regmap_update_bits(priv->regmap, USB_R4, USB_R4_P21_SLEEP_M0,
130 				   0);
131 		break;
132 
133 	case PHY_MODE_USB_DEVICE:
134 		regmap_update_bits(priv->regmap, USB_R0, USB_R0_U2D_ACT,
135 				   USB_R0_U2D_ACT);
136 		regmap_update_bits(priv->regmap, USB_R4, USB_R4_P21_SLEEP_M0,
137 				   USB_R4_P21_SLEEP_M0);
138 		break;
139 
140 	default:
141 		dev_err(&phy->dev, "unsupported PHY mode %d\n", mode);
142 		return -EINVAL;
143 	}
144 
145 	priv->mode = mode;
146 
147 	return 0;
148 }
149 
phy_meson_gxl_usb3_init(struct phy * phy)150 static int phy_meson_gxl_usb3_init(struct phy *phy)
151 {
152 	struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy);
153 	int ret;
154 
155 	ret = reset_control_reset(priv->reset);
156 	if (ret)
157 		goto err;
158 
159 	ret = clk_prepare_enable(priv->clk_phy);
160 	if (ret)
161 		goto err;
162 
163 	ret = clk_prepare_enable(priv->clk_peripheral);
164 	if (ret)
165 		goto err_disable_clk_phy;
166 
167 	ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode);
168 	if (ret)
169 		goto err_disable_clk_peripheral;
170 
171 	regmap_update_bits(priv->regmap, USB_R1,
172 			   USB_R1_U3H_FLADJ_30MHZ_REG_MASK,
173 			   FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20));
174 
175 	return 0;
176 
177 err_disable_clk_peripheral:
178 	clk_disable_unprepare(priv->clk_peripheral);
179 err_disable_clk_phy:
180 	clk_disable_unprepare(priv->clk_phy);
181 err:
182 	return ret;
183 }
184 
phy_meson_gxl_usb3_exit(struct phy * phy)185 static int phy_meson_gxl_usb3_exit(struct phy *phy)
186 {
187 	struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy);
188 
189 	clk_disable_unprepare(priv->clk_peripheral);
190 	clk_disable_unprepare(priv->clk_phy);
191 
192 	return 0;
193 }
194 
195 static const struct phy_ops phy_meson_gxl_usb3_ops = {
196 	.power_on	= phy_meson_gxl_usb3_power_on,
197 	.power_off	= phy_meson_gxl_usb3_power_off,
198 	.set_mode	= phy_meson_gxl_usb3_set_mode,
199 	.init		= phy_meson_gxl_usb3_init,
200 	.exit		= phy_meson_gxl_usb3_exit,
201 	.owner		= THIS_MODULE,
202 };
203 
phy_meson_gxl_usb3_probe(struct platform_device * pdev)204 static int phy_meson_gxl_usb3_probe(struct platform_device *pdev)
205 {
206 	struct device *dev = &pdev->dev;
207 	struct device_node *np = dev->of_node;
208 	struct phy_meson_gxl_usb3_priv *priv;
209 	struct resource *res;
210 	struct phy *phy;
211 	struct phy_provider *phy_provider;
212 	void __iomem *base;
213 	int ret;
214 
215 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
216 	if (!priv)
217 		return -ENOMEM;
218 
219 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
220 	base = devm_ioremap_resource(dev, res);
221 	if (IS_ERR(base))
222 		return PTR_ERR(base);
223 
224 	priv->regmap = devm_regmap_init_mmio(dev, base,
225 					     &phy_meson_gxl_usb3_regmap_conf);
226 	if (IS_ERR(priv->regmap))
227 		return PTR_ERR(priv->regmap);
228 
229 	priv->clk_phy = devm_clk_get(dev, "phy");
230 	if (IS_ERR(priv->clk_phy))
231 		return PTR_ERR(priv->clk_phy);
232 
233 	priv->clk_peripheral = devm_clk_get(dev, "peripheral");
234 	if (IS_ERR(priv->clk_peripheral))
235 		return PTR_ERR(priv->clk_peripheral);
236 
237 	priv->reset = devm_reset_control_array_get_shared(dev);
238 	if (IS_ERR(priv->reset))
239 		return PTR_ERR(priv->reset);
240 
241 	/*
242 	 * default to host mode as hardware defaults and/or boot-loader
243 	 * behavior can result in this PHY starting up in device mode. this
244 	 * default and the initialization in phy_meson_gxl_usb3_init ensure
245 	 * that we reproducibly start in a known mode on all devices.
246 	 */
247 	priv->mode = PHY_MODE_USB_HOST;
248 
249 	phy = devm_phy_create(dev, np, &phy_meson_gxl_usb3_ops);
250 	if (IS_ERR(phy)) {
251 		ret = PTR_ERR(phy);
252 		if (ret != -EPROBE_DEFER)
253 			dev_err(dev, "failed to create PHY\n");
254 
255 		return ret;
256 	}
257 
258 	phy_set_drvdata(phy, priv);
259 
260 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
261 
262 	return PTR_ERR_OR_ZERO(phy_provider);
263 }
264 
265 static const struct of_device_id phy_meson_gxl_usb3_of_match[] = {
266 	{ .compatible = "amlogic,meson-gxl-usb3-phy", },
267 	{ },
268 };
269 MODULE_DEVICE_TABLE(of, phy_meson_gxl_usb3_of_match);
270 
271 static struct platform_driver phy_meson_gxl_usb3_driver = {
272 	.probe	= phy_meson_gxl_usb3_probe,
273 	.driver	= {
274 		.name		= "phy-meson-gxl-usb3",
275 		.of_match_table	= phy_meson_gxl_usb3_of_match,
276 	},
277 };
278 module_platform_driver(phy_meson_gxl_usb3_driver);
279 
280 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
281 MODULE_DESCRIPTION("Meson GXL USB3 PHY and OTG detection driver");
282 MODULE_LICENSE("GPL v2");
283