hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
....@@ -13,11 +13,13 @@
1313 #include <linux/mfd/syscon.h>
1414 #include <linux/module.h>
1515 #include <linux/of_device.h>
16
+#include <linux/phy/pcie.h>
1617 #include <linux/phy/phy.h>
1718 #include <linux/regmap.h>
1819 #include <linux/reset.h>
19
-#include <dt-bindings/phy/phy.h>
20
+#include <dt-bindings/phy/phy-snps-pcie3.h>
2021
22
+/* Register for RK3568 */
2123 #define GRF_PCIE30PHY_CON1 0x4
2224 #define GRF_PCIE30PHY_CON4 0x10
2325 #define GRF_PCIE30PHY_CON6 0x18
....@@ -25,24 +27,41 @@
2527 #define GRF_PCIE30PHY_STATUS0 0x80
2628 #define SRAM_INIT_DONE(reg) (reg & BIT(14))
2729
30
+/* Register for RK3588 */
31
+#define PHP_GRF_PCIESEL_CON 0x100
32
+#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
33
+#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
34
+#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
35
+#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
36
+
37
+struct rockchip_p3phy_ops;
38
+
2839 struct rockchip_p3phy_priv {
40
+ const struct rockchip_p3phy_ops *ops;
2941 void __iomem *mmio;
42
+ /* mode: RC, EP */
3043 int mode;
44
+ /* pcie30_phymode: Aggregation, Bifurcation */
45
+ int pcie30_phymode;
3146 struct regmap *phy_grf;
47
+ struct regmap *pipe_grf;
3248 struct reset_control *p30phy;
33
- struct clk *ref_clk_m;
34
- struct clk *ref_clk_n;
35
- struct clk *pclk;
3649 struct phy *phy;
50
+ struct clk_bulk_data *clks;
51
+ int num_clks;
3752 bool is_bifurcation;
3853 };
3954
40
-static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode)
55
+struct rockchip_p3phy_ops {
56
+ int (*phy_init)(struct rockchip_p3phy_priv *priv);
57
+};
58
+
59
+static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
4160 {
4261 struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
4362
4463 /* Acutally We don't care EP/RC mode, but just record it */
45
- switch (mode) {
64
+ switch (submode) {
4665 case PHY_MODE_PCIE_RC:
4766 priv->mode = PHY_MODE_PCIE_RC;
4867 break;
....@@ -64,27 +83,11 @@
6483 #include "phy-rockchip-snps-pcie3.fw"
6584 };
6685
67
-static int rochchip_p3phy_init(struct phy *phy)
86
+static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
6887 {
69
- struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
7088 int i;
7189 int ret = 0;
7290 u32 reg;
73
-
74
- ret = clk_prepare_enable(priv->ref_clk_m);
75
- if (ret < 0)
76
- return ret;
77
-
78
- ret = clk_prepare_enable(priv->ref_clk_n);
79
- if (ret < 0)
80
- goto err_ref;
81
-
82
- ret = clk_prepare_enable(priv->pclk);
83
- if (ret < 0)
84
- goto err_pclk;
85
-
86
- reset_control_assert(priv->p30phy);
87
- udelay(1);
8891
8992 /* Deassert PCIe PMA output clamp mode */
9093 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
....@@ -96,13 +99,12 @@
9699 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
97100 (0x1 << 15) | (0x1 << 31));
98101 }
99
-
100102 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
101103 (0x0 << 14) | (0x1 << (14 + 16))); //sdram_ld_done
102104 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
103105 (0x0 << 13) | (0x1 << (13 + 16))); //sdram_bypass
104
- reset_control_deassert(priv->p30phy);
105106
107
+ reset_control_deassert(priv->p30phy);
106108 ret = regmap_read_poll_timeout(priv->phy_grf,
107109 GRF_PCIE30PHY_STATUS0,
108110 reg, SRAM_INIT_DONE(reg),
....@@ -110,7 +112,7 @@
110112 if (ret) {
111113 pr_err("%s: lock failed 0x%x, check input refclk and power supply\n",
112114 __func__, reg);
113
- goto err_pclk;
115
+ goto out;
114116 }
115117
116118 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
....@@ -124,20 +126,70 @@
124126 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
125127 (0x1 << 14) | (0x1 << (14 + 16))); //sdram_ld_done
126128
127
- return 0;
128
-err_pclk:
129
- clk_disable_unprepare(priv->ref_clk_n);
130
-err_ref:
131
- clk_disable_unprepare(priv->ref_clk_m);
129
+out:
130
+ return ret;
131
+}
132
+
133
+static const struct rockchip_p3phy_ops rk3568_ops = {
134
+ .phy_init = rockchip_p3phy_rk3568_init,
135
+};
136
+
137
+static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
138
+{
139
+ int ret = 0;
140
+ u32 reg;
141
+
142
+ /* Deassert PCIe PMA output clamp mode */
143
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
144
+ (0x1 << 8) | (0x1 << 24));
145
+
146
+ reset_control_deassert(priv->p30phy);
147
+
148
+ ret = regmap_read_poll_timeout(priv->phy_grf,
149
+ RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
150
+ reg, RK3588_SRAM_INIT_DONE(reg),
151
+ 0, 500);
152
+ ret |= regmap_read_poll_timeout(priv->phy_grf,
153
+ RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
154
+ reg, RK3588_SRAM_INIT_DONE(reg),
155
+ 0, 500);
156
+ if (ret)
157
+ pr_err("%s: lock failed 0x%x, check input refclk and power supply\n",
158
+ __func__, reg);
159
+ return ret;
160
+}
161
+
162
+static const struct rockchip_p3phy_ops rk3588_ops = {
163
+ .phy_init = rockchip_p3phy_rk3588_init,
164
+};
165
+
166
+static int rochchip_p3phy_init(struct phy *phy)
167
+{
168
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
169
+ int ret;
170
+
171
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
172
+ if (ret) {
173
+ pr_err("failed to enable PCIe bulk clks %d\n", ret);
174
+ return ret;
175
+ }
176
+
177
+ reset_control_assert(priv->p30phy);
178
+ udelay(1);
179
+
180
+ if (priv->ops->phy_init) {
181
+ ret = priv->ops->phy_init(priv);
182
+ if (ret)
183
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
184
+ };
185
+
132186 return ret;
133187 }
134188
135189 static int rochchip_p3phy_exit(struct phy *phy)
136190 {
137191 struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
138
- clk_disable_unprepare(priv->ref_clk_m);
139
- clk_disable_unprepare(priv->ref_clk_n);
140
- clk_disable_unprepare(priv->pclk);
192
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
141193 reset_control_assert(priv->p30phy);
142194 return 0;
143195 }
....@@ -157,6 +209,7 @@
157209 struct device_node *np = dev->of_node;
158210 struct resource *res;
159211 int ret;
212
+ u32 val, reg;
160213
161214 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
162215 if (!priv)
....@@ -169,11 +222,43 @@
169222 return ret;
170223 }
171224
225
+ priv->ops = of_device_get_match_data(&pdev->dev);
226
+ if (!priv->ops) {
227
+ dev_err(&pdev->dev, "no of match data provided\n");
228
+ return -EINVAL;
229
+ }
230
+
172231 priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
173232 if (IS_ERR(priv->phy_grf)) {
174233 dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
175234 return PTR_ERR(priv->phy_grf);
176235 }
236
+
237
+ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
238
+ "rockchip,pipe-grf");
239
+ if (IS_ERR(priv->pipe_grf))
240
+ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
241
+
242
+ ret = device_property_read_u32(dev, "rockchip,pcie30-phymode", &val);
243
+ if (!ret)
244
+ priv->pcie30_phymode = val;
245
+ else
246
+ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION;
247
+
248
+ /* Select correct pcie30_phymode */
249
+ if (priv->pcie30_phymode > 4)
250
+ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION;
251
+
252
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
253
+ (0x7<<16) | priv->pcie30_phymode);
254
+
255
+ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
256
+ if (!IS_ERR(priv->pipe_grf)) {
257
+ reg = priv->pcie30_phymode & 3;
258
+ if (reg)
259
+ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
260
+ (reg << 16) | reg);
261
+ };
177262
178263 priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
179264 if (IS_ERR(priv->phy)) {
....@@ -187,23 +272,9 @@
187272 priv->p30phy = NULL;
188273 }
189274
190
- priv->ref_clk_m = devm_clk_get(dev, "refclk_m");
191
- if (IS_ERR(priv->ref_clk_m)) {
192
- dev_err(dev, "failed to find ref clock M\n");
193
- return PTR_ERR(priv->ref_clk_m);
194
- }
195
-
196
- priv->ref_clk_n = devm_clk_get(dev, "refclk_n");
197
- if (IS_ERR(priv->ref_clk_n)) {
198
- dev_err(dev, "failed to find ref clock N\n");
199
- return PTR_ERR(priv->ref_clk_n);
200
- }
201
-
202
- priv->pclk = devm_clk_get(dev, "pclk");
203
- if (IS_ERR(priv->pclk)) {
204
- dev_err(dev, "failed to find pclk\n");
205
- return PTR_ERR(priv->pclk);
206
- }
275
+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
276
+ if (priv->num_clks < 1)
277
+ return -ENODEV;
207278
208279 dev_set_drvdata(dev, priv);
209280 phy_set_drvdata(priv->phy, priv);
....@@ -212,7 +283,8 @@
212283 }
213284
214285 static const struct of_device_id rockchip_p3phy_of_match[] = {
215
- { .compatible = "rockchip,rk3568-pcie3-phy" },
286
+ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
287
+ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
216288 { },
217289 };
218290 MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);