blob: d4c243c2fa2f553831123a626ca7b56e3be28912 [file] [log] [blame]
Ajay Agarwal76081082018-01-31 14:32:19 +05301/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
Manu Gautam115c2982013-07-17 11:58:34 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 */
7
8#include <linux/module.h>
9#include <linux/platform_device.h>
10#include <linux/pm_runtime.h>
11#include <linux/usb/msm_hsusb_hw.h>
12#include <linux/usb/ulpi.h>
13#include <linux/gpio.h>
Ajay Agarwal76081082018-01-31 14:32:19 +053014#include <linux/pinctrl/consumer.h>
Manu Gautam115c2982013-07-17 11:58:34 +053015
16#include "ci13xxx_udc.c"
17
18#define MSM_USB_BASE (udc->regs)
19
20#define CI13XXX_MSM_MAX_LOG2_ITC 7
21
22struct ci13xxx_udc_context {
23 int irq;
24 void __iomem *regs;
25 int wake_gpio;
26 int wake_irq;
27 bool wake_irq_state;
Ajay Agarwal76081082018-01-31 14:32:19 +053028 struct pinctrl *ci13xxx_pinctrl;
29 struct timer_list irq_enable_timer;
30 bool irq_disabled;
Manu Gautam115c2982013-07-17 11:58:34 +053031};
32
33static struct ci13xxx_udc_context _udc_ctxt;
Ajay Agarwal76081082018-01-31 14:32:19 +053034#define IRQ_ENABLE_DELAY (jiffies + msecs_to_jiffies(1000))
Manu Gautam115c2982013-07-17 11:58:34 +053035
36static irqreturn_t msm_udc_irq(int irq, void *data)
37{
38 return udc_irq();
39}
40
41static void ci13xxx_msm_suspend(void)
42{
43 struct device *dev = _udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +053044
Manu Gautam115c2982013-07-17 11:58:34 +053045 dev_dbg(dev, "ci13xxx_msm_suspend\n");
46
47 if (_udc_ctxt.wake_irq && !_udc_ctxt.wake_irq_state) {
48 enable_irq_wake(_udc_ctxt.wake_irq);
49 enable_irq(_udc_ctxt.wake_irq);
50 _udc_ctxt.wake_irq_state = true;
51 }
52}
53
54static void ci13xxx_msm_resume(void)
55{
56 struct device *dev = _udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +053057
Manu Gautam115c2982013-07-17 11:58:34 +053058 dev_dbg(dev, "ci13xxx_msm_resume\n");
59
60 if (_udc_ctxt.wake_irq && _udc_ctxt.wake_irq_state) {
61 disable_irq_wake(_udc_ctxt.wake_irq);
62 disable_irq_nosync(_udc_ctxt.wake_irq);
63 _udc_ctxt.wake_irq_state = false;
64 }
65}
66
67static void ci13xxx_msm_disconnect(void)
68{
69 struct ci13xxx *udc = _udc;
70 struct usb_phy *phy = udc->transceiver;
71
Ajay Agarwal76081082018-01-31 14:32:19 +053072 if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
73 u32 temp;
74
Manu Gautam115c2982013-07-17 11:58:34 +053075 usb_phy_io_write(phy,
76 ULPI_MISC_A_VBUSVLDEXT |
77 ULPI_MISC_A_VBUSVLDEXTSEL,
78 ULPI_CLR(ULPI_MISC_A));
Ajay Agarwal76081082018-01-31 14:32:19 +053079
80 /* Notify LINK of VBUS LOW */
81 temp = readl_relaxed(USB_USBCMD);
82 temp &= ~USBCMD_SESS_VLD_CTRL;
83 writel_relaxed(temp, USB_USBCMD);
84
85 /*
86 * Add memory barrier as it is must to complete
87 * above USB PHY and Link register writes before
88 * moving ahead with USB peripheral mode enumeration,
89 * otherwise USB peripheral mode may not work.
90 */
91 mb();
92 }
Manu Gautam115c2982013-07-17 11:58:34 +053093}
94
95/* Link power management will reduce power consumption by
96 * short time HW suspend/resume.
97 */
98static void ci13xxx_msm_set_l1(struct ci13xxx *udc)
99{
100 int temp;
101 struct device *dev = udc->gadget.dev.parent;
102
103 dev_dbg(dev, "Enable link power management\n");
104
105 /* Enable remote wakeup and L1 for IN EPs */
106 writel_relaxed(0xffff0000, USB_L1_EP_CTRL);
107
108 temp = readl_relaxed(USB_L1_CONFIG);
109 temp |= L1_CONFIG_LPM_EN | L1_CONFIG_REMOTE_WAKEUP |
110 L1_CONFIG_GATE_SYS_CLK | L1_CONFIG_PHY_LPM |
111 L1_CONFIG_PLL;
112 writel_relaxed(temp, USB_L1_CONFIG);
113}
114
115static void ci13xxx_msm_connect(void)
116{
117 struct ci13xxx *udc = _udc;
118 struct usb_phy *phy = udc->transceiver;
119
120 if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
121 int temp;
122
123 usb_phy_io_write(phy,
124 ULPI_MISC_A_VBUSVLDEXT |
125 ULPI_MISC_A_VBUSVLDEXTSEL,
126 ULPI_SET(ULPI_MISC_A));
127
Ajay Agarwal76081082018-01-31 14:32:19 +0530128 temp = readl_relaxed(USB_GENCONFIG_2);
129 temp |= GENCONFIG_2_SESS_VLD_CTRL_EN;
130 writel_relaxed(temp, USB_GENCONFIG_2);
Manu Gautam115c2982013-07-17 11:58:34 +0530131
132 temp = readl_relaxed(USB_USBCMD);
133 temp |= USBCMD_SESS_VLD_CTRL;
134 writel_relaxed(temp, USB_USBCMD);
135
136 /*
137 * Add memory barrier as it is must to complete
138 * above USB PHY and Link register writes before
139 * moving ahead with USB peripheral mode enumeration,
140 * otherwise USB peripheral mode may not work.
141 */
142 mb();
143 }
144}
145
146static void ci13xxx_msm_reset(void)
147{
148 struct ci13xxx *udc = _udc;
149 struct usb_phy *phy = udc->transceiver;
150 struct device *dev = udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +0530151 int temp;
Manu Gautam115c2982013-07-17 11:58:34 +0530152
153 writel_relaxed(0, USB_AHBBURST);
154 writel_relaxed(0x08, USB_AHBMODE);
155
Ajay Agarwal76081082018-01-31 14:32:19 +0530156 /* workaround for rx buffer collision issue */
157 temp = readl_relaxed(USB_GENCONFIG);
158 temp &= ~GENCONFIG_TXFIFO_IDLE_FORCE_DISABLE;
159 temp &= ~GENCONFIG_ULPI_SERIAL_EN;
160 writel_relaxed(temp, USB_GENCONFIG);
161
Manu Gautam115c2982013-07-17 11:58:34 +0530162 if (udc->gadget.l1_supported)
163 ci13xxx_msm_set_l1(udc);
164
165 if (phy && (phy->flags & ENABLE_SECONDARY_PHY)) {
166 int temp;
167
168 dev_dbg(dev, "using secondary hsphy\n");
169 temp = readl_relaxed(USB_PHY_CTRL2);
170 temp |= (1<<16);
171 writel_relaxed(temp, USB_PHY_CTRL2);
172
173 /*
174 * Add memory barrier to make sure above LINK writes are
175 * complete before moving ahead with USB peripheral mode
176 * enumeration.
177 */
178 mb();
179 }
180}
181
Ajay Agarwal76081082018-01-31 14:32:19 +0530182static void ci13xxx_msm_mark_err_event(void)
183{
184 struct ci13xxx *udc = _udc;
185 struct msm_otg *otg;
186
187 if (udc == NULL)
188 return;
189
190 if (udc->transceiver == NULL)
191 return;
192
193 otg = container_of(udc->transceiver, struct msm_otg, phy);
194
195 /* This will trigger hardware reset before next connection */
196 otg->err_event_seen = true;
197}
198
199static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned int event)
Manu Gautam115c2982013-07-17 11:58:34 +0530200{
201 struct device *dev = udc->gadget.dev.parent;
202
203 switch (event) {
204 case CI13XXX_CONTROLLER_RESET_EVENT:
205 dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
206 ci13xxx_msm_reset();
207 break;
208 case CI13XXX_CONTROLLER_DISCONNECT_EVENT:
209 dev_info(dev, "CI13XXX_CONTROLLER_DISCONNECT_EVENT received\n");
210 ci13xxx_msm_disconnect();
211 ci13xxx_msm_resume();
212 break;
213 case CI13XXX_CONTROLLER_CONNECT_EVENT:
214 dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
215 ci13xxx_msm_connect();
216 break;
217 case CI13XXX_CONTROLLER_SUSPEND_EVENT:
218 dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
219 ci13xxx_msm_suspend();
220 break;
221 case CI13XXX_CONTROLLER_RESUME_EVENT:
222 dev_info(dev, "CI13XXX_CONTROLLER_RESUME_EVENT received\n");
223 ci13xxx_msm_resume();
224 break;
Ajay Agarwal76081082018-01-31 14:32:19 +0530225 case CI13XXX_CONTROLLER_ERROR_EVENT:
226 dev_info(dev, "CI13XXX_CONTROLLER_ERROR_EVENT received\n");
227 ci13xxx_msm_mark_err_event();
228 break;
229 case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
230 dev_info(dev,
231 "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
232 break;
Manu Gautam115c2982013-07-17 11:58:34 +0530233 default:
234 dev_dbg(dev, "unknown ci13xxx_udc event\n");
235 break;
236 }
237}
238
Ajay Agarwal76081082018-01-31 14:32:19 +0530239static bool ci13xxx_msm_in_lpm(struct ci13xxx *udc)
240{
241 struct msm_otg *otg;
242
243 if (udc == NULL)
244 return false;
245
246 if (udc->transceiver == NULL)
247 return false;
248
249 otg = container_of(udc->transceiver, struct msm_otg, phy);
250
251 return (atomic_read(&otg->in_lpm) != 0);
252}
253
254
Manu Gautam115c2982013-07-17 11:58:34 +0530255static irqreturn_t ci13xxx_msm_resume_irq(int irq, void *data)
256{
257 struct ci13xxx *udc = _udc;
258
259 if (udc->transceiver && udc->vbus_active && udc->suspended)
260 usb_phy_set_suspend(udc->transceiver, 0);
261 else if (!udc->suspended)
262 ci13xxx_msm_resume();
263
264 return IRQ_HANDLED;
265}
266
267static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
268 .name = "ci13xxx_msm",
269 .flags = CI13XXX_REGS_SHARED |
270 CI13XXX_REQUIRE_TRANSCEIVER |
271 CI13XXX_PULLUP_ON_VBUS |
272 CI13XXX_ZERO_ITC |
Ajay Agarwal76081082018-01-31 14:32:19 +0530273 CI13XXX_DISABLE_STREAMING,
Manu Gautam115c2982013-07-17 11:58:34 +0530274 .nz_itc = 0,
275 .notify_event = ci13xxx_msm_notify_event,
Ajay Agarwal76081082018-01-31 14:32:19 +0530276 .in_lpm = ci13xxx_msm_in_lpm,
Manu Gautam115c2982013-07-17 11:58:34 +0530277};
278
279static int ci13xxx_msm_install_wake_gpio(struct platform_device *pdev,
280 struct resource *res)
281{
282 int wake_irq;
283 int ret;
Ajay Agarwal76081082018-01-31 14:32:19 +0530284 struct pinctrl_state *set_state;
Manu Gautam115c2982013-07-17 11:58:34 +0530285
286 dev_dbg(&pdev->dev, "ci13xxx_msm_install_wake_gpio\n");
287
288 _udc_ctxt.wake_gpio = res->start;
Ajay Agarwal76081082018-01-31 14:32:19 +0530289 if (_udc_ctxt.ci13xxx_pinctrl) {
290 set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
291 "ci13xxx_active");
292 if (IS_ERR(set_state)) {
293 pr_err("cannot get ci13xxx pinctrl active state\n");
294 return PTR_ERR(set_state);
295 }
296 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl, set_state);
297 }
Manu Gautam115c2982013-07-17 11:58:34 +0530298 gpio_request(_udc_ctxt.wake_gpio, "USB_RESUME");
299 gpio_direction_input(_udc_ctxt.wake_gpio);
300 wake_irq = gpio_to_irq(_udc_ctxt.wake_gpio);
301 if (wake_irq < 0) {
302 dev_err(&pdev->dev, "could not register USB_RESUME GPIO.\n");
303 return -ENXIO;
304 }
305
306 dev_dbg(&pdev->dev, "_udc_ctxt.gpio_irq = %d and irq = %d\n",
307 _udc_ctxt.wake_gpio, wake_irq);
308 ret = request_irq(wake_irq, ci13xxx_msm_resume_irq,
309 IRQF_TRIGGER_RISING | IRQF_ONESHOT, "usb resume", NULL);
310 if (ret < 0) {
311 dev_err(&pdev->dev, "could not register USB_RESUME IRQ.\n");
312 goto gpio_free;
313 }
314 disable_irq(wake_irq);
315 _udc_ctxt.wake_irq = wake_irq;
316
317 return 0;
318
319gpio_free:
320 gpio_free(_udc_ctxt.wake_gpio);
Ajay Agarwal76081082018-01-31 14:32:19 +0530321 if (_udc_ctxt.ci13xxx_pinctrl) {
322 set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
323 "ci13xxx_sleep");
324 if (IS_ERR(set_state))
325 pr_err("cannot get ci13xxx pinctrl sleep state\n");
326 else
327 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
328 set_state);
329 }
Manu Gautam115c2982013-07-17 11:58:34 +0530330 _udc_ctxt.wake_gpio = 0;
331 return ret;
332}
333
334static void ci13xxx_msm_uninstall_wake_gpio(struct platform_device *pdev)
335{
Ajay Agarwal76081082018-01-31 14:32:19 +0530336 struct pinctrl_state *set_state;
337
Manu Gautam115c2982013-07-17 11:58:34 +0530338 dev_dbg(&pdev->dev, "ci13xxx_msm_uninstall_wake_gpio\n");
339
340 if (_udc_ctxt.wake_gpio) {
341 gpio_free(_udc_ctxt.wake_gpio);
Ajay Agarwal76081082018-01-31 14:32:19 +0530342 if (_udc_ctxt.ci13xxx_pinctrl) {
343 set_state =
344 pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
345 "ci13xxx_sleep");
346 if (IS_ERR(set_state))
347 pr_err("cannot get ci13xxx pinctrl sleep state\n");
348 else
349 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
350 set_state);
351 }
Manu Gautam115c2982013-07-17 11:58:34 +0530352 _udc_ctxt.wake_gpio = 0;
353 }
354}
355
Ajay Agarwal76081082018-01-31 14:32:19 +0530356static void enable_usb_irq_timer_func(unsigned long data);
Manu Gautam115c2982013-07-17 11:58:34 +0530357static int ci13xxx_msm_probe(struct platform_device *pdev)
358{
359 struct resource *res;
360 int ret;
361 struct ci13xxx_platform_data *pdata = pdev->dev.platform_data;
362 bool is_l1_supported = false;
363
364 dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
365
366 if (pdata) {
367 /* Acceptable values for nz_itc are: 0,1,2,4,8,16,32,64 */
368 if (pdata->log2_itc > CI13XXX_MSM_MAX_LOG2_ITC ||
369 pdata->log2_itc <= 0)
370 ci13xxx_msm_udc_driver.nz_itc = 0;
371 else
372 ci13xxx_msm_udc_driver.nz_itc =
373 1 << (pdata->log2_itc-1);
374
375 is_l1_supported = pdata->l1_supported;
Ajay Agarwal76081082018-01-31 14:32:19 +0530376 /* Set ahb2ahb bypass flag if it is requested. */
377 if (pdata->enable_ahb2ahb_bypass)
378 ci13xxx_msm_udc_driver.flags |=
379 CI13XXX_ENABLE_AHB2AHB_BYPASS;
380
381 /* Clear disable streaming flag if is requested. */
382 if (pdata->enable_streaming)
383 ci13xxx_msm_udc_driver.flags &=
384 ~CI13XXX_DISABLE_STREAMING;
Manu Gautam115c2982013-07-17 11:58:34 +0530385 }
386
387 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
388 if (!res) {
389 dev_err(&pdev->dev, "failed to get platform resource mem\n");
390 return -ENXIO;
391 }
392
393 _udc_ctxt.regs = ioremap(res->start, resource_size(res));
394 if (!_udc_ctxt.regs) {
395 dev_err(&pdev->dev, "ioremap failed\n");
396 return -ENOMEM;
397 }
398
399 ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, _udc_ctxt.regs);
400 if (ret < 0) {
401 dev_err(&pdev->dev, "udc_probe failed\n");
402 goto iounmap;
403 }
404
405 _udc->gadget.l1_supported = is_l1_supported;
406
407 _udc_ctxt.irq = platform_get_irq(pdev, 0);
408 if (_udc_ctxt.irq < 0) {
409 dev_err(&pdev->dev, "IRQ not found\n");
410 ret = -ENXIO;
411 goto udc_remove;
412 }
413
414 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "USB_RESUME");
Ajay Agarwal76081082018-01-31 14:32:19 +0530415 /* Get pinctrl if target uses pinctrl */
416 _udc_ctxt.ci13xxx_pinctrl = devm_pinctrl_get(&pdev->dev);
417 if (IS_ERR(_udc_ctxt.ci13xxx_pinctrl)) {
418 if (of_property_read_bool(pdev->dev.of_node, "pinctrl-names")) {
419 dev_err(&pdev->dev, "Error encountered while getting pinctrl");
420 ret = PTR_ERR(_udc_ctxt.ci13xxx_pinctrl);
421 goto udc_remove;
422 }
423 dev_dbg(&pdev->dev, "Target does not use pinctrl\n");
424 _udc_ctxt.ci13xxx_pinctrl = NULL;
425 }
Manu Gautam115c2982013-07-17 11:58:34 +0530426 if (res) {
427 ret = ci13xxx_msm_install_wake_gpio(pdev, res);
428 if (ret < 0) {
429 dev_err(&pdev->dev, "gpio irq install failed\n");
430 goto udc_remove;
431 }
432 }
433
434 ret = request_irq(_udc_ctxt.irq, msm_udc_irq, IRQF_SHARED, pdev->name,
435 pdev);
436 if (ret < 0) {
437 dev_err(&pdev->dev, "request_irq failed\n");
438 goto gpio_uninstall;
439 }
440
Ajay Agarwal76081082018-01-31 14:32:19 +0530441 setup_timer(&_udc_ctxt.irq_enable_timer, enable_usb_irq_timer_func,
442 (unsigned long)NULL);
443
Manu Gautam115c2982013-07-17 11:58:34 +0530444 pm_runtime_no_callbacks(&pdev->dev);
Ajay Agarwal76081082018-01-31 14:32:19 +0530445 pm_runtime_set_active(&pdev->dev);
Manu Gautam115c2982013-07-17 11:58:34 +0530446 pm_runtime_enable(&pdev->dev);
447
448 return 0;
449
450gpio_uninstall:
451 ci13xxx_msm_uninstall_wake_gpio(pdev);
452udc_remove:
453 udc_remove();
454iounmap:
455 iounmap(_udc_ctxt.regs);
456
457 return ret;
458}
459
460int ci13xxx_msm_remove(struct platform_device *pdev)
461{
462 pm_runtime_disable(&pdev->dev);
463 free_irq(_udc_ctxt.irq, pdev);
464 ci13xxx_msm_uninstall_wake_gpio(pdev);
465 udc_remove();
466 iounmap(_udc_ctxt.regs);
467 return 0;
468}
469
Ajay Agarwal76081082018-01-31 14:32:19 +0530470void ci13xxx_msm_shutdown(struct platform_device *pdev)
471{
472 ci13xxx_pullup(&_udc->gadget, 0);
473}
474
475void msm_hw_soft_reset(void)
476{
477 struct ci13xxx *udc = _udc;
478
479 hw_device_reset(udc);
480}
481
Manu Gautam115c2982013-07-17 11:58:34 +0530482void msm_hw_bam_disable(bool bam_disable)
483{
484 u32 val;
485 struct ci13xxx *udc = _udc;
486
487 if (bam_disable)
488 val = readl_relaxed(USB_GENCONFIG) | GENCONFIG_BAM_DISABLE;
489 else
490 val = readl_relaxed(USB_GENCONFIG) & ~GENCONFIG_BAM_DISABLE;
491
492 writel_relaxed(val, USB_GENCONFIG);
493}
494
Ajay Agarwal76081082018-01-31 14:32:19 +0530495void msm_usb_irq_disable(bool disable)
496{
497 struct ci13xxx *udc = _udc;
498 unsigned long flags;
499
500 spin_lock_irqsave(udc->lock, flags);
501
502 if (_udc_ctxt.irq_disabled == disable) {
503 pr_debug("Interrupt state already disable = %d\n", disable);
504 if (disable)
505 mod_timer(&_udc_ctxt.irq_enable_timer,
506 IRQ_ENABLE_DELAY);
507 spin_unlock_irqrestore(udc->lock, flags);
508 return;
509 }
510
511 if (disable) {
512 disable_irq_nosync(_udc_ctxt.irq);
513 /* start timer here */
514 pr_debug("%s: Disabling interrupts\n", __func__);
515 mod_timer(&_udc_ctxt.irq_enable_timer, IRQ_ENABLE_DELAY);
516 _udc_ctxt.irq_disabled = true;
517
518 } else {
519 pr_debug("%s: Enabling interrupts\n", __func__);
520 del_timer(&_udc_ctxt.irq_enable_timer);
521 enable_irq(_udc_ctxt.irq);
522 _udc_ctxt.irq_disabled = false;
523 }
524
525 spin_unlock_irqrestore(udc->lock, flags);
526}
527
528static void enable_usb_irq_timer_func(unsigned long data)
529{
530 pr_debug("enabling interrupt from timer\n");
531 msm_usb_irq_disable(false);
532}
533
Manu Gautam115c2982013-07-17 11:58:34 +0530534static struct platform_driver ci13xxx_msm_driver = {
535 .probe = ci13xxx_msm_probe,
536 .driver = {
537 .name = "msm_hsusb",
538 },
539 .remove = ci13xxx_msm_remove,
Ajay Agarwal76081082018-01-31 14:32:19 +0530540 .shutdown = ci13xxx_msm_shutdown,
Manu Gautam115c2982013-07-17 11:58:34 +0530541};
542MODULE_ALIAS("platform:msm_hsusb");
543
544static int __init ci13xxx_msm_init(void)
545{
546 return platform_driver_register(&ci13xxx_msm_driver);
547}
548module_init(ci13xxx_msm_init);
549
550static void __exit ci13xxx_msm_exit(void)
551{
552 platform_driver_unregister(&ci13xxx_msm_driver);
553}
554module_exit(ci13xxx_msm_exit);
555
556MODULE_LICENSE("GPL v2");