]> git.sur5r.net Git - u-boot/blob - drivers/phy/meson-gxl-usb3.c
Merge git://git.denx.de/u-boot-imx
[u-boot] / drivers / phy / meson-gxl-usb3.c
1 /*
2  * Meson GXL USB3 PHY driver
3  *
4  * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
5  * Copyright (C) 2018 BayLibre, SAS
6  * Author: Neil Armstrong <narmstron@baylibre.com>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.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 <clk.h>
19
20 #include <linux/bitops.h>
21 #include <linux/compat.h>
22 #include <linux/bitfield.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 #define USB_R0                                                  0x00
27         #define USB_R0_P30_FSEL_MASK                            GENMASK(5, 0)
28         #define USB_R0_P30_PHY_RESET                            BIT(6)
29         #define USB_R0_P30_TEST_POWERDOWN_HSP                   BIT(7)
30         #define USB_R0_P30_TEST_POWERDOWN_SSP                   BIT(8)
31         #define USB_R0_P30_ACJT_LEVEL_MASK                      GENMASK(13, 9)
32         #define USB_R0_P30_TX_BOOST_LEVEL_MASK                  GENMASK(16, 14)
33         #define USB_R0_P30_LANE0_TX2RX_LOOPBACK                 BIT(17)
34         #define USB_R0_P30_LANE0_EXT_PCLK_REQ                   BIT(18)
35         #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK             GENMASK(28, 19)
36         #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK               GENMASK(30, 29)
37         #define USB_R0_U2D_ACT                                  BIT(31)
38
39 #define USB_R1                                                  0x04
40         #define USB_R1_U3H_BIGENDIAN_GS                         BIT(0)
41         #define USB_R1_U3H_PME_ENABLE                           BIT(1)
42         #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK            GENMASK(6, 2)
43         #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK            GENMASK(11, 7)
44         #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK            GENMASK(15, 12)
45         #define USB_R1_U3H_HOST_U3_PORT_DISABLE                 BIT(16)
46         #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT      BIT(17)
47         #define USB_R1_U3H_HOST_MSI_ENABLE                      BIT(18)
48         #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK                 GENMASK(24, 19)
49         #define USB_R1_P30_PCS_TX_SWING_FULL_MASK               GENMASK(31, 25)
50
51 #define USB_R2                                                  0x08
52         #define USB_R2_P30_CR_DATA_IN_MASK                      GENMASK(15, 0)
53         #define USB_R2_P30_CR_READ                              BIT(16)
54         #define USB_R2_P30_CR_WRITE                             BIT(17)
55         #define USB_R2_P30_CR_CAP_ADDR                          BIT(18)
56         #define USB_R2_P30_CR_CAP_DATA                          BIT(19)
57         #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK             GENMASK(25, 20)
58         #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK               GENMASK(31, 26)
59
60 #define USB_R3                                                  0x0c
61         #define USB_R3_P30_SSC_ENABLE                           BIT(0)
62         #define USB_R3_P30_SSC_RANGE_MASK                       GENMASK(3, 1)
63         #define USB_R3_P30_SSC_REF_CLK_SEL_MASK                 GENMASK(12, 4)
64         #define USB_R3_P30_REF_SSP_EN                           BIT(13)
65         #define USB_R3_P30_LOS_BIAS_MASK                        GENMASK(18, 16)
66         #define USB_R3_P30_LOS_LEVEL_MASK                       GENMASK(23, 19)
67         #define USB_R3_P30_MPLL_MULTIPLIER_MASK                 GENMASK(30, 24)
68
69 #define USB_R4                                                  0x10
70         #define USB_R4_P21_PORT_RESET_0                         BIT(0)
71         #define USB_R4_P21_SLEEP_M0                             BIT(1)
72         #define USB_R4_MEM_PD_MASK                              GENMASK(3, 2)
73         #define USB_R4_P21_ONLY                                 BIT(4)
74
75 #define USB_R5                                                  0x14
76         #define USB_R5_ID_DIG_SYNC                              BIT(0)
77         #define USB_R5_ID_DIG_REG                               BIT(1)
78         #define USB_R5_ID_DIG_CFG_MASK                          GENMASK(3, 2)
79         #define USB_R5_ID_DIG_EN_0                              BIT(4)
80         #define USB_R5_ID_DIG_EN_1                              BIT(5)
81         #define USB_R5_ID_DIG_CURR                              BIT(6)
82         #define USB_R5_ID_DIG_IRQ                               BIT(7)
83         #define USB_R5_ID_DIG_TH_MASK                           GENMASK(15, 8)
84         #define USB_R5_ID_DIG_CNT_MASK                          GENMASK(23, 16)
85
86 /* read-only register */
87 #define USB_R6                                                  0x18
88         #define USB_R6_P30_CR_DATA_OUT_MASK                     GENMASK(15, 0)
89         #define USB_R6_P30_CR_ACK                               BIT(16)
90
91 struct phy_meson_gxl_usb3_priv {
92         struct regmap           *regmap;
93 #if CONFIG_IS_ENABLED(CLK)
94         struct clk              clk;
95 #endif
96 };
97
98 static int
99 phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv)
100 {
101         uint val;
102
103         regmap_read(priv->regmap, USB_R0, &val);
104         val &= ~USB_R0_U2D_ACT;
105         regmap_write(priv->regmap, USB_R0, val);
106
107         regmap_read(priv->regmap, USB_R4, &val);
108         val &= ~USB_R4_P21_SLEEP_M0;
109         regmap_write(priv->regmap, USB_R4, val);
110
111         return 0;
112 }
113
114 static int phy_meson_gxl_usb3_power_on(struct phy *phy)
115 {
116         struct udevice *dev = phy->dev;
117         struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
118         uint val;
119
120         regmap_read(priv->regmap, USB_R5, &val);
121         val |= USB_R5_ID_DIG_EN_0;
122         val |= USB_R5_ID_DIG_EN_1;
123         val &= ~USB_R5_ID_DIG_TH_MASK;
124         val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff);
125         regmap_write(priv->regmap, USB_R5, val);
126
127         return phy_meson_gxl_usb3_set_host_mode(priv);
128 }
129
130 static int phy_meson_gxl_usb3_power_off(struct phy *phy)
131 {
132         struct udevice *dev = phy->dev;
133         struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
134         uint val;
135
136         regmap_read(priv->regmap, USB_R5, &val);
137         val &= ~USB_R5_ID_DIG_EN_0;
138         val &= ~USB_R5_ID_DIG_EN_1;
139         regmap_write(priv->regmap, USB_R5, val);
140
141         return 0;
142 }
143
144 static int phy_meson_gxl_usb3_init(struct phy *phy)
145 {
146         struct udevice *dev = phy->dev;
147         struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
148         uint val;
149
150         regmap_read(priv->regmap, USB_R1, &val);
151         val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK;
152         val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20);
153         regmap_write(priv->regmap, USB_R1, val);
154
155         return 0;
156 }
157
158 struct phy_ops meson_gxl_usb3_phy_ops = {
159         .init = phy_meson_gxl_usb3_init,
160         .power_on = phy_meson_gxl_usb3_power_on,
161         .power_off = phy_meson_gxl_usb3_power_off,
162 };
163
164 int meson_gxl_usb3_phy_probe(struct udevice *dev)
165 {
166         struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
167         int ret;
168
169         ret = regmap_init_mem(dev, &priv->regmap);
170         if (ret)
171                 return ret;
172         
173 #if CONFIG_IS_ENABLED(CLK)
174         ret = clk_get_by_index(dev, 0, &priv->clk);
175         if (ret < 0)
176                 return ret;
177
178         ret = clk_enable(&priv->clk);
179         if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
180                 pr_err("failed to enable PHY clock\n");
181                 clk_free(&priv->clk);
182                 return ret;
183         }
184 #endif
185
186         return 0;
187 }
188
189 static const struct udevice_id meson_gxl_usb3_phy_ids[] = {
190         { .compatible = "amlogic,meson-gxl-usb3-phy" },
191         { }
192 };
193
194 U_BOOT_DRIVER(meson_gxl_usb3_phy) = {
195         .name = "meson_gxl_usb3_phy",
196         .id = UCLASS_PHY,
197         .of_match = meson_gxl_usb3_phy_ids,
198         .probe = meson_gxl_usb3_phy_probe,
199         .ops = &meson_gxl_usb3_phy_ops,
200         .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv),
201 };