hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/reset/reset-imx7.c
....@@ -1,30 +1,36 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2017, Impinj, Inc.
34 *
45 * i.MX7 System Reset Controller (SRC) driver
56 *
67 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; version 2 of the License.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
168 */
179
1810 #include <linux/mfd/syscon.h>
19
-#include <linux/mod_devicetable.h>
11
+#include <linux/module.h>
12
+#include <linux/of_device.h>
2013 #include <linux/platform_device.h>
2114 #include <linux/reset-controller.h>
2215 #include <linux/regmap.h>
2316 #include <dt-bindings/reset/imx7-reset.h>
17
+#include <dt-bindings/reset/imx8mq-reset.h>
18
+#include <dt-bindings/reset/imx8mp-reset.h>
19
+
20
+struct imx7_src_signal {
21
+ unsigned int offset, bit;
22
+};
23
+
24
+struct imx7_src_variant {
25
+ const struct imx7_src_signal *signals;
26
+ unsigned int signals_num;
27
+ struct reset_control_ops ops;
28
+};
2429
2530 struct imx7_src {
2631 struct reset_controller_dev rcdev;
2732 struct regmap *regmap;
33
+ const struct imx7_src_signal *signals;
2834 };
2935
3036 enum imx7_src_registers {
....@@ -39,9 +45,14 @@
3945 SRC_DDRC_RCR = 0x1000,
4046 };
4147
42
-struct imx7_src_signal {
43
- unsigned int offset, bit;
44
-};
48
+static int imx7_reset_update(struct imx7_src *imx7src,
49
+ unsigned long id, unsigned int value)
50
+{
51
+ const struct imx7_src_signal *signal = &imx7src->signals[id];
52
+
53
+ return regmap_update_bits(imx7src->regmap,
54
+ signal->offset, signal->bit, value);
55
+}
4556
4657 static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
4758 [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
....@@ -67,6 +78,7 @@
6778 [IMX7_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
6879 [IMX7_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
6980 [IMX7_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
81
+ [IMX7_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
7082 [IMX7_RESET_DDRC_PRST] = { SRC_DDRC_RCR, BIT(0) },
7183 [IMX7_RESET_DDRC_CORE_RST] = { SRC_DDRC_RCR, BIT(1) },
7284 };
....@@ -80,8 +92,8 @@
8092 unsigned long id, bool assert)
8193 {
8294 struct imx7_src *imx7src = to_imx7_src(rcdev);
83
- const struct imx7_src_signal *signal = &imx7_src_signals[id];
84
- unsigned int value = assert ? signal->bit : 0;
95
+ const unsigned int bit = imx7src->signals[id].bit;
96
+ unsigned int value = assert ? bit : 0;
8597
8698 switch (id) {
8799 case IMX7_RESET_PCIEPHY:
....@@ -94,12 +106,11 @@
94106 break;
95107
96108 case IMX7_RESET_PCIE_CTRL_APPS_EN:
97
- value = (assert) ? 0 : signal->bit;
109
+ value = assert ? 0 : bit;
98110 break;
99111 }
100112
101
- return regmap_update_bits(imx7src->regmap,
102
- signal->offset, signal->bit, value);
113
+ return imx7_reset_update(imx7src, id, value);
103114 }
104115
105116 static int imx7_reset_assert(struct reset_controller_dev *rcdev,
....@@ -114,9 +125,237 @@
114125 return imx7_reset_set(rcdev, id, false);
115126 }
116127
117
-static const struct reset_control_ops imx7_reset_ops = {
118
- .assert = imx7_reset_assert,
119
- .deassert = imx7_reset_deassert,
128
+static const struct imx7_src_variant variant_imx7 = {
129
+ .signals = imx7_src_signals,
130
+ .signals_num = ARRAY_SIZE(imx7_src_signals),
131
+ .ops = {
132
+ .assert = imx7_reset_assert,
133
+ .deassert = imx7_reset_deassert,
134
+ },
135
+};
136
+
137
+enum imx8mq_src_registers {
138
+ SRC_A53RCR0 = 0x0004,
139
+ SRC_HDMI_RCR = 0x0030,
140
+ SRC_DISP_RCR = 0x0034,
141
+ SRC_GPU_RCR = 0x0040,
142
+ SRC_VPU_RCR = 0x0044,
143
+ SRC_PCIE2_RCR = 0x0048,
144
+ SRC_MIPIPHY1_RCR = 0x004c,
145
+ SRC_MIPIPHY2_RCR = 0x0050,
146
+ SRC_DDRC2_RCR = 0x1004,
147
+};
148
+
149
+enum imx8mp_src_registers {
150
+ SRC_SUPERMIX_RCR = 0x0018,
151
+ SRC_AUDIOMIX_RCR = 0x001c,
152
+ SRC_MLMIX_RCR = 0x0028,
153
+ SRC_GPU2D_RCR = 0x0038,
154
+ SRC_GPU3D_RCR = 0x003c,
155
+ SRC_VPU_G1_RCR = 0x0048,
156
+ SRC_VPU_G2_RCR = 0x004c,
157
+ SRC_VPUVC8KE_RCR = 0x0050,
158
+ SRC_NOC_RCR = 0x0054,
159
+};
160
+
161
+static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
162
+ [IMX8MQ_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) },
163
+ [IMX8MQ_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) },
164
+ [IMX8MQ_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) },
165
+ [IMX8MQ_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) },
166
+ [IMX8MQ_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) },
167
+ [IMX8MQ_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) },
168
+ [IMX8MQ_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) },
169
+ [IMX8MQ_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) },
170
+ [IMX8MQ_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) },
171
+ [IMX8MQ_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) },
172
+ [IMX8MQ_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) },
173
+ [IMX8MQ_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) },
174
+ [IMX8MQ_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) },
175
+ [IMX8MQ_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) },
176
+ [IMX8MQ_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) },
177
+ [IMX8MQ_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) },
178
+ [IMX8MQ_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) },
179
+ [IMX8MQ_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) },
180
+ [IMX8MQ_RESET_SW_NON_SCLR_M4C_RST] = { SRC_M4RCR, BIT(0) },
181
+ [IMX8MQ_RESET_SW_M4C_RST] = { SRC_M4RCR, BIT(1) },
182
+ [IMX8MQ_RESET_SW_M4P_RST] = { SRC_M4RCR, BIT(2) },
183
+ [IMX8MQ_RESET_M4_ENABLE] = { SRC_M4RCR, BIT(3) },
184
+ [IMX8MQ_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) },
185
+ [IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
186
+ [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
187
+ [IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) },
188
+ [IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
189
+ [IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
190
+ [IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
191
+ [IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR,
192
+ BIT(2) | BIT(1) },
193
+ [IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
194
+ [IMX8MQ_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
195
+ [IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
196
+ [IMX8MQ_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) },
197
+ [IMX8MQ_RESET_DISP_RESET] = { SRC_DISP_RCR, BIT(0) },
198
+ [IMX8MQ_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) },
199
+ [IMX8MQ_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) },
200
+ [IMX8MQ_RESET_PCIEPHY2] = { SRC_PCIE2_RCR,
201
+ BIT(2) | BIT(1) },
202
+ [IMX8MQ_RESET_PCIEPHY2_PERST] = { SRC_PCIE2_RCR, BIT(3) },
203
+ [IMX8MQ_RESET_PCIE2_CTRL_APPS_EN] = { SRC_PCIE2_RCR, BIT(6) },
204
+ [IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF] = { SRC_PCIE2_RCR, BIT(11) },
205
+ [IMX8MQ_RESET_MIPI_CSI1_CORE_RESET] = { SRC_MIPIPHY1_RCR, BIT(0) },
206
+ [IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET] = { SRC_MIPIPHY1_RCR, BIT(1) },
207
+ [IMX8MQ_RESET_MIPI_CSI1_ESC_RESET] = { SRC_MIPIPHY1_RCR, BIT(2) },
208
+ [IMX8MQ_RESET_MIPI_CSI2_CORE_RESET] = { SRC_MIPIPHY2_RCR, BIT(0) },
209
+ [IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET] = { SRC_MIPIPHY2_RCR, BIT(1) },
210
+ [IMX8MQ_RESET_MIPI_CSI2_ESC_RESET] = { SRC_MIPIPHY2_RCR, BIT(2) },
211
+ [IMX8MQ_RESET_DDRC1_PRST] = { SRC_DDRC_RCR, BIT(0) },
212
+ [IMX8MQ_RESET_DDRC1_CORE_RESET] = { SRC_DDRC_RCR, BIT(1) },
213
+ [IMX8MQ_RESET_DDRC1_PHY_RESET] = { SRC_DDRC_RCR, BIT(2) },
214
+ [IMX8MQ_RESET_DDRC2_PHY_RESET] = { SRC_DDRC2_RCR, BIT(0) },
215
+ [IMX8MQ_RESET_DDRC2_CORE_RESET] = { SRC_DDRC2_RCR, BIT(1) },
216
+ [IMX8MQ_RESET_DDRC2_PRST] = { SRC_DDRC2_RCR, BIT(2) },
217
+};
218
+
219
+static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
220
+ unsigned long id, bool assert)
221
+{
222
+ struct imx7_src *imx7src = to_imx7_src(rcdev);
223
+ const unsigned int bit = imx7src->signals[id].bit;
224
+ unsigned int value = assert ? bit : 0;
225
+
226
+ switch (id) {
227
+ case IMX8MQ_RESET_PCIEPHY:
228
+ case IMX8MQ_RESET_PCIEPHY2:
229
+ /*
230
+ * wait for more than 10us to release phy g_rst and
231
+ * btnrst
232
+ */
233
+ if (!assert)
234
+ udelay(10);
235
+ break;
236
+
237
+ case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
238
+ case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN:
239
+ case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N:
240
+ case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N:
241
+ case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N:
242
+ case IMX8MQ_RESET_MIPI_DSI_RESET_N:
243
+ case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N:
244
+ case IMX8MQ_RESET_M4_ENABLE:
245
+ value = assert ? 0 : bit;
246
+ break;
247
+ }
248
+
249
+ return imx7_reset_update(imx7src, id, value);
250
+}
251
+
252
+static int imx8mq_reset_assert(struct reset_controller_dev *rcdev,
253
+ unsigned long id)
254
+{
255
+ return imx8mq_reset_set(rcdev, id, true);
256
+}
257
+
258
+static int imx8mq_reset_deassert(struct reset_controller_dev *rcdev,
259
+ unsigned long id)
260
+{
261
+ return imx8mq_reset_set(rcdev, id, false);
262
+}
263
+
264
+static const struct imx7_src_variant variant_imx8mq = {
265
+ .signals = imx8mq_src_signals,
266
+ .signals_num = ARRAY_SIZE(imx8mq_src_signals),
267
+ .ops = {
268
+ .assert = imx8mq_reset_assert,
269
+ .deassert = imx8mq_reset_deassert,
270
+ },
271
+};
272
+
273
+static const struct imx7_src_signal imx8mp_src_signals[IMX8MP_RESET_NUM] = {
274
+ [IMX8MP_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) },
275
+ [IMX8MP_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) },
276
+ [IMX8MP_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) },
277
+ [IMX8MP_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) },
278
+ [IMX8MP_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) },
279
+ [IMX8MP_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) },
280
+ [IMX8MP_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) },
281
+ [IMX8MP_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) },
282
+ [IMX8MP_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) },
283
+ [IMX8MP_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) },
284
+ [IMX8MP_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) },
285
+ [IMX8MP_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) },
286
+ [IMX8MP_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) },
287
+ [IMX8MP_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) },
288
+ [IMX8MP_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) },
289
+ [IMX8MP_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) },
290
+ [IMX8MP_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) },
291
+ [IMX8MP_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) },
292
+ [IMX8MP_RESET_SW_NON_SCLR_M7C_RST] = { SRC_M4RCR, BIT(0) },
293
+ [IMX8MP_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) },
294
+ [IMX8MP_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
295
+ [IMX8MP_RESET_SUPERMIX_RESET] = { SRC_SUPERMIX_RCR, BIT(0) },
296
+ [IMX8MP_RESET_AUDIOMIX_RESET] = { SRC_AUDIOMIX_RCR, BIT(0) },
297
+ [IMX8MP_RESET_MLMIX_RESET] = { SRC_MLMIX_RCR, BIT(0) },
298
+ [IMX8MP_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) },
299
+ [IMX8MP_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
300
+ [IMX8MP_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
301
+ [IMX8MP_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
302
+ [IMX8MP_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) },
303
+ [IMX8MP_RESET_MEDIA_RESET] = { SRC_DISP_RCR, BIT(0) },
304
+ [IMX8MP_RESET_GPU2D_RESET] = { SRC_GPU2D_RCR, BIT(0) },
305
+ [IMX8MP_RESET_GPU3D_RESET] = { SRC_GPU3D_RCR, BIT(0) },
306
+ [IMX8MP_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) },
307
+ [IMX8MP_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) },
308
+ [IMX8MP_RESET_VPU_G1_RESET] = { SRC_VPU_G1_RCR, BIT(0) },
309
+ [IMX8MP_RESET_VPU_G2_RESET] = { SRC_VPU_G2_RCR, BIT(0) },
310
+ [IMX8MP_RESET_VPUVC8KE_RESET] = { SRC_VPUVC8KE_RCR, BIT(0) },
311
+ [IMX8MP_RESET_NOC_RESET] = { SRC_NOC_RCR, BIT(0) },
312
+};
313
+
314
+static int imx8mp_reset_set(struct reset_controller_dev *rcdev,
315
+ unsigned long id, bool assert)
316
+{
317
+ struct imx7_src *imx7src = to_imx7_src(rcdev);
318
+ const unsigned int bit = imx7src->signals[id].bit;
319
+ unsigned int value = assert ? bit : 0;
320
+
321
+ switch (id) {
322
+ case IMX8MP_RESET_PCIEPHY:
323
+ /*
324
+ * wait for more than 10us to release phy g_rst and
325
+ * btnrst
326
+ */
327
+ if (!assert)
328
+ udelay(10);
329
+ break;
330
+
331
+ case IMX8MP_RESET_PCIE_CTRL_APPS_EN:
332
+ case IMX8MP_RESET_PCIEPHY_PERST:
333
+ value = assert ? 0 : bit;
334
+ break;
335
+ }
336
+
337
+ return imx7_reset_update(imx7src, id, value);
338
+}
339
+
340
+static int imx8mp_reset_assert(struct reset_controller_dev *rcdev,
341
+ unsigned long id)
342
+{
343
+ return imx8mp_reset_set(rcdev, id, true);
344
+}
345
+
346
+static int imx8mp_reset_deassert(struct reset_controller_dev *rcdev,
347
+ unsigned long id)
348
+{
349
+ return imx8mp_reset_set(rcdev, id, false);
350
+}
351
+
352
+static const struct imx7_src_variant variant_imx8mp = {
353
+ .signals = imx8mp_src_signals,
354
+ .signals_num = ARRAY_SIZE(imx8mp_src_signals),
355
+ .ops = {
356
+ .assert = imx8mp_reset_assert,
357
+ .deassert = imx8mp_reset_deassert,
358
+ },
120359 };
121360
122361 static int imx7_reset_probe(struct platform_device *pdev)
....@@ -124,11 +363,13 @@
124363 struct imx7_src *imx7src;
125364 struct device *dev = &pdev->dev;
126365 struct regmap_config config = { .name = "src" };
366
+ const struct imx7_src_variant *variant = of_device_get_match_data(dev);
127367
128368 imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
129369 if (!imx7src)
130370 return -ENOMEM;
131371
372
+ imx7src->signals = variant->signals;
132373 imx7src->regmap = syscon_node_to_regmap(dev->of_node);
133374 if (IS_ERR(imx7src->regmap)) {
134375 dev_err(dev, "Unable to get imx7-src regmap");
....@@ -137,17 +378,20 @@
137378 regmap_attach_dev(dev, imx7src->regmap, &config);
138379
139380 imx7src->rcdev.owner = THIS_MODULE;
140
- imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
141
- imx7src->rcdev.ops = &imx7_reset_ops;
381
+ imx7src->rcdev.nr_resets = variant->signals_num;
382
+ imx7src->rcdev.ops = &variant->ops;
142383 imx7src->rcdev.of_node = dev->of_node;
143384
144385 return devm_reset_controller_register(dev, &imx7src->rcdev);
145386 }
146387
147388 static const struct of_device_id imx7_reset_dt_ids[] = {
148
- { .compatible = "fsl,imx7d-src", },
389
+ { .compatible = "fsl,imx7d-src", .data = &variant_imx7 },
390
+ { .compatible = "fsl,imx8mq-src", .data = &variant_imx8mq },
391
+ { .compatible = "fsl,imx8mp-src", .data = &variant_imx8mp },
149392 { /* sentinel */ },
150393 };
394
+MODULE_DEVICE_TABLE(of, imx7_reset_dt_ids);
151395
152396 static struct platform_driver imx7_reset_driver = {
153397 .probe = imx7_reset_probe,
....@@ -156,4 +400,8 @@
156400 .of_match_table = imx7_reset_dt_ids,
157401 },
158402 };
159
-builtin_platform_driver(imx7_reset_driver);
403
+module_platform_driver(imx7_reset_driver);
404
+
405
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
406
+MODULE_DESCRIPTION("NXP i.MX7 reset driver");
407
+MODULE_LICENSE("GPL v2");