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