xref: /linux/drivers/phy/marvell/phy-mmp3-usb.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
4  * Copyright (C) 2018,2019 Lubomir Rintel <lkundrak@v3.sk>
5  */
6 
7 #include <linux/delay.h>
8 #include <linux/io.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/module.h>
11 #include <linux/phy/phy.h>
12 #include <linux/platform_device.h>
13 #include <linux/soc/mmp/cputype.h>
14 
15 #define USB2_PLL_REG0		0x4
16 #define USB2_PLL_REG1		0x8
17 #define USB2_TX_REG0		0x10
18 #define USB2_TX_REG1		0x14
19 #define USB2_TX_REG2		0x18
20 #define USB2_RX_REG0		0x20
21 #define USB2_RX_REG1		0x24
22 #define USB2_RX_REG2		0x28
23 #define USB2_ANA_REG0		0x30
24 #define USB2_ANA_REG1		0x34
25 #define USB2_ANA_REG2		0x38
26 #define USB2_DIG_REG0		0x3C
27 #define USB2_DIG_REG1		0x40
28 #define USB2_DIG_REG2		0x44
29 #define USB2_DIG_REG3		0x48
30 #define USB2_TEST_REG0		0x4C
31 #define USB2_TEST_REG1		0x50
32 #define USB2_TEST_REG2		0x54
33 #define USB2_CHARGER_REG0	0x58
34 #define USB2_OTG_REG0		0x5C
35 #define USB2_PHY_MON0		0x60
36 #define USB2_RESETVE_REG0	0x64
37 #define USB2_ICID_REG0		0x78
38 #define USB2_ICID_REG1		0x7C
39 
40 /* USB2_PLL_REG0 */
41 
42 /* This is for Ax stepping */
43 #define USB2_PLL_FBDIV_SHIFT_MMP3		0
44 #define USB2_PLL_FBDIV_MASK_MMP3		(0xFF << 0)
45 
46 #define USB2_PLL_REFDIV_SHIFT_MMP3		8
47 #define USB2_PLL_REFDIV_MASK_MMP3		(0xF << 8)
48 
49 #define USB2_PLL_VDD12_SHIFT_MMP3		12
50 #define USB2_PLL_VDD18_SHIFT_MMP3		14
51 
52 /* This is for B0 stepping */
53 #define USB2_PLL_FBDIV_SHIFT_MMP3_B0		0
54 #define USB2_PLL_REFDIV_SHIFT_MMP3_B0		9
55 #define USB2_PLL_VDD18_SHIFT_MMP3_B0		14
56 #define USB2_PLL_FBDIV_MASK_MMP3_B0		0x01FF
57 #define USB2_PLL_REFDIV_MASK_MMP3_B0		0x3E00
58 
59 #define USB2_PLL_CAL12_SHIFT_MMP3		0
60 #define USB2_PLL_CALI12_MASK_MMP3		(0x3 << 0)
61 
62 #define USB2_PLL_VCOCAL_START_SHIFT_MMP3	2
63 
64 #define USB2_PLL_KVCO_SHIFT_MMP3		4
65 #define USB2_PLL_KVCO_MASK_MMP3			(0x7<<4)
66 
67 #define USB2_PLL_ICP_SHIFT_MMP3			8
68 #define USB2_PLL_ICP_MASK_MMP3			(0x7<<8)
69 
70 #define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3		12
71 
72 #define USB2_PLL_PU_PLL_SHIFT_MMP3		13
73 #define USB2_PLL_PU_PLL_MASK			(0x1 << 13)
74 
75 #define USB2_PLL_READY_MASK_MMP3		(0x1 << 15)
76 
77 /* USB2_TX_REG0 */
78 #define USB2_TX_IMPCAL_VTH_SHIFT_MMP3		8
79 #define USB2_TX_IMPCAL_VTH_MASK_MMP3		(0x7 << 8)
80 
81 #define USB2_TX_RCAL_START_SHIFT_MMP3		13
82 
83 /* USB2_TX_REG1 */
84 #define USB2_TX_CK60_PHSEL_SHIFT_MMP3		0
85 #define USB2_TX_CK60_PHSEL_MASK_MMP3		(0xf << 0)
86 
87 #define USB2_TX_AMP_SHIFT_MMP3			4
88 #define USB2_TX_AMP_MASK_MMP3			(0x7 << 4)
89 
90 #define USB2_TX_VDD12_SHIFT_MMP3		8
91 #define USB2_TX_VDD12_MASK_MMP3			(0x3 << 8)
92 
93 /* USB2_TX_REG2 */
94 #define USB2_TX_DRV_SLEWRATE_SHIFT		10
95 
96 /* USB2_RX_REG0 */
97 #define USB2_RX_SQ_THRESH_SHIFT_MMP3		4
98 #define USB2_RX_SQ_THRESH_MASK_MMP3		(0xf << 4)
99 
100 #define USB2_RX_SQ_LENGTH_SHIFT_MMP3		10
101 #define USB2_RX_SQ_LENGTH_MASK_MMP3		(0x3 << 10)
102 
103 /* USB2_ANA_REG1*/
104 #define USB2_ANA_PU_ANA_SHIFT_MMP3		14
105 
106 /* USB2_OTG_REG0 */
107 #define USB2_OTG_PU_OTG_SHIFT_MMP3		3
108 
109 struct mmp3_usb_phy {
110 	struct phy *phy;
111 	void __iomem *base;
112 };
113 
u2o_get(void __iomem * base,unsigned int offset)114 static unsigned int u2o_get(void __iomem *base, unsigned int offset)
115 {
116 	return readl_relaxed(base + offset);
117 }
118 
u2o_set(void __iomem * base,unsigned int offset,unsigned int value)119 static void u2o_set(void __iomem *base, unsigned int offset,
120 		unsigned int value)
121 {
122 	u32 reg;
123 
124 	reg = readl_relaxed(base + offset);
125 	reg |= value;
126 	writel_relaxed(reg, base + offset);
127 	readl_relaxed(base + offset);
128 }
129 
u2o_clear(void __iomem * base,unsigned int offset,unsigned int value)130 static void u2o_clear(void __iomem *base, unsigned int offset,
131 		unsigned int value)
132 {
133 	u32 reg;
134 
135 	reg = readl_relaxed(base + offset);
136 	reg &= ~value;
137 	writel_relaxed(reg, base + offset);
138 	readl_relaxed(base + offset);
139 }
140 
mmp3_usb_phy_init(struct phy * phy)141 static int mmp3_usb_phy_init(struct phy *phy)
142 {
143 	struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
144 	void __iomem *base = mmp3_usb_phy->base;
145 
146 	if (cpu_is_mmp3_a0()) {
147 		u2o_clear(base, USB2_PLL_REG0, (USB2_PLL_FBDIV_MASK_MMP3
148 			| USB2_PLL_REFDIV_MASK_MMP3));
149 		u2o_set(base, USB2_PLL_REG0,
150 			0xd << USB2_PLL_REFDIV_SHIFT_MMP3
151 			| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3);
152 	} else if (cpu_is_mmp3_b0()) {
153 		u2o_clear(base, USB2_PLL_REG0, USB2_PLL_REFDIV_MASK_MMP3_B0
154 			| USB2_PLL_FBDIV_MASK_MMP3_B0);
155 		u2o_set(base, USB2_PLL_REG0,
156 			0xd << USB2_PLL_REFDIV_SHIFT_MMP3_B0
157 			| 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3_B0);
158 	} else {
159 		dev_err(&phy->dev, "unsupported silicon revision\n");
160 		return -ENODEV;
161 	}
162 
163 	u2o_clear(base, USB2_PLL_REG1, USB2_PLL_PU_PLL_MASK
164 		| USB2_PLL_ICP_MASK_MMP3
165 		| USB2_PLL_KVCO_MASK_MMP3
166 		| USB2_PLL_CALI12_MASK_MMP3);
167 	u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_PU_PLL_SHIFT_MMP3
168 		| 1 << USB2_PLL_LOCK_BYPASS_SHIFT_MMP3
169 		| 3 << USB2_PLL_ICP_SHIFT_MMP3
170 		| 3 << USB2_PLL_KVCO_SHIFT_MMP3
171 		| 3 << USB2_PLL_CAL12_SHIFT_MMP3);
172 
173 	u2o_clear(base, USB2_TX_REG0, USB2_TX_IMPCAL_VTH_MASK_MMP3);
174 	u2o_set(base, USB2_TX_REG0, 2 << USB2_TX_IMPCAL_VTH_SHIFT_MMP3);
175 
176 	u2o_clear(base, USB2_TX_REG1, USB2_TX_VDD12_MASK_MMP3
177 		| USB2_TX_AMP_MASK_MMP3
178 		| USB2_TX_CK60_PHSEL_MASK_MMP3);
179 	u2o_set(base, USB2_TX_REG1, 3 << USB2_TX_VDD12_SHIFT_MMP3
180 		| 4 << USB2_TX_AMP_SHIFT_MMP3
181 		| 4 << USB2_TX_CK60_PHSEL_SHIFT_MMP3);
182 
183 	u2o_clear(base, USB2_TX_REG2, 3 << USB2_TX_DRV_SLEWRATE_SHIFT);
184 	u2o_set(base, USB2_TX_REG2, 2 << USB2_TX_DRV_SLEWRATE_SHIFT);
185 
186 	u2o_clear(base, USB2_RX_REG0, USB2_RX_SQ_THRESH_MASK_MMP3);
187 	u2o_set(base, USB2_RX_REG0, 0xa << USB2_RX_SQ_THRESH_SHIFT_MMP3);
188 
189 	u2o_set(base, USB2_ANA_REG1, 0x1 << USB2_ANA_PU_ANA_SHIFT_MMP3);
190 
191 	u2o_set(base, USB2_OTG_REG0, 0x1 << USB2_OTG_PU_OTG_SHIFT_MMP3);
192 
193 	return 0;
194 }
195 
mmp3_usb_phy_calibrate(struct phy * phy)196 static int mmp3_usb_phy_calibrate(struct phy *phy)
197 {
198 	struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
199 	void __iomem *base = mmp3_usb_phy->base;
200 	int loops;
201 
202 	/*
203 	 * PLL VCO and TX Impedance Calibration Timing:
204 	 *
205 	 *                _____________________________________
206 	 * PU  __________|
207 	 *                        _____________________________
208 	 * VCOCAL START _________|
209 	 *                                 ___
210 	 * REG_RCAL_START ________________|   |________|_______
211 	 *               | 200us | 400us  | 40| 400us  | USB PHY READY
212 	 */
213 
214 	udelay(200);
215 	u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_VCOCAL_START_SHIFT_MMP3);
216 	udelay(400);
217 	u2o_set(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
218 	udelay(40);
219 	u2o_clear(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
220 	udelay(400);
221 
222 	loops = 0;
223 	while ((u2o_get(base, USB2_PLL_REG1) & USB2_PLL_READY_MASK_MMP3) == 0) {
224 		mdelay(1);
225 		loops++;
226 		if (loops > 100) {
227 			dev_err(&phy->dev, "PLL_READY not set after 100mS.\n");
228 			return -ETIMEDOUT;
229 		}
230 	}
231 
232 	return 0;
233 }
234 
235 static const struct phy_ops mmp3_usb_phy_ops = {
236 	.init		= mmp3_usb_phy_init,
237 	.calibrate	= mmp3_usb_phy_calibrate,
238 	.owner		= THIS_MODULE,
239 };
240 
241 static const struct of_device_id mmp3_usb_phy_of_match[] = {
242 	{ .compatible = "marvell,mmp3-usb-phy", },
243 	{ },
244 };
245 MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match);
246 
mmp3_usb_phy_probe(struct platform_device * pdev)247 static int mmp3_usb_phy_probe(struct platform_device *pdev)
248 {
249 	struct device *dev = &pdev->dev;
250 	struct mmp3_usb_phy *mmp3_usb_phy;
251 	struct phy_provider *provider;
252 
253 	mmp3_usb_phy = devm_kzalloc(dev, sizeof(*mmp3_usb_phy), GFP_KERNEL);
254 	if (!mmp3_usb_phy)
255 		return -ENOMEM;
256 
257 	mmp3_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);
258 	if (IS_ERR(mmp3_usb_phy->base)) {
259 		dev_err(dev, "failed to remap PHY regs\n");
260 		return PTR_ERR(mmp3_usb_phy->base);
261 	}
262 
263 	mmp3_usb_phy->phy = devm_phy_create(dev, NULL, &mmp3_usb_phy_ops);
264 	if (IS_ERR(mmp3_usb_phy->phy)) {
265 		dev_err(dev, "failed to create PHY\n");
266 		return PTR_ERR(mmp3_usb_phy->phy);
267 	}
268 
269 	phy_set_drvdata(mmp3_usb_phy->phy, mmp3_usb_phy);
270 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
271 	if (IS_ERR(provider)) {
272 		dev_err(dev, "failed to register PHY provider\n");
273 		return PTR_ERR(provider);
274 	}
275 
276 	return 0;
277 }
278 
279 static struct platform_driver mmp3_usb_phy_driver = {
280 	.probe		= mmp3_usb_phy_probe,
281 	.driver		= {
282 		.name	= "mmp3-usb-phy",
283 		.of_match_table = mmp3_usb_phy_of_match,
284 	},
285 };
286 module_platform_driver(mmp3_usb_phy_driver);
287 
288 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
289 MODULE_DESCRIPTION("Marvell MMP3 USB PHY Driver");
290 MODULE_LICENSE("GPL v2");
291