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