Merge tag 'linux-watchdog-5.11-rc1' of git://www.linux-watchdog.org/linux-watchdog
[linux-2.6-microblaze.git] / drivers / phy / ingenic / phy-ingenic-usb.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Ingenic SoCs USB PHY driver
4  * Copyright (c) Paul Cercueil <paul@crapouillou.net>
5  * Copyright (c) 漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com>
6  * Copyright (c) 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
7  */
8
9 #include <linux/bitfield.h>
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/consumer.h>
17
18 /* OTGPHY register offsets */
19 #define REG_USBPCR_OFFSET                       0x00
20 #define REG_USBRDT_OFFSET                       0x04
21 #define REG_USBVBFIL_OFFSET                     0x08
22 #define REG_USBPCR1_OFFSET                      0x0c
23
24 /* bits within the USBPCR register */
25 #define USBPCR_USB_MODE                         BIT(31)
26 #define USBPCR_AVLD_REG                         BIT(30)
27 #define USBPCR_COMMONONN                        BIT(25)
28 #define USBPCR_VBUSVLDEXT                       BIT(24)
29 #define USBPCR_VBUSVLDEXTSEL            BIT(23)
30 #define USBPCR_POR                                      BIT(22)
31 #define USBPCR_SIDDQ                            BIT(21)
32 #define USBPCR_OTG_DISABLE                      BIT(20)
33 #define USBPCR_TXPREEMPHTUNE            BIT(6)
34
35 #define USBPCR_IDPULLUP_MASK            GENMASK(29, 28)
36 #define USBPCR_IDPULLUP_ALWAYS          0x2
37 #define USBPCR_IDPULLUP_SUSPEND         0x1
38 #define USBPCR_IDPULLUP_OTG                     0x0
39
40 #define USBPCR_COMPDISTUNE_MASK         GENMASK(19, 17)
41 #define USBPCR_COMPDISTUNE_DFT          0x4
42
43 #define USBPCR_OTGTUNE_MASK                     GENMASK(16, 14)
44 #define USBPCR_OTGTUNE_DFT                      0x4
45
46 #define USBPCR_SQRXTUNE_MASK            GENMASK(13, 11)
47 #define USBPCR_SQRXTUNE_DCR_20PCT       0x7
48 #define USBPCR_SQRXTUNE_DFT                     0x3
49
50 #define USBPCR_TXFSLSTUNE_MASK          GENMASK(10, 7)
51 #define USBPCR_TXFSLSTUNE_DCR_50PPT     0xf
52 #define USBPCR_TXFSLSTUNE_DCR_25PPT     0x7
53 #define USBPCR_TXFSLSTUNE_DFT           0x3
54 #define USBPCR_TXFSLSTUNE_INC_25PPT     0x1
55 #define USBPCR_TXFSLSTUNE_INC_50PPT     0x0
56
57 #define USBPCR_TXHSXVTUNE_MASK          GENMASK(5, 4)
58 #define USBPCR_TXHSXVTUNE_DFT           0x3
59 #define USBPCR_TXHSXVTUNE_DCR_15MV      0x1
60
61 #define USBPCR_TXRISETUNE_MASK          GENMASK(5, 4)
62 #define USBPCR_TXRISETUNE_DFT           0x3
63
64 #define USBPCR_TXVREFTUNE_MASK          GENMASK(3, 0)
65 #define USBPCR_TXVREFTUNE_INC_75PPT     0xb
66 #define USBPCR_TXVREFTUNE_INC_25PPT     0x7
67 #define USBPCR_TXVREFTUNE_DFT           0x5
68
69 /* bits within the USBRDTR register */
70 #define USBRDT_UTMI_RST                         BIT(27)
71 #define USBRDT_HB_MASK                          BIT(26)
72 #define USBRDT_VBFIL_LD_EN                      BIT(25)
73 #define USBRDT_IDDIG_EN                         BIT(24)
74 #define USBRDT_IDDIG_REG                        BIT(23)
75 #define USBRDT_VBFIL_EN                         BIT(2)
76
77 /* bits within the USBPCR1 register */
78 #define USBPCR1_BVLD_REG                        BIT(31)
79 #define USBPCR1_DPPD                            BIT(29)
80 #define USBPCR1_DMPD                            BIT(28)
81 #define USBPCR1_USB_SEL                         BIT(28)
82 #define USBPCR1_PORT_RST                        BIT(21)
83 #define USBPCR1_WORD_IF_16BIT           BIT(19)
84
85 enum ingenic_usb_phy_version {
86         ID_JZ4770,
87         ID_JZ4775,
88         ID_JZ4780,
89         ID_X1000,
90         ID_X1830,
91         ID_X2000,
92 };
93
94 struct ingenic_soc_info {
95         enum ingenic_usb_phy_version version;
96
97         void (*usb_phy_init)(struct phy *phy);
98 };
99
100 struct ingenic_usb_phy {
101         const struct ingenic_soc_info *soc_info;
102
103         struct phy *phy;
104         void __iomem *base;
105         struct clk *clk;
106         struct regulator *vcc_supply;
107 };
108
109 static int ingenic_usb_phy_init(struct phy *phy)
110 {
111         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
112         int err;
113         u32 reg;
114
115         err = clk_prepare_enable(priv->clk);
116         if (err) {
117                 dev_err(&phy->dev, "Unable to start clock: %d\n", err);
118                 return err;
119         }
120
121         priv->soc_info->usb_phy_init(phy);
122
123         /* Wait for PHY to reset */
124         usleep_range(30, 300);
125         reg = readl(priv->base + REG_USBPCR_OFFSET);
126         writel(reg & ~USBPCR_POR, priv->base + REG_USBPCR_OFFSET);
127         usleep_range(300, 1000);
128
129         return 0;
130 }
131
132 static int ingenic_usb_phy_exit(struct phy *phy)
133 {
134         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
135
136         clk_disable_unprepare(priv->clk);
137         regulator_disable(priv->vcc_supply);
138
139         return 0;
140 }
141
142 static int ingenic_usb_phy_power_on(struct phy *phy)
143 {
144         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
145         int err;
146
147         err = regulator_enable(priv->vcc_supply);
148         if (err) {
149                 dev_err(&phy->dev, "Unable to enable VCC: %d\n", err);
150                 return err;
151         }
152
153         return 0;
154 }
155
156 static int ingenic_usb_phy_power_off(struct phy *phy)
157 {
158         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
159
160         regulator_disable(priv->vcc_supply);
161
162         return 0;
163 }
164
165 static int ingenic_usb_phy_set_mode(struct phy *phy,
166                                   enum phy_mode mode, int submode)
167 {
168         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
169         u32 reg;
170
171         switch (mode) {
172         case PHY_MODE_USB_HOST:
173                 reg = readl(priv->base + REG_USBPCR_OFFSET);
174                 u32p_replace_bits(&reg, 1, USBPCR_USB_MODE);
175                 u32p_replace_bits(&reg, 0, USBPCR_VBUSVLDEXT);
176                 u32p_replace_bits(&reg, 0, USBPCR_VBUSVLDEXTSEL);
177                 u32p_replace_bits(&reg, 0, USBPCR_OTG_DISABLE);
178                 writel(reg, priv->base + REG_USBPCR_OFFSET);
179
180                 break;
181         case PHY_MODE_USB_DEVICE:
182                 reg = readl(priv->base + REG_USBPCR_OFFSET);
183                 u32p_replace_bits(&reg, 0, USBPCR_USB_MODE);
184                 u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXT);
185                 u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXTSEL);
186                 u32p_replace_bits(&reg, 1, USBPCR_OTG_DISABLE);
187                 writel(reg, priv->base + REG_USBPCR_OFFSET);
188
189                 break;
190         case PHY_MODE_USB_OTG:
191                 reg = readl(priv->base + REG_USBPCR_OFFSET);
192                 u32p_replace_bits(&reg, 1, USBPCR_USB_MODE);
193                 u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXT);
194                 u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXTSEL);
195                 u32p_replace_bits(&reg, 0, USBPCR_OTG_DISABLE);
196                 writel(reg, priv->base + REG_USBPCR_OFFSET);
197
198                 break;
199         default:
200                 return -EINVAL;
201         }
202
203         return 0;
204 }
205
206 static const struct phy_ops ingenic_usb_phy_ops = {
207         .init           = ingenic_usb_phy_init,
208         .exit           = ingenic_usb_phy_exit,
209         .power_on       = ingenic_usb_phy_power_on,
210         .power_off      = ingenic_usb_phy_power_off,
211         .set_mode       = ingenic_usb_phy_set_mode,
212         .owner          = THIS_MODULE,
213 };
214
215 static void jz4770_usb_phy_init(struct phy *phy)
216 {
217         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
218         u32 reg;
219
220         reg = USBPCR_AVLD_REG | USBPCR_COMMONONN | USBPCR_POR |
221                 FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_ALWAYS) |
222                 FIELD_PREP(USBPCR_COMPDISTUNE_MASK, USBPCR_COMPDISTUNE_DFT) |
223                 FIELD_PREP(USBPCR_OTGTUNE_MASK, USBPCR_OTGTUNE_DFT) |
224                 FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DFT) |
225                 FIELD_PREP(USBPCR_TXFSLSTUNE_MASK, USBPCR_TXFSLSTUNE_DFT) |
226                 FIELD_PREP(USBPCR_TXRISETUNE_MASK, USBPCR_TXRISETUNE_DFT) |
227                 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_DFT);
228         writel(reg, priv->base + REG_USBPCR_OFFSET);
229 }
230
231 static void jz4775_usb_phy_init(struct phy *phy)
232 {
233         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
234         u32 reg;
235
236         reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL |
237                 USBPCR1_WORD_IF_16BIT;
238         writel(reg, priv->base + REG_USBPCR1_OFFSET);
239
240         reg = USBPCR_COMMONONN | USBPCR_POR |
241                 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_75PPT);
242         writel(reg, priv->base + REG_USBPCR_OFFSET);
243 }
244
245 static void jz4780_usb_phy_init(struct phy *phy)
246 {
247         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
248         u32 reg;
249
250         reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL |
251                 USBPCR1_WORD_IF_16BIT;
252         writel(reg, priv->base + REG_USBPCR1_OFFSET);
253
254         reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR;
255         writel(reg, priv->base + REG_USBPCR_OFFSET);
256 }
257
258 static void x1000_usb_phy_init(struct phy *phy)
259 {
260         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
261         u32 reg;
262
263         reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT;
264         writel(reg, priv->base + REG_USBPCR1_OFFSET);
265
266         reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR |
267                 FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DCR_20PCT) |
268                 FIELD_PREP(USBPCR_TXHSXVTUNE_MASK, USBPCR_TXHSXVTUNE_DCR_15MV) |
269                 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_25PPT);
270         writel(reg, priv->base + REG_USBPCR_OFFSET);
271 }
272
273 static void x1830_usb_phy_init(struct phy *phy)
274 {
275         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
276         u32 reg;
277
278         /* rdt */
279         writel(USBRDT_VBFIL_EN | USBRDT_UTMI_RST, priv->base + REG_USBRDT_OFFSET);
280
281         reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT |
282                 USBPCR1_DMPD | USBPCR1_DPPD;
283         writel(reg, priv->base + REG_USBPCR1_OFFSET);
284
285         reg = USBPCR_VBUSVLDEXT | USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR |
286                 FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG);
287         writel(reg, priv->base + REG_USBPCR_OFFSET);
288 }
289
290 static void x2000_usb_phy_init(struct phy *phy)
291 {
292         struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
293         u32 reg;
294
295         reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_DPPD | USBPCR1_DMPD;
296         writel(reg & ~USBPCR1_PORT_RST, priv->base + REG_USBPCR1_OFFSET);
297
298         reg = USBPCR_POR | FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG);
299         writel(reg, priv->base + REG_USBPCR_OFFSET);
300 }
301
302 static const struct ingenic_soc_info jz4770_soc_info = {
303         .version = ID_JZ4770,
304
305         .usb_phy_init = jz4770_usb_phy_init,
306 };
307
308 static const struct ingenic_soc_info jz4775_soc_info = {
309         .version = ID_JZ4775,
310
311         .usb_phy_init = jz4775_usb_phy_init,
312 };
313
314 static const struct ingenic_soc_info jz4780_soc_info = {
315         .version = ID_JZ4780,
316
317         .usb_phy_init = jz4780_usb_phy_init,
318 };
319
320 static const struct ingenic_soc_info x1000_soc_info = {
321         .version = ID_X1000,
322
323         .usb_phy_init = x1000_usb_phy_init,
324 };
325
326 static const struct ingenic_soc_info x1830_soc_info = {
327         .version = ID_X1830,
328
329         .usb_phy_init = x1830_usb_phy_init,
330 };
331
332 static const struct ingenic_soc_info x2000_soc_info = {
333         .version = ID_X2000,
334
335         .usb_phy_init = x2000_usb_phy_init,
336 };
337
338 static int ingenic_usb_phy_probe(struct platform_device *pdev)
339 {
340         struct ingenic_usb_phy *priv;
341         struct phy_provider *provider;
342         struct device *dev = &pdev->dev;
343         int err;
344
345         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
346         if (!priv)
347                 return -ENOMEM;
348
349         priv->soc_info = device_get_match_data(dev);
350         if (!priv->soc_info) {
351                 dev_err(dev, "Error: No device match found\n");
352                 return -ENODEV;
353         }
354
355         priv->base = devm_platform_ioremap_resource(pdev, 0);
356         if (IS_ERR(priv->base)) {
357                 dev_err(dev, "Failed to map registers\n");
358                 return PTR_ERR(priv->base);
359         }
360
361         priv->clk = devm_clk_get(dev, NULL);
362         if (IS_ERR(priv->clk)) {
363                 err = PTR_ERR(priv->clk);
364                 if (err != -EPROBE_DEFER)
365                         dev_err(dev, "Failed to get clock\n");
366                 return err;
367         }
368
369         priv->vcc_supply = devm_regulator_get(dev, "vcc");
370         if (IS_ERR(priv->vcc_supply)) {
371                 err = PTR_ERR(priv->vcc_supply);
372                 if (err != -EPROBE_DEFER)
373                         dev_err(dev, "Failed to get regulator\n");
374                 return err;
375         }
376
377         priv->phy = devm_phy_create(dev, NULL, &ingenic_usb_phy_ops);
378         if (IS_ERR(priv))
379                 return PTR_ERR(priv);
380
381         phy_set_drvdata(priv->phy, priv);
382
383         provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
384
385         return PTR_ERR_OR_ZERO(provider);
386 }
387
388 static const struct of_device_id ingenic_usb_phy_of_matches[] = {
389         { .compatible = "ingenic,jz4770-phy", .data = &jz4770_soc_info },
390         { .compatible = "ingenic,jz4775-phy", .data = &jz4775_soc_info },
391         { .compatible = "ingenic,jz4780-phy", .data = &jz4780_soc_info },
392         { .compatible = "ingenic,x1000-phy", .data = &x1000_soc_info },
393         { .compatible = "ingenic,x1830-phy", .data = &x1830_soc_info },
394         { .compatible = "ingenic,x2000-phy", .data = &x2000_soc_info },
395         { /* sentinel */ }
396 };
397 MODULE_DEVICE_TABLE(of, ingenic_usb_phy_of_matches);
398
399 static struct platform_driver ingenic_usb_phy_driver = {
400         .probe          = ingenic_usb_phy_probe,
401         .driver         = {
402                 .name   = "ingenic-usb-phy",
403                 .of_match_table = ingenic_usb_phy_of_matches,
404         },
405 };
406 module_platform_driver(ingenic_usb_phy_driver);
407
408 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
409 MODULE_AUTHOR("漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com>");
410 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
411 MODULE_DESCRIPTION("Ingenic SoCs USB PHY driver");
412 MODULE_LICENSE("GPL");