1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6 */
7
8 #include <linux/kernel.h>
9 #include <linux/clk.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/delay.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
17 #include <linux/reset.h>
18 #include <linux/phy/phy.h>
19
20 #define HIWORD_UPDATE(x, h, l) ((((x) << (l)) & GENMASK((h), (l))) | (GENMASK((h), (l)) << 16))
21
22 #define EDP_PHY_GRF_CON0 0x0000
23 #define EDP_PHY_TX_IDLE(x) HIWORD_UPDATE(x, 11, 8)
24 #define EDP_PHY_TX_PD(x) HIWORD_UPDATE(x, 7, 4)
25 #define EDP_PHY_IDDQ_EN(x) HIWORD_UPDATE(x, 1, 1)
26 #define EDP_PHY_PD_PLL(x) HIWORD_UPDATE(x, 0, 0)
27 #define EDP_PHY_GRF_CON1 0x0004
28 #define EDP_PHY_PLL_DIV(x) HIWORD_UPDATE(x, 14, 0)
29 #define EDP_PHY_GRF_CON2 0x0008
30 #define EDP_PHY_TX_RTERM(x) HIWORD_UPDATE(x, 10, 8)
31 #define EDP_PHY_RATE(x) HIWORD_UPDATE(x, 5, 4)
32 #define EDP_PHY_REF_DIV(x) HIWORD_UPDATE(x, 3, 0)
33 #define EDP_PHY_GRF_CON3 0x000c
34 #define EDP_PHY_TX_EMP(lane, x) HIWORD_UPDATE(x, 4 * ((lane) + 1) - 1, 4 * (lane))
35 #define EDP_PHY_GRF_CON4 0x0010
36 #define EDP_PHY_TX_AMP(lane, x) HIWORD_UPDATE(x, 4 * ((lane) + 1) - 2, 4 * (lane))
37 #define EDP_PHY_GRF_CON5 0x0014
38 #define EDP_PHY_TX_MODE(x) HIWORD_UPDATE(x, 9, 8)
39 #define EDP_PHY_TX_AMP_SCALE(lane, x) HIWORD_UPDATE(x, 2 * ((lane) + 1) - 1, 2 * (lane))
40 #define EDP_PHY_GRF_CON6 0x0018
41 #define EDP_PHY_SSC_DEPTH(x) HIWORD_UPDATE(x, 15, 12)
42 #define EDP_PHY_SSC_EN(x) HIWORD_UPDATE(x, 11, 11)
43 #define EDP_PHY_SSC_CNT(x) HIWORD_UPDATE(x, 9, 0)
44 #define EDP_PHY_GRF_CON7 0x001c
45 #define EDP_PHY_GRF_CON8 0x0020
46 #define EDP_PHY_PLL_CTL_H(x) HIWORD_UPDATE(x, 15, 0)
47 #define EDP_PHY_GRF_CON9 0x0024
48 #define EDP_PHY_TX_CTL(x) HIWORD_UPDATE(x, 15, 0)
49 #define EDP_PHY_GRF_CON10 0x0028
50 #define EDP_PHY_AUX_RCV_PD_SEL(x) HIWORD_UPDATE(x, 5, 5)
51 #define EDP_PHY_AUX_DRV_PD_SEL(x) HIWORD_UPDATE(x, 4, 4)
52 #define EDP_PHY_AUX_IDLE_MASK BIT(2)
53 #define EDP_PHY_AUX_IDLE(x) HIWORD_UPDATE(x, 2, 2)
54 #define EDP_PHY_AUX_RCV_PD(x) HIWORD_UPDATE(x, 1, 1)
55 #define EDP_PHY_AUX_DRV_PD(x) HIWORD_UPDATE(x, 0, 0)
56 #define EDP_PHY_GRF_CON11 0x002c
57 #define EDP_PHY_AUX_RCV_VCM(x) HIWORD_UPDATE(x, 14, 12)
58 #define EDP_PHY_AUX_MODE(x) HIWORD_UPDATE(x, 11, 10)
59 #define EDP_PHY_AUX_AMP_SCALE(x) HIWORD_UPDATE(x, 9, 8)
60 #define EDP_PHY_AUX_AMP(x) HIWORD_UPDATE(x, 6, 4)
61 #define EDP_PHY_AUX_RTERM(x) HIWORD_UPDATE(x, 2, 0)
62 #define EDP_PHY_GRF_STATUS0 0x0030
63 #define PLL_RDY BIT(0)
64 #define EDP_PHY_GRF_STATUS1 0x0034
65
66 struct rockchip_edp_phy {
67 void __iomem *regs;
68 struct device *dev;
69 struct clk *pclk;
70 struct clk *refclk;
71 struct reset_control *apb_reset;
72 };
73
74 static struct {
75 int amp;
76 int amp_scale;
77 int emp;
78 } vp[4][4] = {
79 {{0x1, 0x1, 0x0}, {0x2, 0x1, 0x4}, {0x3, 0x1, 0x8}, {0x4, 0x1, 0xd}},
80 {{0x3, 0x1, 0x0}, {0x5, 0x1, 0x7}, {0x6, 0x1, 0x6}, {-1, -1, -1}},
81 {{0x5, 0x1, 0x0}, {0x7, 0x1, 0x4}, {-1, -1, -1}, {-1, -1, -1}},
82 {{0x7, 0x1, 0x0}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}},
83 };
84
rockchip_edp_phy_set_voltages(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)85 static int rockchip_edp_phy_set_voltages(struct rockchip_edp_phy *edpphy, struct phy_configure_opts_dp *dp)
86 {
87 u8 lane;
88 u32 val;
89
90 for (lane = 0; lane < dp->lanes; lane++) {
91 val = vp[dp->voltage[lane]][dp->pre[lane]].amp;
92 writel(EDP_PHY_TX_AMP(lane, val), edpphy->regs + EDP_PHY_GRF_CON4);
93
94 val = vp[dp->voltage[lane]][dp->pre[lane]].amp_scale;
95 writel(EDP_PHY_TX_AMP_SCALE(lane, val), edpphy->regs + EDP_PHY_GRF_CON5);
96
97 val = vp[dp->voltage[lane]][dp->pre[lane]].emp;
98 writel(EDP_PHY_TX_EMP(lane, val), edpphy->regs + EDP_PHY_GRF_CON3);
99 }
100
101 return 0;
102 }
103
rockchip_edp_phy_set_rate(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)104 static int rockchip_edp_phy_set_rate(struct rockchip_edp_phy *edpphy, struct phy_configure_opts_dp *dp)
105 {
106 u32 value;
107 int ret;
108
109 writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf), edpphy->regs + EDP_PHY_GRF_CON0);
110 usleep_range(0x64, 0x65);
111 writel(EDP_PHY_TX_MODE(0x3), edpphy->regs + EDP_PHY_GRF_CON5);
112 writel(EDP_PHY_PD_PLL(0x1), edpphy->regs + EDP_PHY_GRF_CON0);
113
114 switch (dp->link_rate) {
115 case 0x654:
116 writel(EDP_PHY_PLL_DIV(0x4380), edpphy->regs + EDP_PHY_GRF_CON1);
117 writel(EDP_PHY_TX_RTERM(0x1) | EDP_PHY_RATE(0x1) | EDP_PHY_REF_DIV(0x0), edpphy->regs + EDP_PHY_GRF_CON2);
118 writel(EDP_PHY_PLL_CTL_H(0x0800), edpphy->regs + EDP_PHY_GRF_CON8);
119 writel(EDP_PHY_TX_CTL(0x0000), edpphy->regs + EDP_PHY_GRF_CON9);
120 break;
121 case 0xA8C:
122 writel(EDP_PHY_PLL_DIV(0x3840), edpphy->regs + EDP_PHY_GRF_CON1);
123 writel(EDP_PHY_TX_RTERM(0x1) | EDP_PHY_RATE(0x0) | EDP_PHY_REF_DIV(0x0), edpphy->regs + EDP_PHY_GRF_CON2);
124 writel(EDP_PHY_PLL_CTL_H(0x0800), edpphy->regs + EDP_PHY_GRF_CON8);
125 writel(EDP_PHY_TX_CTL(0x0000), edpphy->regs + EDP_PHY_GRF_CON9);
126 break;
127 }
128
129 if (dp->ssc) {
130 writel(EDP_PHY_SSC_DEPTH(0x9) | EDP_PHY_SSC_EN(0x1) | EDP_PHY_SSC_CNT(0x17d), edpphy->regs + EDP_PHY_GRF_CON6);
131 } else {
132 writel(EDP_PHY_SSC_EN(0x0), edpphy->regs + EDP_PHY_GRF_CON6);
133 }
134
135 writel(EDP_PHY_PD_PLL(0x0), edpphy->regs + EDP_PHY_GRF_CON0);
136 writel(EDP_PHY_TX_PD(~GENMASK(dp->lanes - 1, 0)), edpphy->regs + EDP_PHY_GRF_CON0);
137 ret = readl_poll_timeout(edpphy->regs + EDP_PHY_GRF_STATUS0, value, value & PLL_RDY, 0x64, 0x3E8);
138 if (ret) {
139 dev_err(edpphy->dev, "pll is not ready: %d\n", ret);
140 return ret;
141 }
142
143 writel(EDP_PHY_TX_MODE(0x0), edpphy->regs + EDP_PHY_GRF_CON5);
144 writel(EDP_PHY_TX_IDLE(~GENMASK(dp->lanes - 1, 0)), edpphy->regs + EDP_PHY_GRF_CON0);
145
146 return 0;
147 }
148
rockchip_edp_phy_verify_config(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)149 static int rockchip_edp_phy_verify_config(struct rockchip_edp_phy *edpphy, struct phy_configure_opts_dp *dp)
150 {
151 int i;
152
153 /* If changing link rate was required, verify it's supported. */
154 if (dp->set_rate) {
155 switch (dp->link_rate) {
156 case 0x654:
157 case 0xA8C:
158 /* valid bit rate */
159 break;
160 default:
161 return -EINVAL;
162 }
163 }
164
165 /* Verify lane count. */
166 switch (dp->lanes) {
167 case 1:
168 case 0x02:
169 case 0x04:
170 /* valid lane count. */
171 break;
172 default:
173 return -EINVAL;
174 }
175
176 /*
177 * If changing voltages is required, check swing and pre-emphasis
178 * levels, per-lane.
179 */
180 if (dp->set_voltages) {
181 /* Lane count verified previously. */
182 for (i = 0; i < dp->lanes; i++) {
183 if (dp->voltage[i] > 0x03 || dp->pre[i] > 0x03) {
184 return -EINVAL;
185 }
186
187 /*
188 * Sum of voltage swing and pre-emphasis levels cannot
189 * exceed 3.
190 */
191 if (dp->voltage[i] + dp->pre[i] > 0x03) {
192 return -EINVAL;
193 }
194 }
195 }
196
197 return 0;
198 }
199
rockchip_edp_phy_configure(struct phy * phy,union phy_configure_opts * opts)200 static int rockchip_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
201 {
202 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
203 int ret;
204
205 ret = rockchip_edp_phy_verify_config(edpphy, &opts->dp);
206 if (ret) {
207 dev_err(edpphy->dev, "invalid params for phy configure\n");
208 return ret;
209 }
210
211 if (opts->dp.set_rate) {
212 ret = rockchip_edp_phy_set_rate(edpphy, &opts->dp);
213 if (ret) {
214 dev_err(edpphy->dev, "rockchip_edp_phy_set_rate failed\n");
215 return ret;
216 }
217 }
218
219 if (opts->dp.set_voltages) {
220 ret = rockchip_edp_phy_set_voltages(edpphy, &opts->dp);
221 if (ret) {
222 dev_err(edpphy->dev, "rockchip_edp_phy_set_voltages failed\n");
223 return ret;
224 }
225 }
226
227 return 0;
228 }
229
rockchip_edp_phy_enabled(struct rockchip_edp_phy * edpphy)230 static bool rockchip_edp_phy_enabled(struct rockchip_edp_phy *edpphy)
231 {
232 u32 val;
233
234 val = readl(edpphy->regs + EDP_PHY_GRF_CON10);
235 if (val & EDP_PHY_AUX_IDLE_MASK) {
236 return false;
237 }
238
239 return true;
240 }
241
rockchip_edp_phy_power_on(struct phy * phy)242 static int rockchip_edp_phy_power_on(struct phy *phy)
243 {
244 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
245
246 clk_prepare_enable(edpphy->pclk);
247 clk_prepare_enable(edpphy->refclk);
248
249 if (rockchip_edp_phy_enabled(edpphy)) {
250 return 0;
251 }
252
253 reset_control_assert(edpphy->apb_reset);
254 usleep_range(0x64, 0x65);
255 reset_control_deassert(edpphy->apb_reset);
256 usleep_range(0x64, 0x65);
257
258 writel(EDP_PHY_AUX_RCV_PD(0x1) | EDP_PHY_AUX_DRV_PD(0x1) | EDP_PHY_AUX_IDLE(0x1), edpphy->regs + EDP_PHY_GRF_CON10);
259 writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf) | EDP_PHY_PD_PLL(0x1), edpphy->regs + EDP_PHY_GRF_CON0);
260 usleep_range(0x64, 0x65);
261
262 writel(EDP_PHY_AUX_RCV_VCM(0x4) | EDP_PHY_AUX_MODE(0x1) | EDP_PHY_AUX_AMP_SCALE(0x1) | EDP_PHY_AUX_AMP(0x3) |
263 EDP_PHY_AUX_RTERM(0x1),
264 edpphy->regs + EDP_PHY_GRF_CON11);
265
266 writel(EDP_PHY_AUX_RCV_PD(0x0) | EDP_PHY_AUX_DRV_PD(0x0), edpphy->regs + EDP_PHY_GRF_CON10);
267 usleep_range(0x64, 0x65);
268
269 writel(EDP_PHY_AUX_IDLE(0x0), edpphy->regs + EDP_PHY_GRF_CON10);
270 usleep_range(0x2710, 0x2AF8);
271
272 return 0;
273 }
274
rockchip_edp_phy_power_off(struct phy * phy)275 static int rockchip_edp_phy_power_off(struct phy *phy)
276 {
277 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
278
279 writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf), edpphy->regs + EDP_PHY_GRF_CON0);
280 usleep_range(0x64, 0x65);
281 writel(EDP_PHY_TX_MODE(0x3), edpphy->regs + EDP_PHY_GRF_CON5);
282 writel(EDP_PHY_PD_PLL(0x1), edpphy->regs + EDP_PHY_GRF_CON0);
283 writel(EDP_PHY_AUX_RCV_PD(0x1) | EDP_PHY_AUX_DRV_PD(0x1) | EDP_PHY_AUX_IDLE(0x1), edpphy->regs + EDP_PHY_GRF_CON10);
284
285 clk_disable_unprepare(edpphy->refclk);
286 clk_disable_unprepare(edpphy->pclk);
287
288 return 0;
289 }
290
291 static const struct phy_ops rockchip_edp_phy_ops = {
292 .power_on = rockchip_edp_phy_power_on,
293 .power_off = rockchip_edp_phy_power_off,
294 .configure = rockchip_edp_phy_configure,
295 .owner = THIS_MODULE,
296 };
297
rockchip_edp_phy_probe(struct platform_device * pdev)298 static int rockchip_edp_phy_probe(struct platform_device *pdev)
299 {
300 struct device *dev = &pdev->dev;
301 struct rockchip_edp_phy *edpphy;
302 struct phy *phy;
303 struct phy_provider *phy_provider;
304 struct resource *res;
305 int ret;
306
307 edpphy = devm_kzalloc(dev, sizeof(*edpphy), GFP_KERNEL);
308 if (!edpphy) {
309 return -ENOMEM;
310 }
311
312 edpphy->dev = dev;
313
314 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
315 edpphy->regs = devm_ioremap_resource(dev, res);
316 if (IS_ERR(edpphy->regs)) {
317 return PTR_ERR(edpphy->regs);
318 }
319
320 edpphy->refclk = devm_clk_get(dev, "refclk");
321 if (IS_ERR(edpphy->refclk)) {
322 ret = PTR_ERR(edpphy->refclk);
323 dev_err(dev, "failed to get refclk: %d\n", ret);
324 return ret;
325 }
326
327 edpphy->pclk = devm_clk_get(dev, "pclk");
328 if (IS_ERR(edpphy->pclk)) {
329 ret = PTR_ERR(edpphy->pclk);
330 dev_err(dev, "failed to get pclk: %d\n", ret);
331 return ret;
332 }
333
334 edpphy->apb_reset = devm_reset_control_get(dev, "apb");
335 if (IS_ERR(edpphy->apb_reset)) {
336 ret = PTR_ERR(edpphy->apb_reset);
337 dev_err(dev, "failed to get apb reset: %d\n", ret);
338 return ret;
339 }
340
341 phy = devm_phy_create(dev, NULL, &rockchip_edp_phy_ops);
342 if (IS_ERR(phy)) {
343 ret = PTR_ERR(phy);
344 dev_err(dev, "failed to create PHY: %d\n", ret);
345 return ret;
346 }
347
348 phy_set_drvdata(phy, edpphy);
349
350 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
351 if (IS_ERR(phy_provider)) {
352 dev_err(dev, "failed to register phy provider\n");
353 return PTR_ERR(phy_provider);
354 }
355
356 return 0;
357 }
358
359 static const struct of_device_id rockchip_edp_phy_of_match[] = {{
360 .compatible = "rockchip,rk3568-edp-phy",
361 }, {
362 }};
363 MODULE_DEVICE_TABLE(of, rockchip_edp_phy_of_match);
364
365 static struct platform_driver rockchip_edp_phy_driver = {
366 .driver =
367 {
368 .name = "rockchip-edpphy-naneng",
369 .of_match_table = of_match_ptr(rockchip_edp_phy_of_match),
370 },
371 .probe = rockchip_edp_phy_probe,
372 };
373 module_platform_driver(rockchip_edp_phy_driver);
374
375 MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
376 MODULE_DESCRIPTION("Rockchip Naneng eDP Transmitter PHY driver");
377 MODULE_LICENSE("GPL v2");
378