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