6030031184c8c77c1dff7da9ede4aea4b58e1427
[oweals/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 <power/regulator.h>
20 #include <reset.h>
21 #include <clk.h>
22
23 #include <linux/bitops.h>
24 #include <linux/compat.h>
25
26 #define PHY_CTRL_R0                                             0x0
27 #define PHY_CTRL_R1                                             0x4
28 #define PHY_CTRL_R2                                             0x8
29 #define PHY_CTRL_R3                                             0xc
30 #define PHY_CTRL_R4                                             0x10
31 #define PHY_CTRL_R5                                             0x14
32 #define PHY_CTRL_R6                                             0x18
33 #define PHY_CTRL_R7                                             0x1c
34 #define PHY_CTRL_R8                                             0x20
35 #define PHY_CTRL_R9                                             0x24
36 #define PHY_CTRL_R10                                            0x28
37 #define PHY_CTRL_R11                                            0x2c
38 #define PHY_CTRL_R12                                            0x30
39 #define PHY_CTRL_R13                                            0x34
40 #define PHY_CTRL_R14                                            0x38
41 #define PHY_CTRL_R15                                            0x3c
42 #define PHY_CTRL_R16                                            0x40
43 #define PHY_CTRL_R17                                            0x44
44 #define PHY_CTRL_R18                                            0x48
45 #define PHY_CTRL_R19                                            0x4c
46 #define PHY_CTRL_R20                                            0x50
47 #define PHY_CTRL_R21                                            0x54
48 #define PHY_CTRL_R22                                            0x58
49 #define PHY_CTRL_R23                                            0x5c
50
51 #define RESET_COMPLETE_TIME                                     1000
52 #define PLL_RESET_COMPLETE_TIME                                 100
53
54 struct phy_meson_g12a_usb2_priv {
55         struct regmap           *regmap;
56 #if CONFIG_IS_ENABLED(DM_REGULATOR)
57         struct udevice          *phy_supply;
58 #endif
59 #if CONFIG_IS_ENABLED(CLK)
60         struct clk              clk;
61 #endif
62         struct reset_ctl        reset;
63 };
64
65
66 static int phy_meson_g12a_usb2_power_on(struct phy *phy)
67 {
68         struct udevice *dev = phy->dev;
69         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
70
71 #if CONFIG_IS_ENABLED(DM_REGULATOR)
72         if (priv->phy_supply) {
73                 int ret = regulator_set_enable(priv->phy_supply, true);
74                 if (ret)
75                         return ret;
76         }
77 #endif
78
79         return 0;
80 }
81
82 static int phy_meson_g12a_usb2_power_off(struct phy *phy)
83 {
84         struct udevice *dev = phy->dev;
85         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
86
87 #if CONFIG_IS_ENABLED(DM_REGULATOR)
88         if (priv->phy_supply) {
89                 int ret = regulator_set_enable(priv->phy_supply, false);
90                 if (ret) {
91                         pr_err("Error disabling PHY supply\n");
92                         return ret;
93                 }
94         }
95 #endif
96
97         return 0;
98 }
99
100 static int phy_meson_g12a_usb2_init(struct phy *phy)
101 {
102         struct udevice *dev = phy->dev;
103         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
104         int ret;
105
106         ret = reset_assert(&priv->reset);
107         udelay(1);
108         ret |= reset_deassert(&priv->reset);
109         if (ret)
110                 return ret;
111
112         udelay(RESET_COMPLETE_TIME);
113
114         /* usb2_otg_aca_en == 0 */
115         regmap_update_bits(priv->regmap, PHY_CTRL_R21, BIT(2), 0);
116
117         /* PLL Setup : 24MHz * 20 / 1 = 480MHz */
118         regmap_write(priv->regmap, PHY_CTRL_R16, 0x39400414);
119         regmap_write(priv->regmap, PHY_CTRL_R17, 0x927e0000);
120         regmap_write(priv->regmap, PHY_CTRL_R18, 0xac5f49e5);
121
122         udelay(PLL_RESET_COMPLETE_TIME);
123
124         /* UnReset PLL */
125         regmap_write(priv->regmap, PHY_CTRL_R16, 0x19400414);
126
127         /* PHY Tuning */
128         regmap_write(priv->regmap, PHY_CTRL_R20, 0xfe18);
129         regmap_write(priv->regmap, PHY_CTRL_R4, 0x8000fff);
130
131         /* Tuning Disconnect Threshold */
132         regmap_write(priv->regmap, PHY_CTRL_R3, 0x34);
133
134         /* Analog Settings */
135         regmap_write(priv->regmap, PHY_CTRL_R14, 0);
136         regmap_write(priv->regmap, PHY_CTRL_R13, 0x78000);
137
138         return 0;
139 }
140
141 static int phy_meson_g12a_usb2_exit(struct phy *phy)
142 {
143         struct udevice *dev = phy->dev;
144         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
145         int ret;
146
147         ret = reset_assert(&priv->reset);
148         if (ret)
149                 return ret;
150
151         return 0;
152 }
153
154 struct phy_ops meson_g12a_usb2_phy_ops = {
155         .init = phy_meson_g12a_usb2_init,
156         .exit = phy_meson_g12a_usb2_exit,
157         .power_on = phy_meson_g12a_usb2_power_on,
158         .power_off = phy_meson_g12a_usb2_power_off,
159 };
160
161 int meson_g12a_usb2_phy_probe(struct udevice *dev)
162 {
163         struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
164         int ret;
165
166         ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
167         if (ret)
168                 return ret;
169
170         ret = reset_get_by_index(dev, 0, &priv->reset);
171         if (ret == -ENOTSUPP)
172                 return 0;
173         else if (ret)
174                 return ret;
175
176         ret = reset_deassert(&priv->reset);
177         if (ret) {
178                 reset_release_all(&priv->reset, 1);
179                 return ret;
180         }
181
182 #if CONFIG_IS_ENABLED(CLK)
183         ret = clk_get_by_index(dev, 0, &priv->clk);
184         if (ret < 0)
185                 return ret;
186
187         ret = clk_enable(&priv->clk);
188         if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
189                 pr_err("failed to enable PHY clock\n");
190                 clk_free(&priv->clk);
191                 return ret;
192         }
193 #endif
194
195 #if CONFIG_IS_ENABLED(DM_REGULATOR)
196         ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply);
197         if (ret && ret != -ENOENT) {
198                 pr_err("Failed to get PHY regulator\n");
199                 return ret;
200         }
201 #endif
202
203         return 0;
204 }
205
206 static const struct udevice_id meson_g12a_usb2_phy_ids[] = {
207         { .compatible = "amlogic,g12a-usb2-phy" },
208         { }
209 };
210
211 U_BOOT_DRIVER(meson_g12a_usb2_phy) = {
212         .name = "meson_g12a_usb2_phy",
213         .id = UCLASS_PHY,
214         .of_match = meson_g12a_usb2_phy_ids,
215         .probe = meson_g12a_usb2_phy_probe,
216         .ops = &meson_g12a_usb2_phy_ops,
217         .priv_auto_alloc_size = sizeof(struct phy_meson_g12a_usb2_priv),
218 };