Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / phy / meson-g12a-usb2.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Meson G12A USB2 PHY driver
4  *
5  * Copyright (C) 2017 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 <log.h>
12 #include <malloc.h>
13 #include <asm/io.h>
14 #include <bitfield.h>
15 #include <dm.h>
16 #include <errno.h>
17 #include <generic-phy.h>
18 #include <regmap.h>
19 #include <linux/delay.h>
20 #include <power/regulator.h>
21 #include <reset.h>
22 #include <clk.h>
23
24 #include <linux/bitops.h>
25 #include <linux/compat.h>
26
27 #define PHY_CTRL_R0                                             0x0
28 #define PHY_CTRL_R1                                             0x4
29 #define PHY_CTRL_R2                                             0x8
30 #define PHY_CTRL_R3                                             0xc
31 #define PHY_CTRL_R4                                             0x10
32 #define PHY_CTRL_R5                                             0x14
33 #define PHY_CTRL_R6                                             0x18
34 #define PHY_CTRL_R7                                             0x1c
35 #define PHY_CTRL_R8                                             0x20
36 #define PHY_CTRL_R9                                             0x24
37 #define PHY_CTRL_R10                                            0x28
38 #define PHY_CTRL_R11                                            0x2c
39 #define PHY_CTRL_R12                                            0x30
40 #define PHY_CTRL_R13                                            0x34
41 #define PHY_CTRL_R14                                            0x38
42 #define PHY_CTRL_R15                                            0x3c
43 #define PHY_CTRL_R16                                            0x40
44 #define PHY_CTRL_R17                                            0x44
45 #define PHY_CTRL_R18                                            0x48
46 #define PHY_CTRL_R19                                            0x4c
47 #define PHY_CTRL_R20                                            0x50
48 #define PHY_CTRL_R21                                            0x54
49 #define PHY_CTRL_R22                                            0x58
50 #define PHY_CTRL_R23                                            0x5c
51
52 #define RESET_COMPLETE_TIME                                     1000
53 #define PLL_RESET_COMPLETE_TIME                                 100
54
55 struct phy_meson_g12a_usb2_priv {
56         struct regmap           *regmap;
57 #if CONFIG_IS_ENABLED(CLK)
58         struct clk              clk;
59 #endif
60         struct reset_ctl        reset;
61 };
62
63 static int phy_meson_g12a_usb2_init(struct phy *phy)
64 {
65         struct udevice *dev = phy->dev;
66         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
67         int ret;
68
69         ret = reset_assert(&priv->reset);
70         udelay(1);
71         ret |= reset_deassert(&priv->reset);
72         if (ret)
73                 return ret;
74
75         udelay(RESET_COMPLETE_TIME);
76
77         /* usb2_otg_aca_en == 0 */
78         regmap_update_bits(priv->regmap, PHY_CTRL_R21, BIT(2), 0);
79
80         /* PLL Setup : 24MHz * 20 / 1 = 480MHz */
81         regmap_write(priv->regmap, PHY_CTRL_R16, 0x39400414);
82         regmap_write(priv->regmap, PHY_CTRL_R17, 0x927e0000);
83         regmap_write(priv->regmap, PHY_CTRL_R18, 0xac5f49e5);
84
85         udelay(PLL_RESET_COMPLETE_TIME);
86
87         /* UnReset PLL */
88         regmap_write(priv->regmap, PHY_CTRL_R16, 0x19400414);
89
90         /* PHY Tuning */
91         regmap_write(priv->regmap, PHY_CTRL_R20, 0xfe18);
92         regmap_write(priv->regmap, PHY_CTRL_R4, 0x8000fff);
93
94         /* Tuning Disconnect Threshold */
95         regmap_write(priv->regmap, PHY_CTRL_R3, 0x34);
96
97         /* Analog Settings */
98         regmap_write(priv->regmap, PHY_CTRL_R14, 0);
99         regmap_write(priv->regmap, PHY_CTRL_R13, 0x78000);
100
101         return 0;
102 }
103
104 static int phy_meson_g12a_usb2_exit(struct phy *phy)
105 {
106         struct udevice *dev = phy->dev;
107         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
108         int ret;
109
110         ret = reset_assert(&priv->reset);
111         if (ret)
112                 return ret;
113
114         return 0;
115 }
116
117 struct phy_ops meson_g12a_usb2_phy_ops = {
118         .init = phy_meson_g12a_usb2_init,
119         .exit = phy_meson_g12a_usb2_exit,
120 };
121
122 int meson_g12a_usb2_phy_probe(struct udevice *dev)
123 {
124         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
125         int ret;
126
127         ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
128         if (ret)
129                 return ret;
130
131         ret = reset_get_by_index(dev, 0, &priv->reset);
132         if (ret == -ENOTSUPP)
133                 return 0;
134         else if (ret)
135                 return ret;
136
137         ret = reset_deassert(&priv->reset);
138         if (ret) {
139                 reset_release_all(&priv->reset, 1);
140                 return ret;
141         }
142
143 #if CONFIG_IS_ENABLED(CLK)
144         ret = clk_get_by_index(dev, 0, &priv->clk);
145         if (ret < 0)
146                 return ret;
147
148         ret = clk_enable(&priv->clk);
149         if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
150                 pr_err("failed to enable PHY clock\n");
151                 clk_free(&priv->clk);
152                 return ret;
153         }
154 #endif
155
156         return 0;
157 }
158
159 static const struct udevice_id meson_g12a_usb2_phy_ids[] = {
160         { .compatible = "amlogic,g12a-usb2-phy" },
161         { }
162 };
163
164 U_BOOT_DRIVER(meson_g12a_usb2_phy) = {
165         .name = "meson_g12a_usb2_phy",
166         .id = UCLASS_PHY,
167         .of_match = meson_g12a_usb2_phy_ids,
168         .probe = meson_g12a_usb2_phy_probe,
169         .ops = &meson_g12a_usb2_phy_ops,
170         .priv_auto      = sizeof(struct phy_meson_g12a_usb2_priv),
171 };