1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Support for Microchip MCP4728
4 *
5 * Copyright (C) 2023 Andrea Collamati <andrea.collamati@gmail.com>
6 *
7 * Based on mcp4725 by Peter Meerwald <pmeerw@pmeerw.net>
8 *
9 * Driver for the Microchip I2C 12-bit digital-to-analog quad channels
10 * converter (DAC).
11 *
12 * (7-bit I2C slave address 0x60, the three LSBs can be configured in
13 * hardware)
14 */
15
16 #include <linux/bitfield.h>
17 #include <linux/delay.h>
18 #include <linux/err.h>
19 #include <linux/i2c.h>
20 #include <linux/iio/iio.h>
21 #include <linux/iio/sysfs.h>
22 #include <linux/module.h>
23 #include <linux/mod_devicetable.h>
24 #include <linux/property.h>
25 #include <linux/regulator/consumer.h>
26
27 #define MCP4728_RESOLUTION 12
28 #define MCP4728_N_CHANNELS 4
29
30 #define MCP4728_CMD_MASK GENMASK(7, 3)
31 #define MCP4728_CHSEL_MASK GENMASK(2, 1)
32 #define MCP4728_UDAC_MASK BIT(0)
33
34 #define MCP4728_VREF_MASK BIT(7)
35 #define MCP4728_PDMODE_MASK GENMASK(6, 5)
36 #define MCP4728_GAIN_MASK BIT(4)
37
38 #define MCP4728_DAC_H_MASK GENMASK(3, 0)
39 #define MCP4728_DAC_L_MASK GENMASK(7, 0)
40
41 #define MCP4728_RDY_MASK BIT(7)
42
43 #define MCP4728_MW_CMD 0x08 /* Multiwrite Command */
44 #define MCP4728_SW_CMD 0x0A /* Sequential Write Command with EEPROM */
45
46 #define MCP4728_READ_RESPONSE_LEN (MCP4728_N_CHANNELS * 3 * 2)
47 #define MCP4728_WRITE_EEPROM_LEN (1 + MCP4728_N_CHANNELS * 2)
48
49 enum vref_mode {
50 MCP4728_VREF_EXTERNAL_VDD = 0,
51 MCP4728_VREF_INTERNAL_2048mV = 1,
52 };
53
54 enum gain_mode {
55 MCP4728_GAIN_X1 = 0,
56 MCP4728_GAIN_X2 = 1,
57 };
58
59 enum iio_powerdown_mode {
60 MCP4728_IIO_1K,
61 MCP4728_IIO_100K,
62 MCP4728_IIO_500K,
63 };
64
65 struct mcp4728_channel_data {
66 enum vref_mode ref_mode;
67 enum iio_powerdown_mode pd_mode;
68 enum gain_mode g_mode;
69 u16 dac_value;
70 };
71
72 /* MCP4728 Full Scale Ranges
73 * the device available ranges are
74 * - VREF = VDD FSR = from 0.0V to VDD
75 * - VREF = Internal Gain = 1 FSR = from 0.0V to VREF
76 * - VREF = Internal Gain = 2 FSR = from 0.0V to 2*VREF
77 */
78 enum mcp4728_scale {
79 MCP4728_SCALE_VDD,
80 MCP4728_SCALE_VINT_NO_GAIN,
81 MCP4728_SCALE_VINT_GAIN_X2,
82 MCP4728_N_SCALES
83 };
84
85 struct mcp4728_data {
86 struct i2c_client *client;
87 struct regulator *vdd_reg;
88 bool powerdown;
89 int scales_avail[MCP4728_N_SCALES * 2];
90 struct mcp4728_channel_data chdata[MCP4728_N_CHANNELS];
91 };
92
93 #define MCP4728_CHAN(chan) { \
94 .type = IIO_VOLTAGE, \
95 .output = 1, \
96 .indexed = 1, \
97 .channel = chan, \
98 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
99 BIT(IIO_CHAN_INFO_SCALE), \
100 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
101 .ext_info = mcp4728_ext_info, \
102 }
103
104 static int mcp4728_suspend(struct device *dev);
105 static int mcp4728_resume(struct device *dev);
106
mcp4728_store_eeprom(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)107 static ssize_t mcp4728_store_eeprom(struct device *dev,
108 struct device_attribute *attr,
109 const char *buf, size_t len)
110 {
111 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
112 struct mcp4728_data *data = iio_priv(indio_dev);
113 u8 outbuf[MCP4728_WRITE_EEPROM_LEN];
114 int tries = 20;
115 u8 inbuf[3];
116 bool state;
117 int ret;
118 unsigned int i;
119
120 ret = kstrtobool(buf, &state);
121 if (ret < 0)
122 return ret;
123
124 if (!state)
125 return 0;
126
127 outbuf[0] = FIELD_PREP(MCP4728_CMD_MASK, MCP4728_SW_CMD);
128
129 for (i = 0; i < MCP4728_N_CHANNELS; i++) {
130 struct mcp4728_channel_data *ch = &data->chdata[i];
131 int offset = 1 + i * 2;
132
133 outbuf[offset] = FIELD_PREP(MCP4728_VREF_MASK, ch->ref_mode);
134
135 if (data->powerdown) {
136 u8 mcp4728_pd_mode = ch->pd_mode + 1;
137
138 outbuf[offset] |= FIELD_PREP(MCP4728_PDMODE_MASK,
139 mcp4728_pd_mode);
140 }
141
142 outbuf[offset] |= FIELD_PREP(MCP4728_GAIN_MASK, ch->g_mode);
143 outbuf[offset] |=
144 FIELD_PREP(MCP4728_DAC_H_MASK, ch->dac_value >> 8);
145 outbuf[offset + 1] =
146 FIELD_PREP(MCP4728_DAC_L_MASK, ch->dac_value);
147 }
148
149 ret = i2c_master_send(data->client, outbuf, MCP4728_WRITE_EEPROM_LEN);
150 if (ret < 0)
151 return ret;
152 else if (ret != MCP4728_WRITE_EEPROM_LEN)
153 return -EIO;
154
155 /* wait RDY signal for write complete, takes up to 50ms */
156 while (tries--) {
157 msleep(20);
158 ret = i2c_master_recv(data->client, inbuf, 3);
159 if (ret < 0)
160 return ret;
161 else if (ret != 3)
162 return -EIO;
163
164 if (FIELD_GET(MCP4728_RDY_MASK, inbuf[0]))
165 break;
166 }
167
168 if (tries < 0) {
169 dev_err(&data->client->dev, "%s failed, incomplete\n",
170 __func__);
171 return -EIO;
172 }
173 return len;
174 }
175
176 static IIO_DEVICE_ATTR(store_eeprom, 0200, NULL, mcp4728_store_eeprom, 0);
177
178 static struct attribute *mcp4728_attributes[] = {
179 &iio_dev_attr_store_eeprom.dev_attr.attr,
180 NULL,
181 };
182
183 static const struct attribute_group mcp4728_attribute_group = {
184 .attrs = mcp4728_attributes,
185 };
186
mcp4728_program_channel_cfg(int channel,struct iio_dev * indio_dev)187 static int mcp4728_program_channel_cfg(int channel, struct iio_dev *indio_dev)
188 {
189 struct mcp4728_data *data = iio_priv(indio_dev);
190 struct mcp4728_channel_data *ch = &data->chdata[channel];
191 u8 outbuf[3];
192 int ret;
193
194 outbuf[0] = FIELD_PREP(MCP4728_CMD_MASK, MCP4728_MW_CMD);
195 outbuf[0] |= FIELD_PREP(MCP4728_CHSEL_MASK, channel);
196 outbuf[0] |= FIELD_PREP(MCP4728_UDAC_MASK, 0);
197
198 outbuf[1] = FIELD_PREP(MCP4728_VREF_MASK, ch->ref_mode);
199
200 if (data->powerdown)
201 outbuf[1] |= FIELD_PREP(MCP4728_PDMODE_MASK, ch->pd_mode + 1);
202
203 outbuf[1] |= FIELD_PREP(MCP4728_GAIN_MASK, ch->g_mode);
204 outbuf[1] |= FIELD_PREP(MCP4728_DAC_H_MASK, ch->dac_value >> 8);
205 outbuf[2] = FIELD_PREP(MCP4728_DAC_L_MASK, ch->dac_value);
206
207 ret = i2c_master_send(data->client, outbuf, 3);
208 if (ret < 0)
209 return ret;
210 else if (ret != 3)
211 return -EIO;
212
213 return 0;
214 }
215
216 static const char *const mcp4728_powerdown_modes[] = { "1kohm_to_gnd",
217 "100kohm_to_gnd",
218 "500kohm_to_gnd" };
219
mcp4728_get_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan)220 static int mcp4728_get_powerdown_mode(struct iio_dev *indio_dev,
221 const struct iio_chan_spec *chan)
222 {
223 struct mcp4728_data *data = iio_priv(indio_dev);
224
225 return data->chdata[chan->channel].pd_mode;
226 }
227
mcp4728_set_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int mode)228 static int mcp4728_set_powerdown_mode(struct iio_dev *indio_dev,
229 const struct iio_chan_spec *chan,
230 unsigned int mode)
231 {
232 struct mcp4728_data *data = iio_priv(indio_dev);
233
234 data->chdata[chan->channel].pd_mode = mode;
235
236 return 0;
237 }
238
mcp4728_read_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)239 static ssize_t mcp4728_read_powerdown(struct iio_dev *indio_dev,
240 uintptr_t private,
241 const struct iio_chan_spec *chan,
242 char *buf)
243 {
244 struct mcp4728_data *data = iio_priv(indio_dev);
245
246 return sysfs_emit(buf, "%d\n", data->powerdown);
247 }
248
mcp4728_write_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)249 static ssize_t mcp4728_write_powerdown(struct iio_dev *indio_dev,
250 uintptr_t private,
251 const struct iio_chan_spec *chan,
252 const char *buf, size_t len)
253 {
254 struct mcp4728_data *data = iio_priv(indio_dev);
255 bool state;
256 int ret;
257
258 ret = kstrtobool(buf, &state);
259 if (ret)
260 return ret;
261
262 if (state)
263 ret = mcp4728_suspend(&data->client->dev);
264 else
265 ret = mcp4728_resume(&data->client->dev);
266
267 if (ret < 0)
268 return ret;
269
270 return len;
271 }
272
273 static const struct iio_enum mcp4728_powerdown_mode_enum = {
274 .items = mcp4728_powerdown_modes,
275 .num_items = ARRAY_SIZE(mcp4728_powerdown_modes),
276 .get = mcp4728_get_powerdown_mode,
277 .set = mcp4728_set_powerdown_mode,
278 };
279
280 static const struct iio_chan_spec_ext_info mcp4728_ext_info[] = {
281 {
282 .name = "powerdown",
283 .read = mcp4728_read_powerdown,
284 .write = mcp4728_write_powerdown,
285 .shared = IIO_SEPARATE,
286 },
287 IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4728_powerdown_mode_enum),
288 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
289 &mcp4728_powerdown_mode_enum),
290 {},
291 };
292
293 static const struct iio_chan_spec mcp4728_channels[MCP4728_N_CHANNELS] = {
294 MCP4728_CHAN(0),
295 MCP4728_CHAN(1),
296 MCP4728_CHAN(2),
297 MCP4728_CHAN(3),
298 };
299
mcp4728_get_scale_avail(enum mcp4728_scale scale,struct mcp4728_data * data,int * val,int * val2)300 static void mcp4728_get_scale_avail(enum mcp4728_scale scale,
301 struct mcp4728_data *data, int *val,
302 int *val2)
303 {
304 *val = data->scales_avail[scale * 2];
305 *val2 = data->scales_avail[scale * 2 + 1];
306 }
307
mcp4728_get_scale(int channel,struct mcp4728_data * data,int * val,int * val2)308 static void mcp4728_get_scale(int channel, struct mcp4728_data *data, int *val,
309 int *val2)
310 {
311 int ref_mode = data->chdata[channel].ref_mode;
312 int g_mode = data->chdata[channel].g_mode;
313
314 if (ref_mode == MCP4728_VREF_EXTERNAL_VDD) {
315 mcp4728_get_scale_avail(MCP4728_SCALE_VDD, data, val, val2);
316 } else {
317 if (g_mode == MCP4728_GAIN_X1) {
318 mcp4728_get_scale_avail(MCP4728_SCALE_VINT_NO_GAIN,
319 data, val, val2);
320 } else {
321 mcp4728_get_scale_avail(MCP4728_SCALE_VINT_GAIN_X2,
322 data, val, val2);
323 }
324 }
325 }
326
mcp4728_find_matching_scale(struct mcp4728_data * data,int val,int val2)327 static int mcp4728_find_matching_scale(struct mcp4728_data *data, int val,
328 int val2)
329 {
330 for (int i = 0; i < MCP4728_N_SCALES; i++) {
331 if (data->scales_avail[i * 2] == val &&
332 data->scales_avail[i * 2 + 1] == val2)
333 return i;
334 }
335 return -EINVAL;
336 }
337
mcp4728_set_scale(int channel,struct mcp4728_data * data,int val,int val2)338 static int mcp4728_set_scale(int channel, struct mcp4728_data *data, int val,
339 int val2)
340 {
341 int scale = mcp4728_find_matching_scale(data, val, val2);
342
343 if (scale < 0)
344 return scale;
345
346 switch (scale) {
347 case MCP4728_SCALE_VDD:
348 data->chdata[channel].ref_mode = MCP4728_VREF_EXTERNAL_VDD;
349 return 0;
350 case MCP4728_SCALE_VINT_NO_GAIN:
351 data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;
352 data->chdata[channel].g_mode = MCP4728_GAIN_X1;
353 return 0;
354 case MCP4728_SCALE_VINT_GAIN_X2:
355 data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;
356 data->chdata[channel].g_mode = MCP4728_GAIN_X2;
357 return 0;
358 default:
359 return -EINVAL;
360 }
361 }
362
mcp4728_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)363 static int mcp4728_read_raw(struct iio_dev *indio_dev,
364 struct iio_chan_spec const *chan, int *val,
365 int *val2, long mask)
366 {
367 struct mcp4728_data *data = iio_priv(indio_dev);
368
369 switch (mask) {
370 case IIO_CHAN_INFO_RAW:
371 *val = data->chdata[chan->channel].dac_value;
372 return IIO_VAL_INT;
373 case IIO_CHAN_INFO_SCALE:
374 mcp4728_get_scale(chan->channel, data, val, val2);
375 return IIO_VAL_INT_PLUS_MICRO;
376 }
377 return -EINVAL;
378 }
379
mcp4728_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)380 static int mcp4728_write_raw(struct iio_dev *indio_dev,
381 struct iio_chan_spec const *chan, int val,
382 int val2, long mask)
383 {
384 struct mcp4728_data *data = iio_priv(indio_dev);
385 int ret;
386
387 switch (mask) {
388 case IIO_CHAN_INFO_RAW:
389 if (val < 0 || val > GENMASK(MCP4728_RESOLUTION - 1, 0))
390 return -EINVAL;
391 data->chdata[chan->channel].dac_value = val;
392 return mcp4728_program_channel_cfg(chan->channel, indio_dev);
393 case IIO_CHAN_INFO_SCALE:
394 ret = mcp4728_set_scale(chan->channel, data, val, val2);
395 if (ret)
396 return ret;
397
398 return mcp4728_program_channel_cfg(chan->channel, indio_dev);
399 default:
400 return -EINVAL;
401 }
402 }
403
mcp4728_init_scale_avail(enum mcp4728_scale scale,int vref_mv,struct mcp4728_data * data)404 static void mcp4728_init_scale_avail(enum mcp4728_scale scale, int vref_mv,
405 struct mcp4728_data *data)
406 {
407 s64 tmp;
408 int value_micro;
409 int value_int;
410
411 tmp = (s64)vref_mv * 1000000LL >> MCP4728_RESOLUTION;
412 value_int = div_s64_rem(tmp, 1000000LL, &value_micro);
413
414 data->scales_avail[scale * 2] = value_int;
415 data->scales_avail[scale * 2 + 1] = value_micro;
416 }
417
mcp4728_init_scales_avail(struct mcp4728_data * data)418 static int mcp4728_init_scales_avail(struct mcp4728_data *data)
419 {
420 int ret;
421
422 ret = regulator_get_voltage(data->vdd_reg);
423 if (ret < 0)
424 return ret;
425
426 mcp4728_init_scale_avail(MCP4728_SCALE_VDD, ret / 1000, data);
427 mcp4728_init_scale_avail(MCP4728_SCALE_VINT_NO_GAIN, 2048, data);
428 mcp4728_init_scale_avail(MCP4728_SCALE_VINT_GAIN_X2, 4096, data);
429
430 return 0;
431 }
432
mcp4728_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long info)433 static int mcp4728_read_avail(struct iio_dev *indio_dev,
434 struct iio_chan_spec const *chan,
435 const int **vals, int *type, int *length,
436 long info)
437 {
438 struct mcp4728_data *data = iio_priv(indio_dev);
439
440 switch (info) {
441 case IIO_CHAN_INFO_SCALE:
442 *type = IIO_VAL_INT_PLUS_MICRO;
443
444 switch (chan->type) {
445 case IIO_VOLTAGE:
446 *vals = data->scales_avail;
447 *length = MCP4728_N_SCALES * 2;
448 return IIO_AVAIL_LIST;
449 default:
450 return -EINVAL;
451 }
452 default:
453 return -EINVAL;
454 }
455 }
456
457 static const struct iio_info mcp4728_info = {
458 .read_raw = mcp4728_read_raw,
459 .write_raw = mcp4728_write_raw,
460 .read_avail = &mcp4728_read_avail,
461 .attrs = &mcp4728_attribute_group,
462 };
463
mcp4728_suspend(struct device * dev)464 static int mcp4728_suspend(struct device *dev)
465 {
466 struct iio_dev *indio_dev = dev_get_drvdata(dev);
467 struct mcp4728_data *data = iio_priv(indio_dev);
468 unsigned int i;
469
470 data->powerdown = true;
471
472 for (i = 0; i < MCP4728_N_CHANNELS; i++) {
473 int err = mcp4728_program_channel_cfg(i, indio_dev);
474
475 if (err)
476 return err;
477 }
478 return 0;
479 }
480
mcp4728_resume(struct device * dev)481 static int mcp4728_resume(struct device *dev)
482 {
483 struct iio_dev *indio_dev = dev_get_drvdata(dev);
484 struct mcp4728_data *data = iio_priv(indio_dev);
485 int err = 0;
486 unsigned int i;
487
488 data->powerdown = false;
489
490 for (i = 0; i < MCP4728_N_CHANNELS; i++) {
491 int ret = mcp4728_program_channel_cfg(i, indio_dev);
492
493 if (ret)
494 err = ret;
495 }
496 return err;
497 }
498
499 static DEFINE_SIMPLE_DEV_PM_OPS(mcp4728_pm_ops, mcp4728_suspend,
500 mcp4728_resume);
501
mcp4728_init_channels_data(struct mcp4728_data * data)502 static int mcp4728_init_channels_data(struct mcp4728_data *data)
503 {
504 u8 inbuf[MCP4728_READ_RESPONSE_LEN];
505 int ret;
506 unsigned int i;
507
508 ret = i2c_master_recv(data->client, inbuf, MCP4728_READ_RESPONSE_LEN);
509 if (ret < 0) {
510 return dev_err_probe(&data->client->dev, ret,
511 "failed to read mcp4728 conf.\n");
512 } else if (ret != MCP4728_READ_RESPONSE_LEN) {
513 return dev_err_probe(&data->client->dev, -EIO,
514 "failed to read mcp4728 conf. Wrong Response Len ret=%d\n",
515 ret);
516 }
517
518 for (i = 0; i < MCP4728_N_CHANNELS; i++) {
519 struct mcp4728_channel_data *ch = &data->chdata[i];
520 u8 r2 = inbuf[i * 6 + 1];
521 u8 r3 = inbuf[i * 6 + 2];
522
523 ch->dac_value = FIELD_GET(MCP4728_DAC_H_MASK, r2) << 8 |
524 FIELD_GET(MCP4728_DAC_L_MASK, r3);
525 ch->ref_mode = FIELD_GET(MCP4728_VREF_MASK, r2);
526 ch->pd_mode = FIELD_GET(MCP4728_PDMODE_MASK, r2);
527 ch->g_mode = FIELD_GET(MCP4728_GAIN_MASK, r2);
528 }
529
530 return 0;
531 }
532
mcp4728_reg_disable(void * reg)533 static void mcp4728_reg_disable(void *reg)
534 {
535 regulator_disable(reg);
536 }
537
mcp4728_probe(struct i2c_client * client)538 static int mcp4728_probe(struct i2c_client *client)
539 {
540 const struct i2c_device_id *id = i2c_client_get_device_id(client);
541 struct mcp4728_data *data;
542 struct iio_dev *indio_dev;
543 int err;
544
545 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
546 if (!indio_dev)
547 return -ENOMEM;
548
549 data = iio_priv(indio_dev);
550 i2c_set_clientdata(client, indio_dev);
551 data->client = client;
552
553 data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
554 if (IS_ERR(data->vdd_reg))
555 return PTR_ERR(data->vdd_reg);
556
557 err = regulator_enable(data->vdd_reg);
558 if (err)
559 return err;
560
561 err = devm_add_action_or_reset(&client->dev, mcp4728_reg_disable,
562 data->vdd_reg);
563 if (err)
564 return err;
565
566 /*
567 * MCP4728 has internal EEPROM that save each channel boot
568 * configuration. It means that device configuration is unknown to the
569 * driver at kernel boot. mcp4728_init_channels_data() reads back DAC
570 * settings and stores them in data structure.
571 */
572 err = mcp4728_init_channels_data(data);
573 if (err) {
574 return dev_err_probe(&client->dev, err,
575 "failed to read mcp4728 current configuration\n");
576 }
577
578 err = mcp4728_init_scales_avail(data);
579 if (err) {
580 return dev_err_probe(&client->dev, err,
581 "failed to init scales\n");
582 }
583
584 indio_dev->name = id->name;
585 indio_dev->info = &mcp4728_info;
586 indio_dev->channels = mcp4728_channels;
587 indio_dev->num_channels = MCP4728_N_CHANNELS;
588 indio_dev->modes = INDIO_DIRECT_MODE;
589
590 return devm_iio_device_register(&client->dev, indio_dev);
591 }
592
593 static const struct i2c_device_id mcp4728_id[] = {
594 { "mcp4728", 0 },
595 {}
596 };
597 MODULE_DEVICE_TABLE(i2c, mcp4728_id);
598
599 static const struct of_device_id mcp4728_of_match[] = {
600 { .compatible = "microchip,mcp4728" },
601 {}
602 };
603 MODULE_DEVICE_TABLE(of, mcp4728_of_match);
604
605 static struct i2c_driver mcp4728_driver = {
606 .driver = {
607 .name = "mcp4728",
608 .of_match_table = mcp4728_of_match,
609 .pm = pm_sleep_ptr(&mcp4728_pm_ops),
610 },
611 .probe = mcp4728_probe,
612 .id_table = mcp4728_id,
613 };
614 module_i2c_driver(mcp4728_driver);
615
616 MODULE_AUTHOR("Andrea Collamati <andrea.collamati@gmail.com>");
617 MODULE_DESCRIPTION("MCP4728 12-bit DAC");
618 MODULE_LICENSE("GPL");
619