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/bitfield.h>
9 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/delay.h>
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/regmap.h>
19 #include <linux/mfd/syscon.h>
20 #include <linux/phy/phy.h>
21
22 #define EDP_PHY_GRF_CON0 0x0000
23 #define EDP_PHY_TX_IDLE GENMASK(11, 8)
24 #define EDP_PHY_TX_PD GENMASK(7, 4)
25 #define EDP_PHY_IDDQ_EN BIT(1)
26 #define EDP_PHY_PD_PLL BIT(0)
27 #define EDP_PHY_GRF_CON1 0x0004
28 #define EDP_PHY_PLL_DIV GENMASK(14, 0)
29 #define EDP_PHY_GRF_CON2 0x0008
30 #define EDP_PHY_TX_RTERM GENMASK(10, 8)
31 #define EDP_PHY_RATE GENMASK(5, 4)
32 #define EDP_PHY_REF_DIV GENMASK(3, 0)
33 #define EDP_PHY_GRF_CON3 0x000c
34 #define EDP_PHY_TX3_EMP GENMASK(15, 12)
35 #define EDP_PHY_TX2_EMP GENMASK(11, 8)
36 #define EDP_PHY_TX1_EMP GENMASK(7, 4)
37 #define EDP_PHY_TX0_EMP GENMASK(3, 0)
38 #define EDP_PHY_GRF_CON4 0x0010
39 #define EDP_PHY_TX3_AMP GENMASK(14, 12)
40 #define EDP_PHY_TX2_AMP GENMASK(10, 8)
41 #define EDP_PHY_TX1_AMP GENMASK(6, 4)
42 #define EDP_PHY_TX0_AMP GENMASK(2, 0)
43 #define EDP_PHY_GRF_CON5 0x0014
44 #define EDP_PHY_TX_MODE GENMASK(9, 8)
45 #define EDP_PHY_TX3_AMP_SCALE GENMASK(7, 6)
46 #define EDP_PHY_TX2_AMP_SCALE GENMASK(5, 4)
47 #define EDP_PHY_TX1_AMP_SCALE GENMASK(3, 2)
48 #define EDP_PHY_TX0_AMP_SCALE GENMASK(1, 0)
49 #define EDP_PHY_GRF_CON6 0x0018
50 #define EDP_PHY_SSC_DEPTH GENMASK(15, 12)
51 #define EDP_PHY_SSC_EN BIT(11)
52 #define EDP_PHY_SSC_CNT GENMASK(9, 0)
53 #define EDP_PHY_GRF_CON7 0x001c
54 #define EDP_PHY_GRF_CON8 0x0020
55 #define EDP_PHY_PLL_CTL_H GENMASK(15, 0)
56 #define EDP_PHY_GRF_CON9 0x0024
57 #define EDP_PHY_TX_CTL GENMASK(15, 0)
58 #define EDP_PHY_GRF_CON10 0x0028
59 #define EDP_PHY_AUX_RCV_PD_SEL BIT(5)
60 #define EDP_PHY_AUX_DRV_PD_SEL BIT(4)
61 #define EDP_PHY_AUX_IDLE BIT(2)
62 #define EDP_PHY_AUX_RCV_PD BIT(1)
63 #define EDP_PHY_AUX_DRV_PD BIT(0)
64 #define EDP_PHY_GRF_CON11 0x002c
65 #define EDP_PHY_AUX_RCV_VCM GENMASK(14, 12)
66 #define EDP_PHY_AUX_MODE GENMASK(11, 10)
67 #define EDP_PHY_AUX_AMP_SCALE GENMASK(9, 8)
68 #define EDP_PHY_AUX_AMP GENMASK(6, 4)
69 #define EDP_PHY_AUX_RTERM GENMASK(2, 0)
70 #define EDP_PHY_GRF_STATUS0 0x0030
71 #define PLL_RDY BIT(0)
72 #define EDP_PHY_GRF_STATUS1 0x0034
73
74 struct rockchip_edp_phy {
75 struct regmap *grf;
76 struct device *dev;
77 struct clk *refclk;
78 };
79
rockchip_grf_write(struct regmap * grf,unsigned int reg,unsigned int mask,unsigned int val)80 static inline int rockchip_grf_write(struct regmap *grf, unsigned int reg,
81 unsigned int mask, unsigned int val)
82 {
83 return regmap_write(grf, reg, (mask << 16) | (val & mask));
84 }
85
86 static struct {
87 int amp;
88 int amp_scale;
89 int emp;
90 } vp[4][4] = {
91 { {0x1, 0x1, 0x0}, {0x2, 0x1, 0x4}, {0x3, 0x1, 0x8}, {0x4, 0x1, 0xd} },
92 { {0x3, 0x1, 0x0}, {0x5, 0x1, 0x7}, {0x6, 0x1, 0x6}, { -1, -1, -1} },
93 { {0x5, 0x1, 0x0}, {0x7, 0x1, 0x4}, { -1, -1, -1}, { -1, -1, -1} },
94 { {0x7, 0x1, 0x0}, { -1, -1, -1}, { -1, -1, -1}, { -1, -1, -1} },
95 };
96
rockchip_edp_phy_set_voltage(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp,u8 lane)97 static void rockchip_edp_phy_set_voltage(struct rockchip_edp_phy *edpphy,
98 struct phy_configure_opts_dp *dp,
99 u8 lane)
100 {
101 u32 amp, amp_scale, emp;
102
103 amp = vp[dp->voltage[lane]][dp->pre[lane]].amp;
104 amp_scale = vp[dp->voltage[lane]][dp->pre[lane]].amp_scale;
105 emp = vp[dp->voltage[lane]][dp->pre[lane]].emp;
106
107 switch (lane) {
108 case 0:
109 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON3,
110 EDP_PHY_TX0_EMP,
111 FIELD_PREP(EDP_PHY_TX0_EMP, emp));
112 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON4,
113 EDP_PHY_TX0_AMP,
114 FIELD_PREP(EDP_PHY_TX0_AMP, amp));
115 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5,
116 EDP_PHY_TX0_AMP_SCALE,
117 FIELD_PREP(EDP_PHY_TX0_AMP_SCALE, amp_scale));
118 break;
119 case 1:
120 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON3,
121 EDP_PHY_TX1_EMP,
122 FIELD_PREP(EDP_PHY_TX1_EMP, emp));
123 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON4,
124 EDP_PHY_TX1_AMP,
125 FIELD_PREP(EDP_PHY_TX1_AMP, amp));
126 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5,
127 EDP_PHY_TX1_AMP_SCALE,
128 FIELD_PREP(EDP_PHY_TX1_AMP_SCALE, amp_scale));
129 break;
130 case 2:
131 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON3,
132 EDP_PHY_TX2_EMP,
133 FIELD_PREP(EDP_PHY_TX2_EMP, emp));
134 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON4,
135 EDP_PHY_TX2_AMP,
136 FIELD_PREP(EDP_PHY_TX2_AMP, amp));
137 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5,
138 EDP_PHY_TX2_AMP_SCALE,
139 FIELD_PREP(EDP_PHY_TX2_AMP_SCALE, amp_scale));
140 break;
141 case 3:
142 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON3,
143 EDP_PHY_TX3_EMP,
144 FIELD_PREP(EDP_PHY_TX3_EMP, emp));
145 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON4,
146 EDP_PHY_TX3_AMP,
147 FIELD_PREP(EDP_PHY_TX3_AMP, amp));
148 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5,
149 EDP_PHY_TX3_AMP_SCALE,
150 FIELD_PREP(EDP_PHY_TX3_AMP_SCALE, amp_scale));
151 break;
152 }
153 }
154
rockchip_edp_phy_set_voltages(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)155 static int rockchip_edp_phy_set_voltages(struct rockchip_edp_phy *edpphy,
156 struct phy_configure_opts_dp *dp)
157 {
158 u8 lane;
159
160 for (lane = 0; lane < dp->lanes; lane++)
161 rockchip_edp_phy_set_voltage(edpphy, dp, lane);
162
163 return 0;
164 }
165
rockchip_edp_phy_set_rate(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)166 static int rockchip_edp_phy_set_rate(struct rockchip_edp_phy *edpphy,
167 struct phy_configure_opts_dp *dp)
168 {
169 u32 value;
170 int ret;
171
172 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0,
173 EDP_PHY_TX_IDLE | EDP_PHY_TX_PD,
174 FIELD_PREP(EDP_PHY_TX_IDLE, 0xf) |
175 FIELD_PREP(EDP_PHY_TX_PD, 0xf));
176 usleep_range(100, 101);
177 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5, EDP_PHY_TX_MODE,
178 FIELD_PREP(EDP_PHY_TX_MODE, 0x3));
179 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0, EDP_PHY_PD_PLL,
180 FIELD_PREP(EDP_PHY_PD_PLL, 0x1));
181
182 switch (dp->link_rate) {
183 case 1620:
184 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON1,
185 EDP_PHY_PLL_DIV,
186 FIELD_PREP(EDP_PHY_PLL_DIV, 0x4380));
187 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON2,
188 EDP_PHY_TX_RTERM | EDP_PHY_RATE | EDP_PHY_REF_DIV,
189 FIELD_PREP(EDP_PHY_TX_RTERM, 0x1) |
190 FIELD_PREP(EDP_PHY_RATE, 0x1) |
191 FIELD_PREP(EDP_PHY_REF_DIV, 0x0));
192 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON8,
193 EDP_PHY_PLL_CTL_H,
194 FIELD_PREP(EDP_PHY_PLL_CTL_H, 0x0800));
195 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON9,
196 EDP_PHY_TX_CTL,
197 FIELD_PREP(EDP_PHY_TX_CTL, 0x0000));
198 break;
199 case 2700:
200 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON1,
201 EDP_PHY_PLL_DIV,
202 FIELD_PREP(EDP_PHY_PLL_DIV, 0x3840));
203 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON2,
204 EDP_PHY_TX_RTERM | EDP_PHY_RATE | EDP_PHY_REF_DIV,
205 FIELD_PREP(EDP_PHY_TX_RTERM, 0x1) |
206 FIELD_PREP(EDP_PHY_RATE, 0x0) |
207 FIELD_PREP(EDP_PHY_REF_DIV, 0x0));
208 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON8,
209 EDP_PHY_PLL_CTL_H,
210 FIELD_PREP(EDP_PHY_PLL_CTL_H, 0x0800));
211 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON9,
212 EDP_PHY_TX_CTL,
213 FIELD_PREP(EDP_PHY_TX_CTL, 0x0000));
214 break;
215 }
216
217 if (dp->ssc)
218 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON6,
219 EDP_PHY_SSC_DEPTH | EDP_PHY_SSC_EN | EDP_PHY_SSC_CNT,
220 FIELD_PREP(EDP_PHY_SSC_DEPTH, 0x9) |
221 FIELD_PREP(EDP_PHY_SSC_EN, 0x1) |
222 FIELD_PREP(EDP_PHY_SSC_CNT, 0x17d));
223 else
224 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON6,
225 EDP_PHY_SSC_EN,
226 FIELD_PREP(EDP_PHY_SSC_EN, 0x0));
227
228 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0, EDP_PHY_PD_PLL,
229 FIELD_PREP(EDP_PHY_PD_PLL, 0));
230 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0, EDP_PHY_TX_PD,
231 FIELD_PREP(EDP_PHY_TX_PD, ~GENMASK(dp->lanes - 1, 0)));
232 ret = regmap_read_poll_timeout(edpphy->grf, EDP_PHY_GRF_STATUS0,
233 value, value & PLL_RDY, 100, 1000);
234 if (ret) {
235 dev_err(edpphy->dev, "pll is not ready: %d\n", ret);
236 return ret;
237 }
238
239 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5, EDP_PHY_TX_MODE,
240 FIELD_PREP(EDP_PHY_TX_MODE, 0x0));
241 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0, EDP_PHY_TX_IDLE,
242 FIELD_PREP(EDP_PHY_TX_IDLE, ~GENMASK(dp->lanes - 1, 0)));
243
244 return 0;
245 }
246
rockchip_edp_phy_verify_config(struct rockchip_edp_phy * edpphy,struct phy_configure_opts_dp * dp)247 static int rockchip_edp_phy_verify_config(struct rockchip_edp_phy *edpphy,
248 struct phy_configure_opts_dp *dp)
249 {
250 int i;
251
252 /* If changing link rate was required, verify it's supported. */
253 if (dp->set_rate) {
254 switch (dp->link_rate) {
255 case 1620:
256 case 2700:
257 /* valid bit rate */
258 break;
259 default:
260 return -EINVAL;
261 }
262 }
263
264 /* Verify lane count. */
265 switch (dp->lanes) {
266 case 1:
267 case 2:
268 case 4:
269 /* valid lane count. */
270 break;
271 default:
272 return -EINVAL;
273 }
274
275 /*
276 * If changing voltages is required, check swing and pre-emphasis
277 * levels, per-lane.
278 */
279 if (dp->set_voltages) {
280 /* Lane count verified previously. */
281 for (i = 0; i < dp->lanes; i++) {
282 if (dp->voltage[i] > 3 || dp->pre[i] > 3)
283 return -EINVAL;
284
285 /*
286 * Sum of voltage swing and pre-emphasis levels cannot
287 * exceed 3.
288 */
289 if (dp->voltage[i] + dp->pre[i] > 3)
290 return -EINVAL;
291 }
292 }
293
294 return 0;
295 }
296
rockchip_edp_phy_configure(struct phy * phy,union phy_configure_opts * opts)297 static int rockchip_edp_phy_configure(struct phy *phy,
298 union phy_configure_opts *opts)
299 {
300 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
301 int ret;
302
303 ret = rockchip_edp_phy_verify_config(edpphy, &opts->dp);
304 if (ret) {
305 dev_err(edpphy->dev, "invalid params for phy configure\n");
306 return ret;
307 }
308
309 if (opts->dp.set_rate) {
310 ret = rockchip_edp_phy_set_rate(edpphy, &opts->dp);
311 if (ret) {
312 dev_err(edpphy->dev,
313 "rockchip_edp_phy_set_rate failed\n");
314 return ret;
315 }
316 }
317
318 if (opts->dp.set_voltages) {
319 ret = rockchip_edp_phy_set_voltages(edpphy, &opts->dp);
320 if (ret) {
321 dev_err(edpphy->dev,
322 "rockchip_edp_phy_set_voltages failed\n");
323 return ret;
324 }
325 }
326
327 return 0;
328 }
329
rockchip_edp_phy_enabled(struct rockchip_edp_phy * edpphy)330 static bool rockchip_edp_phy_enabled(struct rockchip_edp_phy *edpphy)
331 {
332 u32 val;
333
334 regmap_read(edpphy->grf, EDP_PHY_GRF_STATUS0, &val);
335
336 return FIELD_GET(PLL_RDY, val);
337 }
338
rockchip_edp_phy_power_on(struct phy * phy)339 static int rockchip_edp_phy_power_on(struct phy *phy)
340 {
341 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
342
343 clk_prepare_enable(edpphy->refclk);
344
345 if (rockchip_edp_phy_enabled(edpphy))
346 return 0;
347
348 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON10,
349 EDP_PHY_AUX_RCV_PD | EDP_PHY_AUX_DRV_PD | EDP_PHY_AUX_IDLE,
350 FIELD_PREP(EDP_PHY_AUX_RCV_PD, 0x1) |
351 FIELD_PREP(EDP_PHY_AUX_DRV_PD, 0x1) |
352 FIELD_PREP(EDP_PHY_AUX_IDLE, 0x1));
353 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0,
354 EDP_PHY_TX_IDLE | EDP_PHY_TX_PD | EDP_PHY_PD_PLL,
355 FIELD_PREP(EDP_PHY_TX_IDLE, 0xf) |
356 FIELD_PREP(EDP_PHY_TX_PD, 0xf) |
357 FIELD_PREP(EDP_PHY_PD_PLL, 0x1));
358 usleep_range(100, 101);
359
360 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON11,
361 EDP_PHY_AUX_RCV_VCM | EDP_PHY_AUX_MODE |
362 EDP_PHY_AUX_AMP_SCALE | EDP_PHY_AUX_AMP |
363 EDP_PHY_AUX_RTERM,
364 FIELD_PREP(EDP_PHY_AUX_RCV_VCM, 0x4) |
365 FIELD_PREP(EDP_PHY_AUX_MODE, 0x1) |
366 FIELD_PREP(EDP_PHY_AUX_AMP_SCALE, 0x1) |
367 FIELD_PREP(EDP_PHY_AUX_AMP, 0x3) |
368 FIELD_PREP(EDP_PHY_AUX_RTERM, 0x1));
369
370 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON10,
371 EDP_PHY_AUX_RCV_PD | EDP_PHY_AUX_DRV_PD,
372 FIELD_PREP(EDP_PHY_AUX_RCV_PD, 0x0) |
373 FIELD_PREP(EDP_PHY_AUX_DRV_PD, 0x0));
374 usleep_range(100, 101);
375
376 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON10,
377 EDP_PHY_AUX_IDLE,
378 FIELD_PREP(EDP_PHY_AUX_IDLE, 0x0));
379 usleep_range(10000, 11000);
380
381 return 0;
382 }
383
rockchip_edp_phy_power_off(struct phy * phy)384 static int rockchip_edp_phy_power_off(struct phy *phy)
385 {
386 struct rockchip_edp_phy *edpphy = phy_get_drvdata(phy);
387
388 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0,
389 EDP_PHY_TX_IDLE | EDP_PHY_TX_PD,
390 FIELD_PREP(EDP_PHY_TX_IDLE, 0xf) |
391 FIELD_PREP(EDP_PHY_TX_PD, 0xf));
392 usleep_range(100, 101);
393 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON5, EDP_PHY_TX_MODE,
394 FIELD_PREP(EDP_PHY_TX_MODE, 0x3));
395 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON0, EDP_PHY_PD_PLL,
396 FIELD_PREP(EDP_PHY_PD_PLL, 0x1));
397 rockchip_grf_write(edpphy->grf, EDP_PHY_GRF_CON10,
398 EDP_PHY_AUX_RCV_PD | EDP_PHY_AUX_DRV_PD | EDP_PHY_AUX_IDLE,
399 FIELD_PREP(EDP_PHY_AUX_RCV_PD, 0x1) |
400 FIELD_PREP(EDP_PHY_AUX_DRV_PD, 0x1) |
401 FIELD_PREP(EDP_PHY_AUX_IDLE, 0x1));
402
403 clk_disable_unprepare(edpphy->refclk);
404
405 return 0;
406 }
407
408 static const struct phy_ops rockchip_edp_phy_ops = {
409 .power_on = rockchip_edp_phy_power_on,
410 .power_off = rockchip_edp_phy_power_off,
411 .configure = rockchip_edp_phy_configure,
412 .owner = THIS_MODULE,
413 };
414
rockchip_edp_phy_probe(struct platform_device * pdev)415 static int rockchip_edp_phy_probe(struct platform_device *pdev)
416 {
417 struct device *dev = &pdev->dev;
418 struct rockchip_edp_phy *edpphy;
419 struct phy *phy;
420 struct phy_provider *phy_provider;
421 int ret;
422
423 edpphy = devm_kzalloc(dev, sizeof(*edpphy), GFP_KERNEL);
424 if (!edpphy)
425 return -ENOMEM;
426
427 edpphy->dev = dev;
428
429 edpphy->grf = syscon_node_to_regmap(dev->parent->of_node);
430 if (IS_ERR(edpphy->grf)) {
431 ret = PTR_ERR(edpphy->grf);
432 dev_err(dev, "failed to get grf: %d\n", ret);
433 return ret;
434 }
435
436 edpphy->refclk = devm_clk_get(dev, "refclk");
437 if (IS_ERR(edpphy->refclk)) {
438 ret = PTR_ERR(edpphy->refclk);
439 dev_err(dev, "failed to get refclk: %d\n", ret);
440 return ret;
441 }
442
443 phy = devm_phy_create(dev, NULL, &rockchip_edp_phy_ops);
444 if (IS_ERR(phy)) {
445 ret = PTR_ERR(phy);
446 dev_err(dev, "failed to create PHY: %d\n", ret);
447 return ret;
448 }
449
450 phy_set_drvdata(phy, edpphy);
451
452 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
453 if (IS_ERR(phy_provider)) {
454 dev_err(dev, "failed to register phy provider\n");
455 return PTR_ERR(phy_provider);
456 }
457
458 return 0;
459 }
460
461 static const struct of_device_id rockchip_edp_phy_of_match[] = {
462 { .compatible = "rockchip,rk3568-edp-phy", },
463 {}
464 };
465 MODULE_DEVICE_TABLE(of, rockchip_edp_phy_of_match);
466
467 static struct platform_driver rockchip_edp_phy_driver = {
468 .driver = {
469 .name = "rockchip-edpphy-naneng",
470 .of_match_table = of_match_ptr(rockchip_edp_phy_of_match),
471 },
472 .probe = rockchip_edp_phy_probe,
473 };
474 module_platform_driver(rockchip_edp_phy_driver);
475
476 MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
477 MODULE_DESCRIPTION("Rockchip Naneng eDP Transmitter PHY driver");
478 MODULE_LICENSE("GPL v2");
479