1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * GPIO driver for the ACCES PCIe-IDIO-24 family 4 * Copyright (C) 2018 William Breathitt Gray 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * This driver supports the following ACCES devices: PCIe-IDIO-24, 16 * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12. 17 */ 18 #include <linux/bitmap.h> 19 #include <linux/bitops.h> 20 #include <linux/device.h> 21 #include <linux/errno.h> 22 #include <linux/gpio/driver.h> 23 #include <linux/interrupt.h> 24 #include <linux/irqdesc.h> 25 #include <linux/kernel.h> 26 #include <linux/module.h> 27 #include <linux/pci.h> 28 #include <linux/spinlock.h> 29 #include <linux/types.h> 30 31 /* 32 * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status 33 * 34 * Bit: Description 35 * 0: Enable Interrupt Sources (Bit 0) 36 * 1: Enable Interrupt Sources (Bit 1) 37 * 2: Generate Internal PCI Bus Internal SERR# Interrupt 38 * 3: Mailbox Interrupt Enable 39 * 4: Power Management Interrupt Enable 40 * 5: Power Management Interrupt 41 * 6: Slave Read Local Data Parity Check Error Enable 42 * 7: Slave Read Local Data Parity Check Error Status 43 * 8: Internal PCI Wire Interrupt Enable 44 * 9: PCI Express Doorbell Interrupt Enable 45 * 10: PCI Abort Interrupt Enable 46 * 11: Local Interrupt Input Enable 47 * 12: Retry Abort Enable 48 * 13: PCI Express Doorbell Interrupt Active 49 * 14: PCI Abort Interrupt Active 50 * 15: Local Interrupt Input Active 51 * 16: Local Interrupt Output Enable 52 * 17: Local Doorbell Interrupt Enable 53 * 18: DMA Channel 0 Interrupt Enable 54 * 19: DMA Channel 1 Interrupt Enable 55 * 20: Local Doorbell Interrupt Active 56 * 21: DMA Channel 0 Interrupt Active 57 * 22: DMA Channel 1 Interrupt Active 58 * 23: Built-In Self-Test (BIST) Interrupt Active 59 * 24: Direct Master was the Bus Master during a Master or Target Abort 60 * 25: DMA Channel 0 was the Bus Master during a Master or Target Abort 61 * 26: DMA Channel 1 was the Bus Master during a Master or Target Abort 62 * 27: Target Abort after internal 256 consecutive Master Retrys 63 * 28: PCI Bus wrote data to LCS_MBOX0 64 * 29: PCI Bus wrote data to LCS_MBOX1 65 * 30: PCI Bus wrote data to LCS_MBOX2 66 * 31: PCI Bus wrote data to LCS_MBOX3 67 */ 68 #define PLX_PEX8311_PCI_LCS_INTCSR 0x68 69 #define INTCSR_INTERNAL_PCI_WIRE BIT(8) 70 #define INTCSR_LOCAL_INPUT BIT(11) 71 72 /** 73 * struct idio_24_gpio_reg - GPIO device registers structure 74 * @out0_7: Read: FET Outputs 0-7 75 * Write: FET Outputs 0-7 76 * @out8_15: Read: FET Outputs 8-15 77 * Write: FET Outputs 8-15 78 * @out16_23: Read: FET Outputs 16-23 79 * Write: FET Outputs 16-23 80 * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7 81 * Write: TTL/CMOS Outputs 0-7 82 * @in0_7: Read: Isolated Inputs 0-7 83 * Write: Reserved 84 * @in8_15: Read: Isolated Inputs 8-15 85 * Write: Reserved 86 * @in16_23: Read: Isolated Inputs 16-23 87 * Write: Reserved 88 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7 89 * Write: Reserved 90 * @cos0_7: Read: COS Status Inputs 0-7 91 * Write: COS Clear Inputs 0-7 92 * @cos8_15: Read: COS Status Inputs 8-15 93 * Write: COS Clear Inputs 8-15 94 * @cos16_23: Read: COS Status Inputs 16-23 95 * Write: COS Clear Inputs 16-23 96 * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7 97 * Write: COS Clear TTL/CMOS 0-7 98 * @ctl: Read: Control Register 99 * Write: Control Register 100 * @reserved: Read: Reserved 101 * Write: Reserved 102 * @cos_enable: Read: COS Enable 103 * Write: COS Enable 104 * @soft_reset: Read: IRQ Output Pin Status 105 * Write: Software Board Reset 106 */ 107 struct idio_24_gpio_reg { 108 u8 out0_7; 109 u8 out8_15; 110 u8 out16_23; 111 u8 ttl_out0_7; 112 u8 in0_7; 113 u8 in8_15; 114 u8 in16_23; 115 u8 ttl_in0_7; 116 u8 cos0_7; 117 u8 cos8_15; 118 u8 cos16_23; 119 u8 cos_ttl0_7; 120 u8 ctl; 121 u8 reserved; 122 u8 cos_enable; 123 u8 soft_reset; 124 }; 125 126 /** 127 * struct idio_24_gpio - GPIO device private data structure 128 * @chip: instance of the gpio_chip 129 * @lock: synchronization lock to prevent I/O race conditions 130 * @reg: I/O address offset for the GPIO device registers 131 * @irq_mask: I/O bits affected by interrupts 132 */ 133 struct idio_24_gpio { 134 struct gpio_chip chip; 135 raw_spinlock_t lock; 136 __u8 __iomem *plx; 137 struct idio_24_gpio_reg __iomem *reg; 138 unsigned long irq_mask; 139 }; 140 141 static int idio_24_gpio_get_direction(struct gpio_chip *chip, 142 unsigned int offset) 143 { 144 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 145 const unsigned long out_mode_mask = BIT(1); 146 147 /* FET Outputs */ 148 if (offset < 24) 149 return GPIO_LINE_DIRECTION_OUT; 150 151 /* Isolated Inputs */ 152 if (offset < 48) 153 return GPIO_LINE_DIRECTION_IN; 154 155 /* TTL/CMOS I/O */ 156 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */ 157 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 158 return GPIO_LINE_DIRECTION_OUT; 159 160 return GPIO_LINE_DIRECTION_IN; 161 } 162 163 static int idio_24_gpio_direction_input(struct gpio_chip *chip, 164 unsigned int offset) 165 { 166 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 167 unsigned long flags; 168 unsigned int ctl_state; 169 const unsigned long out_mode_mask = BIT(1); 170 171 /* TTL/CMOS I/O */ 172 if (offset > 47) { 173 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 174 175 /* Clear TTL/CMOS Output Mode */ 176 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask; 177 iowrite8(ctl_state, &idio24gpio->reg->ctl); 178 179 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 180 } 181 182 return 0; 183 } 184 185 static int idio_24_gpio_direction_output(struct gpio_chip *chip, 186 unsigned int offset, int value) 187 { 188 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 189 unsigned long flags; 190 unsigned int ctl_state; 191 const unsigned long out_mode_mask = BIT(1); 192 193 /* TTL/CMOS I/O */ 194 if (offset > 47) { 195 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 196 197 /* Set TTL/CMOS Output Mode */ 198 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask; 199 iowrite8(ctl_state, &idio24gpio->reg->ctl); 200 201 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 202 } 203 204 chip->set(chip, offset, value); 205 return 0; 206 } 207 208 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset) 209 { 210 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 211 const unsigned long offset_mask = BIT(offset % 8); 212 const unsigned long out_mode_mask = BIT(1); 213 214 /* FET Outputs */ 215 if (offset < 8) 216 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask); 217 218 if (offset < 16) 219 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask); 220 221 if (offset < 24) 222 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask); 223 224 /* Isolated Inputs */ 225 if (offset < 32) 226 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask); 227 228 if (offset < 40) 229 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask); 230 231 if (offset < 48) 232 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask); 233 234 /* TTL/CMOS Outputs */ 235 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 236 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask); 237 238 /* TTL/CMOS Inputs */ 239 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask); 240 } 241 242 static int idio_24_gpio_get_multiple(struct gpio_chip *chip, 243 unsigned long *mask, unsigned long *bits) 244 { 245 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 246 unsigned long offset; 247 unsigned long gpio_mask; 248 void __iomem *ports[] = { 249 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, 250 &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7, 251 &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23, 252 }; 253 size_t index; 254 unsigned long port_state; 255 const unsigned long out_mode_mask = BIT(1); 256 257 /* clear bits array to a clean slate */ 258 bitmap_zero(bits, chip->ngpio); 259 260 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 261 index = offset / 8; 262 263 /* read bits from current gpio port (port 6 is TTL GPIO) */ 264 if (index < 6) 265 port_state = ioread8(ports[index]); 266 else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 267 port_state = ioread8(&idio24gpio->reg->ttl_out0_7); 268 else 269 port_state = ioread8(&idio24gpio->reg->ttl_in0_7); 270 271 port_state &= gpio_mask; 272 273 bitmap_set_value8(bits, port_state, offset); 274 } 275 276 return 0; 277 } 278 279 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, 280 int value) 281 { 282 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 283 const unsigned long out_mode_mask = BIT(1); 284 void __iomem *base; 285 const unsigned int mask = BIT(offset % 8); 286 unsigned long flags; 287 unsigned int out_state; 288 289 /* Isolated Inputs */ 290 if (offset > 23 && offset < 48) 291 return; 292 293 /* TTL/CMOS Inputs */ 294 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask)) 295 return; 296 297 /* TTL/CMOS Outputs */ 298 if (offset > 47) 299 base = &idio24gpio->reg->ttl_out0_7; 300 /* FET Outputs */ 301 else if (offset > 15) 302 base = &idio24gpio->reg->out16_23; 303 else if (offset > 7) 304 base = &idio24gpio->reg->out8_15; 305 else 306 base = &idio24gpio->reg->out0_7; 307 308 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 309 310 if (value) 311 out_state = ioread8(base) | mask; 312 else 313 out_state = ioread8(base) & ~mask; 314 315 iowrite8(out_state, base); 316 317 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 318 } 319 320 static void idio_24_gpio_set_multiple(struct gpio_chip *chip, 321 unsigned long *mask, unsigned long *bits) 322 { 323 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 324 unsigned long offset; 325 unsigned long gpio_mask; 326 void __iomem *ports[] = { 327 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, 328 &idio24gpio->reg->out16_23 329 }; 330 size_t index; 331 unsigned long bitmask; 332 unsigned long flags; 333 unsigned long out_state; 334 const unsigned long out_mode_mask = BIT(1); 335 336 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 337 index = offset / 8; 338 339 bitmask = bitmap_get_value8(bits, offset) & gpio_mask; 340 341 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 342 343 /* read bits from current gpio port (port 6 is TTL GPIO) */ 344 if (index < 6) { 345 out_state = ioread8(ports[index]); 346 } else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) { 347 out_state = ioread8(&idio24gpio->reg->ttl_out0_7); 348 } else { 349 /* skip TTL GPIO if set for input */ 350 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 351 continue; 352 } 353 354 /* set requested bit states */ 355 out_state &= ~gpio_mask; 356 out_state |= bitmask; 357 358 /* write bits for current gpio port (port 6 is TTL GPIO) */ 359 if (index < 6) 360 iowrite8(out_state, ports[index]); 361 else 362 iowrite8(out_state, &idio24gpio->reg->ttl_out0_7); 363 364 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 365 } 366 } 367 368 static void idio_24_irq_ack(struct irq_data *data) 369 { 370 } 371 372 static void idio_24_irq_mask(struct irq_data *data) 373 { 374 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); 375 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 376 unsigned long flags; 377 const unsigned long bit_offset = irqd_to_hwirq(data) - 24; 378 unsigned char new_irq_mask; 379 const unsigned long bank_offset = bit_offset / 8; 380 unsigned char cos_enable_state; 381 382 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 383 384 idio24gpio->irq_mask &= ~BIT(bit_offset); 385 new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; 386 387 if (!new_irq_mask) { 388 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); 389 390 /* Disable Rising Edge detection */ 391 cos_enable_state &= ~BIT(bank_offset); 392 /* Disable Falling Edge detection */ 393 cos_enable_state &= ~BIT(bank_offset + 4); 394 395 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); 396 } 397 398 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 399 } 400 401 static void idio_24_irq_unmask(struct irq_data *data) 402 { 403 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); 404 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 405 unsigned long flags; 406 unsigned char prev_irq_mask; 407 const unsigned long bit_offset = irqd_to_hwirq(data) - 24; 408 const unsigned long bank_offset = bit_offset / 8; 409 unsigned char cos_enable_state; 410 411 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 412 413 prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; 414 idio24gpio->irq_mask |= BIT(bit_offset); 415 416 if (!prev_irq_mask) { 417 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); 418 419 /* Enable Rising Edge detection */ 420 cos_enable_state |= BIT(bank_offset); 421 /* Enable Falling Edge detection */ 422 cos_enable_state |= BIT(bank_offset + 4); 423 424 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); 425 } 426 427 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 428 } 429 430 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type) 431 { 432 /* The only valid irq types are none and both-edges */ 433 if (flow_type != IRQ_TYPE_NONE && 434 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) 435 return -EINVAL; 436 437 return 0; 438 } 439 440 static struct irq_chip idio_24_irqchip = { 441 .name = "pcie-idio-24", 442 .irq_ack = idio_24_irq_ack, 443 .irq_mask = idio_24_irq_mask, 444 .irq_unmask = idio_24_irq_unmask, 445 .irq_set_type = idio_24_irq_set_type 446 }; 447 448 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id) 449 { 450 struct idio_24_gpio *const idio24gpio = dev_id; 451 unsigned long irq_status; 452 struct gpio_chip *const chip = &idio24gpio->chip; 453 unsigned long irq_mask; 454 int gpio; 455 456 raw_spin_lock(&idio24gpio->lock); 457 458 /* Read Change-Of-State status */ 459 irq_status = ioread32(&idio24gpio->reg->cos0_7); 460 461 raw_spin_unlock(&idio24gpio->lock); 462 463 /* Make sure our device generated IRQ */ 464 if (!irq_status) 465 return IRQ_NONE; 466 467 /* Handle only unmasked IRQ */ 468 irq_mask = idio24gpio->irq_mask & irq_status; 469 470 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24) 471 generic_handle_irq(irq_find_mapping(chip->irq.domain, 472 gpio + 24)); 473 474 raw_spin_lock(&idio24gpio->lock); 475 476 /* Clear Change-Of-State status */ 477 iowrite32(irq_status, &idio24gpio->reg->cos0_7); 478 479 raw_spin_unlock(&idio24gpio->lock); 480 481 return IRQ_HANDLED; 482 } 483 484 #define IDIO_24_NGPIO 56 485 static const char *idio_24_names[IDIO_24_NGPIO] = { 486 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", 487 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", 488 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23", 489 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", 490 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15", 491 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23", 492 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7" 493 }; 494 495 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) 496 { 497 struct device *const dev = &pdev->dev; 498 struct idio_24_gpio *idio24gpio; 499 int err; 500 const size_t pci_plx_bar_index = 1; 501 const size_t pci_bar_index = 2; 502 const char *const name = pci_name(pdev); 503 struct gpio_irq_chip *girq; 504 505 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL); 506 if (!idio24gpio) 507 return -ENOMEM; 508 509 err = pcim_enable_device(pdev); 510 if (err) { 511 dev_err(dev, "Failed to enable PCI device (%d)\n", err); 512 return err; 513 } 514 515 err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name); 516 if (err) { 517 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err); 518 return err; 519 } 520 521 idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index]; 522 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; 523 524 idio24gpio->chip.label = name; 525 idio24gpio->chip.parent = dev; 526 idio24gpio->chip.owner = THIS_MODULE; 527 idio24gpio->chip.base = -1; 528 idio24gpio->chip.ngpio = IDIO_24_NGPIO; 529 idio24gpio->chip.names = idio_24_names; 530 idio24gpio->chip.get_direction = idio_24_gpio_get_direction; 531 idio24gpio->chip.direction_input = idio_24_gpio_direction_input; 532 idio24gpio->chip.direction_output = idio_24_gpio_direction_output; 533 idio24gpio->chip.get = idio_24_gpio_get; 534 idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple; 535 idio24gpio->chip.set = idio_24_gpio_set; 536 idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple; 537 538 girq = &idio24gpio->chip.irq; 539 girq->chip = &idio_24_irqchip; 540 /* This will let us handle the parent IRQ in the driver */ 541 girq->parent_handler = NULL; 542 girq->num_parents = 0; 543 girq->parents = NULL; 544 girq->default_type = IRQ_TYPE_NONE; 545 girq->handler = handle_edge_irq; 546 547 raw_spin_lock_init(&idio24gpio->lock); 548 549 /* Software board reset */ 550 iowrite8(0, &idio24gpio->reg->soft_reset); 551 /* 552 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt 553 * input 554 */ 555 iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8, 556 idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1); 557 558 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio); 559 if (err) { 560 dev_err(dev, "GPIO registering failed (%d)\n", err); 561 return err; 562 } 563 564 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED, 565 name, idio24gpio); 566 if (err) { 567 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 568 return err; 569 } 570 571 return 0; 572 } 573 574 static const struct pci_device_id idio_24_pci_dev_id[] = { 575 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) }, 576 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) }, 577 { 0 } 578 }; 579 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id); 580 581 static struct pci_driver idio_24_driver = { 582 .name = "pcie-idio-24", 583 .id_table = idio_24_pci_dev_id, 584 .probe = idio_24_probe 585 }; 586 587 module_pci_driver(idio_24_driver); 588 589 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 590 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver"); 591 MODULE_LICENSE("GPL v2"); 592