• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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