GNU Linux-libre 6.1.24-gnu
[releases.git] / drivers / phy / rockchip / phy-rockchip-snps-pcie3.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip PCIE3.0 phy driver
4  *
5  * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
6  */
7
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/phy/pcie.h>
17 #include <linux/phy/phy.h>
18 #include <linux/regmap.h>
19 #include <linux/reset.h>
20
21 /* Register for RK3568 */
22 #define GRF_PCIE30PHY_CON1                      0x4
23 #define GRF_PCIE30PHY_CON6                      0x18
24 #define GRF_PCIE30PHY_CON9                      0x24
25 #define GRF_PCIE30PHY_DA_OCM                    (BIT(15) | BIT(31))
26 #define GRF_PCIE30PHY_STATUS0                   0x80
27 #define GRF_PCIE30PHY_WR_EN                     (0xf << 16)
28 #define SRAM_INIT_DONE(reg)                     (reg & BIT(14))
29
30 #define RK3568_BIFURCATION_LANE_0_1             BIT(0)
31
32 /* Register for RK3588 */
33 #define PHP_GRF_PCIESEL_CON                     0x100
34 #define RK3588_PCIE3PHY_GRF_CMN_CON0            0x0
35 #define RK3588_PCIE3PHY_GRF_PHY0_STATUS1        0x904
36 #define RK3588_PCIE3PHY_GRF_PHY1_STATUS1        0xa04
37 #define RK3588_SRAM_INIT_DONE(reg)              (reg & BIT(0))
38
39 #define RK3588_BIFURCATION_LANE_0_1             BIT(0)
40 #define RK3588_BIFURCATION_LANE_2_3             BIT(1)
41 #define RK3588_LANE_AGGREGATION         BIT(2)
42
43 struct rockchip_p3phy_ops;
44
45 struct rockchip_p3phy_priv {
46         const struct rockchip_p3phy_ops *ops;
47         void __iomem *mmio;
48         /* mode: RC, EP */
49         int mode;
50         /* pcie30_phymode: Aggregation, Bifurcation */
51         int pcie30_phymode;
52         struct regmap *phy_grf;
53         struct regmap *pipe_grf;
54         struct reset_control *p30phy;
55         struct phy *phy;
56         struct clk_bulk_data *clks;
57         int num_clks;
58         int num_lanes;
59         u32 lanes[4];
60 };
61
62 struct rockchip_p3phy_ops {
63         int (*phy_init)(struct rockchip_p3phy_priv *priv);
64 };
65
66 static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
67 {
68         struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
69
70         /* Actually We don't care EP/RC mode, but just record it */
71         switch (submode) {
72         case PHY_MODE_PCIE_RC:
73                 priv->mode = PHY_MODE_PCIE_RC;
74                 break;
75         case PHY_MODE_PCIE_EP:
76                 priv->mode = PHY_MODE_PCIE_EP;
77                 break;
78         default:
79                 dev_err(&phy->dev, "%s, invalid mode\n", __func__);
80                 return -EINVAL;
81         }
82
83         return 0;
84 }
85
86 static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
87 {
88         struct phy *phy = priv->phy;
89         bool bifurcation = false;
90         int ret;
91         u32 reg;
92
93         /* Deassert PCIe PMA output clamp mode */
94         regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
95
96         for (int i = 0; i < priv->num_lanes; i++) {
97                 dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]);
98                 if (priv->lanes[i] > 1)
99                         bifurcation = true;
100         }
101
102         /* Set bifurcation if needed, and it doesn't care RC/EP */
103         if (bifurcation) {
104                 dev_info(&phy->dev, "bifurcation enabled\n");
105                 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
106                              GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
107                 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
108                              GRF_PCIE30PHY_DA_OCM);
109         } else {
110                 dev_dbg(&phy->dev, "bifurcation disabled\n");
111                 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
112                              GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
113         }
114
115         reset_control_deassert(priv->p30phy);
116
117         ret = regmap_read_poll_timeout(priv->phy_grf,
118                                        GRF_PCIE30PHY_STATUS0,
119                                        reg, SRAM_INIT_DONE(reg),
120                                        0, 500);
121         if (ret)
122                 dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
123                        __func__, reg);
124         return ret;
125 }
126
127 static const struct rockchip_p3phy_ops rk3568_ops = {
128         .phy_init = rockchip_p3phy_rk3568_init,
129 };
130
131 static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
132 {
133         u32 reg = 0;
134         u8 mode = 0;
135         int ret;
136
137         /* Deassert PCIe PMA output clamp mode */
138         regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
139
140         /* Set bifurcation if needed */
141         for (int i = 0; i < priv->num_lanes; i++) {
142                 if (!priv->lanes[i])
143                         mode |= (BIT(i) << 3);
144
145                 if (priv->lanes[i] > 1)
146                         mode |= (BIT(i) >> 1);
147         }
148
149         if (!mode)
150                 reg = RK3588_LANE_AGGREGATION;
151         else {
152                 if (mode & (BIT(0) | BIT(1)))
153                         reg |= RK3588_BIFURCATION_LANE_0_1;
154
155                 if (mode & (BIT(2) | BIT(3)))
156                         reg |= RK3588_BIFURCATION_LANE_2_3;
157         }
158
159         regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
160
161         /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
162         if (!IS_ERR(priv->pipe_grf)) {
163                 reg = (mode & (BIT(6) | BIT(7))) >> 6;
164                 if (reg)
165                         regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
166                                      (reg << 16) | reg);
167         }
168
169         reset_control_deassert(priv->p30phy);
170
171         ret = regmap_read_poll_timeout(priv->phy_grf,
172                                        RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
173                                        reg, RK3588_SRAM_INIT_DONE(reg),
174                                        0, 500);
175         ret |= regmap_read_poll_timeout(priv->phy_grf,
176                                         RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
177                                         reg, RK3588_SRAM_INIT_DONE(reg),
178                                         0, 500);
179         if (ret)
180                 dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n",
181                         reg);
182         return ret;
183 }
184
185 static const struct rockchip_p3phy_ops rk3588_ops = {
186         .phy_init = rockchip_p3phy_rk3588_init,
187 };
188
189 static int rochchip_p3phy_init(struct phy *phy)
190 {
191         struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
192         int ret;
193
194         ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
195         if (ret) {
196                 dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret);
197                 return ret;
198         }
199
200         reset_control_assert(priv->p30phy);
201         udelay(1);
202
203         if (priv->ops->phy_init) {
204                 ret = priv->ops->phy_init(priv);
205                 if (ret)
206                         clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
207         }
208
209         return ret;
210 }
211
212 static int rochchip_p3phy_exit(struct phy *phy)
213 {
214         struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
215
216         clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
217         reset_control_assert(priv->p30phy);
218         return 0;
219 }
220
221 static const struct phy_ops rochchip_p3phy_ops = {
222         .init = rochchip_p3phy_init,
223         .exit = rochchip_p3phy_exit,
224         .set_mode = rockchip_p3phy_set_mode,
225         .owner = THIS_MODULE,
226 };
227
228 static int rockchip_p3phy_probe(struct platform_device *pdev)
229 {
230         struct phy_provider *phy_provider;
231         struct device *dev = &pdev->dev;
232         struct rockchip_p3phy_priv *priv;
233         struct device_node *np = dev->of_node;
234         int ret;
235
236         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
237         if (!priv)
238                 return -ENOMEM;
239
240         priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
241         if (IS_ERR(priv->mmio)) {
242                 ret = PTR_ERR(priv->mmio);
243                 return ret;
244         }
245
246         priv->ops = of_device_get_match_data(&pdev->dev);
247         if (!priv->ops) {
248                 dev_err(dev, "no of match data provided\n");
249                 return -EINVAL;
250         }
251
252         priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
253         if (IS_ERR(priv->phy_grf)) {
254                 dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
255                 return PTR_ERR(priv->phy_grf);
256         }
257
258         if (of_device_is_compatible(np, "rockchip,rk3588-pcie3-phy")) {
259                 priv->pipe_grf =
260                         syscon_regmap_lookup_by_phandle(dev->of_node,
261                                                         "rockchip,pipe-grf");
262                 if (IS_ERR(priv->pipe_grf))
263                         dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
264         } else {
265                 priv->pipe_grf = NULL;
266         }
267
268         priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes",
269                                                              priv->lanes, 2,
270                                                              ARRAY_SIZE(priv->lanes));
271
272         /* if no data-lanes assume aggregation */
273         if (priv->num_lanes == -EINVAL) {
274                 dev_dbg(dev, "no data-lanes property found\n");
275                 priv->num_lanes = 1;
276                 priv->lanes[0] = 1;
277         } else if (priv->num_lanes < 0) {
278                 dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes);
279                 return priv->num_lanes;
280         }
281
282         priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
283         if (IS_ERR(priv->phy)) {
284                 dev_err(dev, "failed to create combphy\n");
285                 return PTR_ERR(priv->phy);
286         }
287
288         priv->p30phy = devm_reset_control_get_optional_exclusive(dev, "phy");
289         if (IS_ERR(priv->p30phy)) {
290                 return dev_err_probe(dev, PTR_ERR(priv->p30phy),
291                                      "failed to get phy reset control\n");
292         }
293         if (!priv->p30phy)
294                 dev_info(dev, "no phy reset control specified\n");
295
296         priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
297         if (priv->num_clks < 1)
298                 return -ENODEV;
299
300         dev_set_drvdata(dev, priv);
301         phy_set_drvdata(priv->phy, priv);
302         phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
303         return PTR_ERR_OR_ZERO(phy_provider);
304 }
305
306 static const struct of_device_id rockchip_p3phy_of_match[] = {
307         { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
308         { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
309         { },
310 };
311 MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);
312
313 static struct platform_driver rockchip_p3phy_driver = {
314         .probe  = rockchip_p3phy_probe,
315         .driver = {
316                 .name = "rockchip-snps-pcie3-phy",
317                 .of_match_table = rockchip_p3phy_of_match,
318         },
319 };
320 module_platform_driver(rockchip_p3phy_driver);
321 MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver");
322 MODULE_LICENSE("GPL");