xref: /rk3399_rockchip-uboot/drivers/phy/phy-rockchip-naneng-edp.c (revision 5a94b26492fd3ad20c580976e18e101b67d14e6e)
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 <common.h>
9 #include <dm.h>
10 #include <generic-phy.h>
11 #include <reset.h>
12 #include <asm/io.h>
13 #include <linux/iopoll.h>
14 
15 #define HIWORD_UPDATE(x, h, l)		((((x) << (l)) & GENMASK((h), (l))) | \
16 					 (GENMASK((h), (l)) << 16))
17 
18 #define EDP_PHY_GRF_CON0		0x0000
19 #define EDP_PHY_TX_IDLE(x)		HIWORD_UPDATE(x, 11,  8)
20 #define EDP_PHY_TX_PD(x)		HIWORD_UPDATE(x,  7,  4)
21 #define EDP_PHY_IDDQ_EN(x)		HIWORD_UPDATE(x,  1,  1)
22 #define EDP_PHY_PD_PLL(x)		HIWORD_UPDATE(x,  0,  0)
23 #define EDP_PHY_GRF_CON1		0x0004
24 #define EDP_PHY_PLL_DIV(x)		HIWORD_UPDATE(x, 14,  0)
25 #define EDP_PHY_GRF_CON2		0x0008
26 #define EDP_PHY_TX_RTERM(x)		HIWORD_UPDATE(x, 10,  8)
27 #define EDP_PHY_RATE(x)			HIWORD_UPDATE(x,  5,  4)
28 #define EDP_PHY_REF_DIV(x)		HIWORD_UPDATE(x,  3,  0)
29 #define EDP_PHY_GRF_CON3		0x000c
30 #define EDP_PHY_TX_EMP(lane, x)		HIWORD_UPDATE(x, 4 * ((lane) + 1) - 1, \
31 						      4 * (lane))
32 #define EDP_PHY_GRF_CON4		0x0010
33 #define EDP_PHY_TX_AMP(lane, x)		HIWORD_UPDATE(x, 4 * ((lane) + 1) - 2, \
34 						      4 * (lane))
35 #define EDP_PHY_GRF_CON5		0x0014
36 #define EDP_PHY_TX_MODE(x)		HIWORD_UPDATE(x,  9,  8)
37 #define EDP_PHY_TX_AMP_SCALE(lane, x)	HIWORD_UPDATE(x, 2 * ((lane) + 1) - 1, \
38 						      2 * (lane))
39 #define EDP_PHY_GRF_CON6		0x0018
40 #define EDP_PHY_SSC_DEPTH(x)		HIWORD_UPDATE(x, 15, 12)
41 #define EDP_PHY_SSC_EN(x)		HIWORD_UPDATE(x, 11, 11)
42 #define EDP_PHY_SSC_CNT(x)		HIWORD_UPDATE(x,  9,  0)
43 #define EDP_PHY_GRF_CON7		0x001c
44 #define EDP_PHY_GRF_CON8		0x0020
45 #define EDP_PHY_PLL_CTL_H(x)		HIWORD_UPDATE(x, 15,  0)
46 #define EDP_PHY_GRF_CON9		0x0024
47 #define EDP_PHY_TX_CTL(x)		HIWORD_UPDATE(x, 15,  0)
48 #define EDP_PHY_GRF_CON10		0x0028
49 #define EDP_PHY_AUX_RCV_PD_SEL(x)	HIWORD_UPDATE(x,  5,  5)
50 #define EDP_PHY_AUX_DRV_PD_SEL(x)	HIWORD_UPDATE(x,  4,  4)
51 #define EDP_PHY_AUX_IDLE(x)		HIWORD_UPDATE(x,  2,  2)
52 #define EDP_PHY_AUX_RCV_PD(x)		HIWORD_UPDATE(x,  1,  1)
53 #define EDP_PHY_AUX_DRV_PD(x)		HIWORD_UPDATE(x,  0,  0)
54 #define EDP_PHY_GRF_CON11		0x002c
55 #define EDP_PHY_AUX_RCV_VCM(x)		HIWORD_UPDATE(x, 14, 12)
56 #define EDP_PHY_AUX_MODE(x)		HIWORD_UPDATE(x, 11, 10)
57 #define EDP_PHY_AUX_AMP_SCALE(x)	HIWORD_UPDATE(x,  9,  8)
58 #define EDP_PHY_AUX_AMP(x)		HIWORD_UPDATE(x,  6,  4)
59 #define EDP_PHY_AUX_RTERM(x)		HIWORD_UPDATE(x,  2,  0)
60 #define EDP_PHY_GRF_STATUS0		0x0030
61 #define PLL_RDY				BIT(0)
62 #define EDP_PHY_GRF_STATUS1		0x0034
63 
64 struct rockchip_edp_phy {
65 	void __iomem *regs;
66 	struct udevice *dev;
67 	struct reset_ctl apb_reset;
68 };
69 
70 static struct {
71 	int amp;
72 	int amp_scale;
73 	int emp;
74 } vp[4][4] = {
75 	{ {0x1, 0x1, 0x0}, {0x2, 0x1, 0x4}, {0x3, 0x1, 0x8}, {0x4, 0x1, 0xd} },
76 	{ {0x3, 0x1, 0x0}, {0x5, 0x1, 0x7}, {0x6, 0x1, 0x6}, { -1,  -1,  -1} },
77 	{ {0x5, 0x1, 0x0}, {0x7, 0x1, 0x4}, { -1,  -1,  -1}, { -1,  -1,  -1} },
78 	{ {0x7, 0x1, 0x0}, { -1,  -1,  -1}, { -1,  -1,  -1}, { -1,  -1,  -1} },
79 };
80 
81 static int rockchip_edp_phy_set_voltages(struct rockchip_edp_phy *edpphy,
82 					 struct phy_configure_opts_dp *dp)
83 {
84 	u8 lane;
85 	u32 val;
86 
87 	for (lane = 0; lane < dp->lanes; lane++) {
88 		val = vp[dp->voltage[lane]][dp->pre[lane]].amp;
89 		writel(EDP_PHY_TX_AMP(lane, val),
90 		       edpphy->regs + EDP_PHY_GRF_CON4);
91 
92 		val = vp[dp->voltage[lane]][dp->pre[lane]].amp_scale;
93 		writel(EDP_PHY_TX_AMP_SCALE(lane, val),
94 		       edpphy->regs + EDP_PHY_GRF_CON5);
95 
96 		val = vp[dp->voltage[lane]][dp->pre[lane]].emp;
97 		writel(EDP_PHY_TX_EMP(lane, val),
98 		       edpphy->regs + EDP_PHY_GRF_CON3);
99 	}
100 
101 	return 0;
102 }
103 
104 static int rockchip_edp_phy_set_rate(struct rockchip_edp_phy *edpphy,
105 				     struct phy_configure_opts_dp *dp)
106 {
107 	u32 value;
108 	int ret;
109 
110 	writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf),
111 	       edpphy->regs + EDP_PHY_GRF_CON0);
112 	udelay(100);
113 	writel(EDP_PHY_TX_MODE(0x3), edpphy->regs + EDP_PHY_GRF_CON5);
114 	writel(EDP_PHY_PD_PLL(0x1), edpphy->regs + EDP_PHY_GRF_CON0);
115 
116 	switch (dp->link_rate) {
117 	case 1620:
118 		writel(EDP_PHY_PLL_DIV(0x4380),
119 		       edpphy->regs + EDP_PHY_GRF_CON1);
120 		writel(EDP_PHY_TX_RTERM(0x1) | EDP_PHY_RATE(0x1) |
121 		       EDP_PHY_REF_DIV(0x0), edpphy->regs + EDP_PHY_GRF_CON2);
122 		writel(EDP_PHY_PLL_CTL_H(0x0800),
123 		       edpphy->regs + EDP_PHY_GRF_CON8);
124 		writel(EDP_PHY_TX_CTL(0x0000), edpphy->regs + EDP_PHY_GRF_CON9);
125 		break;
126 	case 2700:
127 		writel(EDP_PHY_PLL_DIV(0x3840),
128 		       edpphy->regs + EDP_PHY_GRF_CON1);
129 		writel(EDP_PHY_TX_RTERM(0x1) | EDP_PHY_RATE(0x0) |
130 		       EDP_PHY_REF_DIV(0x0), edpphy->regs + EDP_PHY_GRF_CON2);
131 		writel(EDP_PHY_PLL_CTL_H(0x0800),
132 		       edpphy->regs + EDP_PHY_GRF_CON8);
133 		writel(EDP_PHY_TX_CTL(0x0000), edpphy->regs + EDP_PHY_GRF_CON9);
134 		break;
135 	}
136 
137 	if (dp->ssc)
138 		writel(EDP_PHY_SSC_DEPTH(0x9) | EDP_PHY_SSC_EN(0x1) |
139 		       EDP_PHY_SSC_CNT(0x17d),
140 		       edpphy->regs + EDP_PHY_GRF_CON6);
141 	else
142 		writel(EDP_PHY_SSC_EN(0x0), edpphy->regs + EDP_PHY_GRF_CON6);
143 
144 	writel(EDP_PHY_PD_PLL(0x0), edpphy->regs + EDP_PHY_GRF_CON0);
145 	writel(EDP_PHY_TX_PD(~GENMASK(dp->lanes - 1, 0)),
146 	       edpphy->regs + EDP_PHY_GRF_CON0);
147 	ret = readl_poll_timeout(edpphy->regs + EDP_PHY_GRF_STATUS0,
148 				 value, value & PLL_RDY, 1000);
149 	if (ret) {
150 		dev_err(edpphy->dev, "pll is not ready: %d\n", ret);
151 		return ret;
152 	}
153 
154 	writel(EDP_PHY_TX_MODE(0x0), edpphy->regs + EDP_PHY_GRF_CON5);
155 	writel(EDP_PHY_TX_IDLE(~GENMASK(dp->lanes - 1, 0)),
156 	       edpphy->regs + EDP_PHY_GRF_CON0);
157 
158 	return 0;
159 }
160 
161 static int rockchip_edp_phy_verify_config(struct rockchip_edp_phy *edpphy,
162 					  struct phy_configure_opts_dp *dp)
163 {
164 	int i;
165 
166 	/* If changing link rate was required, verify it's supported. */
167 	if (dp->set_rate) {
168 		switch (dp->link_rate) {
169 		case 1620:
170 		case 2700:
171 			/* valid bit rate */
172 			break;
173 		default:
174 			return -EINVAL;
175 		}
176 	}
177 
178 	/* Verify lane count. */
179 	switch (dp->lanes) {
180 	case 1:
181 	case 2:
182 	case 4:
183 		/* valid lane count. */
184 		break;
185 	default:
186 		return -EINVAL;
187 	}
188 
189 	/*
190 	 * If changing voltages is required, check swing and pre-emphasis
191 	 * levels, per-lane.
192 	 */
193 	if (dp->set_voltages) {
194 		/* Lane count verified previously. */
195 		for (i = 0; i < dp->lanes; i++) {
196 			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
197 				return -EINVAL;
198 
199 			/*
200 			 * Sum of voltage swing and pre-emphasis levels cannot
201 			 * exceed 3.
202 			 */
203 			if (dp->voltage[i] + dp->pre[i] > 3)
204 				return -EINVAL;
205 		}
206 	}
207 
208 	return 0;
209 }
210 
211 static int rockchip_edp_phy_configure(struct phy *phy,
212 				      union phy_configure_opts *opts)
213 {
214 	struct rockchip_edp_phy *edpphy = dev_get_priv(phy->dev);
215 	int ret;
216 
217 	ret = rockchip_edp_phy_verify_config(edpphy, &opts->dp);
218 	if (ret) {
219 		dev_err(edpphy->dev, "invalid params for phy configure\n");
220 		return ret;
221 	}
222 
223 	if (opts->dp.set_rate) {
224 		ret = rockchip_edp_phy_set_rate(edpphy, &opts->dp);
225 		if (ret) {
226 			dev_err(edpphy->dev,
227 				"rockchip_edp_phy_set_rate failed\n");
228 			return ret;
229 		}
230 	}
231 
232 	if (opts->dp.set_voltages) {
233 		ret = rockchip_edp_phy_set_voltages(edpphy, &opts->dp);
234 		if (ret) {
235 			dev_err(edpphy->dev,
236 				"rockchip_edp_phy_set_voltages failed\n");
237 			return ret;
238 		}
239 	}
240 
241 	return 0;
242 }
243 
244 static int rockchip_edp_phy_power_on(struct phy *phy)
245 {
246 	struct rockchip_edp_phy *edpphy = dev_get_priv(phy->dev);
247 
248 	reset_assert(&edpphy->apb_reset);
249 	udelay(1);
250 	reset_deassert(&edpphy->apb_reset);
251 	udelay(1);
252 
253 	writel(EDP_PHY_AUX_RCV_PD(0x1) | EDP_PHY_AUX_DRV_PD(0x1) |
254 	       EDP_PHY_AUX_IDLE(0x1), edpphy->regs + EDP_PHY_GRF_CON10);
255 	writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf) | EDP_PHY_PD_PLL(0x1),
256 	       edpphy->regs + EDP_PHY_GRF_CON0);
257 	udelay(100);
258 
259 	writel(EDP_PHY_AUX_RCV_VCM(0x4) | EDP_PHY_AUX_MODE(0x1) |
260 	       EDP_PHY_AUX_AMP_SCALE(0x1) | EDP_PHY_AUX_AMP(0x3) |
261 	       EDP_PHY_AUX_RTERM(0x1), edpphy->regs + EDP_PHY_GRF_CON11);
262 
263 	writel(EDP_PHY_AUX_RCV_PD(0x0) | EDP_PHY_AUX_DRV_PD(0x0),
264 	       edpphy->regs + EDP_PHY_GRF_CON10);
265 	udelay(100);
266 
267 	writel(EDP_PHY_AUX_IDLE(0x0), edpphy->regs + EDP_PHY_GRF_CON10);
268 	mdelay(20);
269 
270 	return 0;
271 }
272 
273 static int rockchip_edp_phy_power_off(struct phy *phy)
274 {
275 	struct rockchip_edp_phy *edpphy = dev_get_priv(phy->dev);
276 
277 	writel(EDP_PHY_TX_IDLE(0xf) | EDP_PHY_TX_PD(0xf),
278 	       edpphy->regs + EDP_PHY_GRF_CON0);
279 	udelay(100);
280 	writel(EDP_PHY_TX_MODE(0x3), edpphy->regs + EDP_PHY_GRF_CON5);
281 	writel(EDP_PHY_PD_PLL(0x1), edpphy->regs + EDP_PHY_GRF_CON0);
282 	writel(EDP_PHY_AUX_RCV_PD(0x1) | EDP_PHY_AUX_DRV_PD(0x1) |
283 	       EDP_PHY_AUX_IDLE(0x1), edpphy->regs + EDP_PHY_GRF_CON10);
284 
285 	return 0;
286 }
287 
288 static struct phy_ops rockchip_edp_phy_ops = {
289 	.power_on = rockchip_edp_phy_power_on,
290 	.power_off = rockchip_edp_phy_power_off,
291 	.configure = rockchip_edp_phy_configure,
292 };
293 
294 static int rockchip_edp_phy_probe(struct udevice *dev)
295 {
296 	struct rockchip_edp_phy *edpphy = dev_get_priv(dev);
297 	int ret;
298 
299 	edpphy->regs = dev_read_addr_ptr(dev);
300 	if (!edpphy->regs)
301 		return -ENOENT;
302 
303 	edpphy->dev = dev;
304 
305 	ret = reset_get_by_name(dev, "apb", &edpphy->apb_reset);
306 	if (ret < 0) {
307 		dev_err(dev, "failed to get apb reset: %d\n", ret);
308 		return ret;
309 	}
310 
311 	return 0;
312 }
313 
314 static const struct udevice_id rockchip_edp_phy_ids[] = {
315 	{ .compatible = "rockchip,rk3568-edp-phy", },
316 	{}
317 };
318 
319 U_BOOT_DRIVER(rockchip_edp_phy) = {
320 	.name		= "rockchip_edp_phy",
321 	.id		= UCLASS_PHY,
322 	.ops		= &rockchip_edp_phy_ops,
323 	.of_match	= rockchip_edp_phy_ids,
324 	.probe		= rockchip_edp_phy_probe,
325 	.priv_auto_alloc_size = sizeof(struct rockchip_edp_phy),
326 };
327