b53_srab.c (16672B)
1/* 2 * B53 register access through Switch Register Access Bridge Registers 3 * 4 * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <linux/kernel.h> 20#include <linux/module.h> 21#include <linux/delay.h> 22#include <linux/interrupt.h> 23#include <linux/platform_device.h> 24#include <linux/platform_data/b53.h> 25#include <linux/of.h> 26 27#include "b53_priv.h" 28#include "b53_serdes.h" 29 30/* command and status register of the SRAB */ 31#define B53_SRAB_CMDSTAT 0x2c 32#define B53_SRAB_CMDSTAT_RST BIT(2) 33#define B53_SRAB_CMDSTAT_WRITE BIT(1) 34#define B53_SRAB_CMDSTAT_GORDYN BIT(0) 35#define B53_SRAB_CMDSTAT_PAGE 24 36#define B53_SRAB_CMDSTAT_REG 16 37 38/* high order word of write data to switch registe */ 39#define B53_SRAB_WD_H 0x30 40 41/* low order word of write data to switch registe */ 42#define B53_SRAB_WD_L 0x34 43 44/* high order word of read data from switch register */ 45#define B53_SRAB_RD_H 0x38 46 47/* low order word of read data from switch register */ 48#define B53_SRAB_RD_L 0x3c 49 50/* command and status register of the SRAB */ 51#define B53_SRAB_CTRLS 0x40 52#define B53_SRAB_CTRLS_HOST_INTR BIT(1) 53#define B53_SRAB_CTRLS_RCAREQ BIT(3) 54#define B53_SRAB_CTRLS_RCAGNT BIT(4) 55#define B53_SRAB_CTRLS_SW_INIT_DONE BIT(6) 56 57/* the register captures interrupt pulses from the switch */ 58#define B53_SRAB_INTR 0x44 59#define B53_SRAB_INTR_P(x) BIT(x) 60#define B53_SRAB_SWITCH_PHY BIT(8) 61#define B53_SRAB_1588_SYNC BIT(9) 62#define B53_SRAB_IMP1_SLEEP_TIMER BIT(10) 63#define B53_SRAB_P7_SLEEP_TIMER BIT(11) 64#define B53_SRAB_IMP0_SLEEP_TIMER BIT(12) 65 66/* Port mux configuration registers */ 67#define B53_MUX_CONFIG_P5 0x00 68#define MUX_CONFIG_SGMII 0 69#define MUX_CONFIG_MII_LITE 1 70#define MUX_CONFIG_RGMII 2 71#define MUX_CONFIG_GMII 3 72#define MUX_CONFIG_GPHY 4 73#define MUX_CONFIG_INTERNAL 5 74#define MUX_CONFIG_MASK 0x7 75#define B53_MUX_CONFIG_P4 0x04 76 77struct b53_srab_port_priv { 78 int irq; 79 bool irq_enabled; 80 struct b53_device *dev; 81 unsigned int num; 82 phy_interface_t mode; 83}; 84 85struct b53_srab_priv { 86 void __iomem *regs; 87 void __iomem *mux_config; 88 struct b53_srab_port_priv port_intrs[B53_N_PORTS]; 89}; 90 91static int b53_srab_request_grant(struct b53_device *dev) 92{ 93 struct b53_srab_priv *priv = dev->priv; 94 u8 __iomem *regs = priv->regs; 95 u32 ctrls; 96 int i; 97 98 ctrls = readl(regs + B53_SRAB_CTRLS); 99 ctrls |= B53_SRAB_CTRLS_RCAREQ; 100 writel(ctrls, regs + B53_SRAB_CTRLS); 101 102 for (i = 0; i < 20; i++) { 103 ctrls = readl(regs + B53_SRAB_CTRLS); 104 if (ctrls & B53_SRAB_CTRLS_RCAGNT) 105 break; 106 usleep_range(10, 100); 107 } 108 if (WARN_ON(i == 5)) 109 return -EIO; 110 111 return 0; 112} 113 114static void b53_srab_release_grant(struct b53_device *dev) 115{ 116 struct b53_srab_priv *priv = dev->priv; 117 u8 __iomem *regs = priv->regs; 118 u32 ctrls; 119 120 ctrls = readl(regs + B53_SRAB_CTRLS); 121 ctrls &= ~B53_SRAB_CTRLS_RCAREQ; 122 writel(ctrls, regs + B53_SRAB_CTRLS); 123} 124 125static int b53_srab_op(struct b53_device *dev, u8 page, u8 reg, u32 op) 126{ 127 struct b53_srab_priv *priv = dev->priv; 128 u8 __iomem *regs = priv->regs; 129 int i; 130 u32 cmdstat; 131 132 /* set register address */ 133 cmdstat = (page << B53_SRAB_CMDSTAT_PAGE) | 134 (reg << B53_SRAB_CMDSTAT_REG) | 135 B53_SRAB_CMDSTAT_GORDYN | 136 op; 137 writel(cmdstat, regs + B53_SRAB_CMDSTAT); 138 139 /* check if operation completed */ 140 for (i = 0; i < 5; ++i) { 141 cmdstat = readl(regs + B53_SRAB_CMDSTAT); 142 if (!(cmdstat & B53_SRAB_CMDSTAT_GORDYN)) 143 break; 144 usleep_range(10, 100); 145 } 146 147 if (WARN_ON(i == 5)) 148 return -EIO; 149 150 return 0; 151} 152 153static int b53_srab_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) 154{ 155 struct b53_srab_priv *priv = dev->priv; 156 u8 __iomem *regs = priv->regs; 157 int ret = 0; 158 159 ret = b53_srab_request_grant(dev); 160 if (ret) 161 goto err; 162 163 ret = b53_srab_op(dev, page, reg, 0); 164 if (ret) 165 goto err; 166 167 *val = readl(regs + B53_SRAB_RD_L) & 0xff; 168 169err: 170 b53_srab_release_grant(dev); 171 172 return ret; 173} 174 175static int b53_srab_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) 176{ 177 struct b53_srab_priv *priv = dev->priv; 178 u8 __iomem *regs = priv->regs; 179 int ret = 0; 180 181 ret = b53_srab_request_grant(dev); 182 if (ret) 183 goto err; 184 185 ret = b53_srab_op(dev, page, reg, 0); 186 if (ret) 187 goto err; 188 189 *val = readl(regs + B53_SRAB_RD_L) & 0xffff; 190 191err: 192 b53_srab_release_grant(dev); 193 194 return ret; 195} 196 197static int b53_srab_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) 198{ 199 struct b53_srab_priv *priv = dev->priv; 200 u8 __iomem *regs = priv->regs; 201 int ret = 0; 202 203 ret = b53_srab_request_grant(dev); 204 if (ret) 205 goto err; 206 207 ret = b53_srab_op(dev, page, reg, 0); 208 if (ret) 209 goto err; 210 211 *val = readl(regs + B53_SRAB_RD_L); 212 213err: 214 b53_srab_release_grant(dev); 215 216 return ret; 217} 218 219static int b53_srab_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) 220{ 221 struct b53_srab_priv *priv = dev->priv; 222 u8 __iomem *regs = priv->regs; 223 int ret = 0; 224 225 ret = b53_srab_request_grant(dev); 226 if (ret) 227 goto err; 228 229 ret = b53_srab_op(dev, page, reg, 0); 230 if (ret) 231 goto err; 232 233 *val = readl(regs + B53_SRAB_RD_L); 234 *val += ((u64)readl(regs + B53_SRAB_RD_H) & 0xffff) << 32; 235 236err: 237 b53_srab_release_grant(dev); 238 239 return ret; 240} 241 242static int b53_srab_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) 243{ 244 struct b53_srab_priv *priv = dev->priv; 245 u8 __iomem *regs = priv->regs; 246 int ret = 0; 247 248 ret = b53_srab_request_grant(dev); 249 if (ret) 250 goto err; 251 252 ret = b53_srab_op(dev, page, reg, 0); 253 if (ret) 254 goto err; 255 256 *val = readl(regs + B53_SRAB_RD_L); 257 *val += (u64)readl(regs + B53_SRAB_RD_H) << 32; 258 259err: 260 b53_srab_release_grant(dev); 261 262 return ret; 263} 264 265static int b53_srab_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) 266{ 267 struct b53_srab_priv *priv = dev->priv; 268 u8 __iomem *regs = priv->regs; 269 int ret = 0; 270 271 ret = b53_srab_request_grant(dev); 272 if (ret) 273 goto err; 274 275 writel(value, regs + B53_SRAB_WD_L); 276 277 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); 278 279err: 280 b53_srab_release_grant(dev); 281 282 return ret; 283} 284 285static int b53_srab_write16(struct b53_device *dev, u8 page, u8 reg, 286 u16 value) 287{ 288 struct b53_srab_priv *priv = dev->priv; 289 u8 __iomem *regs = priv->regs; 290 int ret = 0; 291 292 ret = b53_srab_request_grant(dev); 293 if (ret) 294 goto err; 295 296 writel(value, regs + B53_SRAB_WD_L); 297 298 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); 299 300err: 301 b53_srab_release_grant(dev); 302 303 return ret; 304} 305 306static int b53_srab_write32(struct b53_device *dev, u8 page, u8 reg, 307 u32 value) 308{ 309 struct b53_srab_priv *priv = dev->priv; 310 u8 __iomem *regs = priv->regs; 311 int ret = 0; 312 313 ret = b53_srab_request_grant(dev); 314 if (ret) 315 goto err; 316 317 writel(value, regs + B53_SRAB_WD_L); 318 319 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); 320 321err: 322 b53_srab_release_grant(dev); 323 324 return ret; 325} 326 327static int b53_srab_write48(struct b53_device *dev, u8 page, u8 reg, 328 u64 value) 329{ 330 struct b53_srab_priv *priv = dev->priv; 331 u8 __iomem *regs = priv->regs; 332 int ret = 0; 333 334 ret = b53_srab_request_grant(dev); 335 if (ret) 336 goto err; 337 338 writel((u32)value, regs + B53_SRAB_WD_L); 339 writel((u16)(value >> 32), regs + B53_SRAB_WD_H); 340 341 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); 342 343err: 344 b53_srab_release_grant(dev); 345 346 return ret; 347} 348 349static int b53_srab_write64(struct b53_device *dev, u8 page, u8 reg, 350 u64 value) 351{ 352 struct b53_srab_priv *priv = dev->priv; 353 u8 __iomem *regs = priv->regs; 354 int ret = 0; 355 356 ret = b53_srab_request_grant(dev); 357 if (ret) 358 goto err; 359 360 writel((u32)value, regs + B53_SRAB_WD_L); 361 writel((u32)(value >> 32), regs + B53_SRAB_WD_H); 362 363 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); 364 365err: 366 b53_srab_release_grant(dev); 367 368 return ret; 369} 370 371static irqreturn_t b53_srab_port_thread(int irq, void *dev_id) 372{ 373 struct b53_srab_port_priv *port = dev_id; 374 struct b53_device *dev = port->dev; 375 376 if (port->mode == PHY_INTERFACE_MODE_SGMII) 377 b53_port_event(dev->ds, port->num); 378 379 return IRQ_HANDLED; 380} 381 382static irqreturn_t b53_srab_port_isr(int irq, void *dev_id) 383{ 384 struct b53_srab_port_priv *port = dev_id; 385 struct b53_device *dev = port->dev; 386 struct b53_srab_priv *priv = dev->priv; 387 388 /* Acknowledge the interrupt */ 389 writel(BIT(port->num), priv->regs + B53_SRAB_INTR); 390 391 return IRQ_WAKE_THREAD; 392} 393 394#if IS_ENABLED(CONFIG_B53_SERDES) 395static u8 b53_srab_serdes_map_lane(struct b53_device *dev, int port) 396{ 397 struct b53_srab_priv *priv = dev->priv; 398 struct b53_srab_port_priv *p = &priv->port_intrs[port]; 399 400 if (p->mode != PHY_INTERFACE_MODE_SGMII) 401 return B53_INVALID_LANE; 402 403 switch (port) { 404 case 5: 405 return 0; 406 case 4: 407 return 1; 408 default: 409 return B53_INVALID_LANE; 410 } 411} 412#endif 413 414static int b53_srab_irq_enable(struct b53_device *dev, int port) 415{ 416 struct b53_srab_priv *priv = dev->priv; 417 struct b53_srab_port_priv *p = &priv->port_intrs[port]; 418 int ret = 0; 419 420 /* Interrupt is optional and was not specified, do not make 421 * this fatal 422 */ 423 if (p->irq == -ENXIO) 424 return ret; 425 426 ret = request_threaded_irq(p->irq, b53_srab_port_isr, 427 b53_srab_port_thread, 0, 428 dev_name(dev->dev), p); 429 if (!ret) 430 p->irq_enabled = true; 431 432 return ret; 433} 434 435static void b53_srab_irq_disable(struct b53_device *dev, int port) 436{ 437 struct b53_srab_priv *priv = dev->priv; 438 struct b53_srab_port_priv *p = &priv->port_intrs[port]; 439 440 if (p->irq_enabled) { 441 free_irq(p->irq, p); 442 p->irq_enabled = false; 443 } 444} 445 446static void b53_srab_phylink_get_caps(struct b53_device *dev, int port, 447 struct phylink_config *config) 448{ 449 struct b53_srab_priv *priv = dev->priv; 450 struct b53_srab_port_priv *p = &priv->port_intrs[port]; 451 452 switch (p->mode) { 453 case PHY_INTERFACE_MODE_SGMII: 454#if IS_ENABLED(CONFIG_B53_SERDES) 455 /* If p->mode indicates SGMII mode, that essentially means we 456 * are using a serdes. As the serdes for the capabilities. 457 */ 458 b53_serdes_phylink_get_caps(dev, port, config); 459#endif 460 break; 461 462 case PHY_INTERFACE_MODE_NA: 463 break; 464 465 case PHY_INTERFACE_MODE_RGMII: 466 /* If we support RGMII, support all RGMII modes, since 467 * that dictates the PHY delay settings. 468 */ 469 phy_interface_set_rgmii(config->supported_interfaces); 470 break; 471 472 default: 473 /* Some other mode (e.g. MII, GMII etc) */ 474 __set_bit(p->mode, config->supported_interfaces); 475 break; 476 } 477} 478 479static const struct b53_io_ops b53_srab_ops = { 480 .read8 = b53_srab_read8, 481 .read16 = b53_srab_read16, 482 .read32 = b53_srab_read32, 483 .read48 = b53_srab_read48, 484 .read64 = b53_srab_read64, 485 .write8 = b53_srab_write8, 486 .write16 = b53_srab_write16, 487 .write32 = b53_srab_write32, 488 .write48 = b53_srab_write48, 489 .write64 = b53_srab_write64, 490 .irq_enable = b53_srab_irq_enable, 491 .irq_disable = b53_srab_irq_disable, 492 .phylink_get_caps = b53_srab_phylink_get_caps, 493#if IS_ENABLED(CONFIG_B53_SERDES) 494 .phylink_mac_select_pcs = b53_serdes_phylink_mac_select_pcs, 495 .serdes_map_lane = b53_srab_serdes_map_lane, 496 .serdes_link_set = b53_serdes_link_set, 497#endif 498}; 499 500static const struct of_device_id b53_srab_of_match[] = { 501 { .compatible = "brcm,bcm53010-srab" }, 502 { .compatible = "brcm,bcm53011-srab" }, 503 { .compatible = "brcm,bcm53012-srab" }, 504 { .compatible = "brcm,bcm53018-srab" }, 505 { .compatible = "brcm,bcm53019-srab" }, 506 { .compatible = "brcm,bcm5301x-srab" }, 507 { .compatible = "brcm,bcm11360-srab", .data = (void *)BCM583XX_DEVICE_ID }, 508 { .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID }, 509 { .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID }, 510 { .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID }, 511 { .compatible = "brcm,bcm58622-srab", .data = (void *)BCM58XX_DEVICE_ID }, 512 { .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID }, 513 { .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID }, 514 { .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID }, 515 { .compatible = "brcm,cygnus-srab", .data = (void *)BCM583XX_DEVICE_ID }, 516 { .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID }, 517 { .compatible = "brcm,omega-srab", .data = (void *)BCM583XX_DEVICE_ID }, 518 { /* sentinel */ }, 519}; 520MODULE_DEVICE_TABLE(of, b53_srab_of_match); 521 522static void b53_srab_intr_set(struct b53_srab_priv *priv, bool set) 523{ 524 u32 reg; 525 526 reg = readl(priv->regs + B53_SRAB_CTRLS); 527 if (set) 528 reg |= B53_SRAB_CTRLS_HOST_INTR; 529 else 530 reg &= ~B53_SRAB_CTRLS_HOST_INTR; 531 writel(reg, priv->regs + B53_SRAB_CTRLS); 532} 533 534static void b53_srab_prepare_irq(struct platform_device *pdev) 535{ 536 struct b53_device *dev = platform_get_drvdata(pdev); 537 struct b53_srab_priv *priv = dev->priv; 538 struct b53_srab_port_priv *port; 539 unsigned int i; 540 char *name; 541 542 /* Clear all pending interrupts */ 543 writel(0xffffffff, priv->regs + B53_SRAB_INTR); 544 545 for (i = 0; i < B53_N_PORTS; i++) { 546 port = &priv->port_intrs[i]; 547 548 /* There is no port 6 */ 549 if (i == 6) 550 continue; 551 552 name = kasprintf(GFP_KERNEL, "link_state_p%d", i); 553 if (!name) 554 return; 555 556 port->num = i; 557 port->dev = dev; 558 port->irq = platform_get_irq_byname_optional(pdev, name); 559 kfree(name); 560 } 561 562 b53_srab_intr_set(priv, true); 563} 564 565static void b53_srab_mux_init(struct platform_device *pdev) 566{ 567 struct b53_device *dev = platform_get_drvdata(pdev); 568 struct b53_srab_priv *priv = dev->priv; 569 struct b53_srab_port_priv *p; 570 unsigned int port; 571 u32 reg, off = 0; 572 int ret; 573 574 if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID) 575 return; 576 577 priv->mux_config = devm_platform_ioremap_resource(pdev, 1); 578 if (IS_ERR(priv->mux_config)) 579 return; 580 581 /* Obtain the port mux configuration so we know which lanes 582 * actually map to SerDes lanes 583 */ 584 for (port = 5; port > 3; port--, off += 4) { 585 p = &priv->port_intrs[port]; 586 587 reg = readl(priv->mux_config + B53_MUX_CONFIG_P5 + off); 588 switch (reg & MUX_CONFIG_MASK) { 589 case MUX_CONFIG_SGMII: 590 p->mode = PHY_INTERFACE_MODE_SGMII; 591 ret = b53_serdes_init(dev, port); 592 if (ret) 593 continue; 594 break; 595 case MUX_CONFIG_MII_LITE: 596 p->mode = PHY_INTERFACE_MODE_MII; 597 break; 598 case MUX_CONFIG_GMII: 599 p->mode = PHY_INTERFACE_MODE_GMII; 600 break; 601 case MUX_CONFIG_RGMII: 602 p->mode = PHY_INTERFACE_MODE_RGMII; 603 break; 604 case MUX_CONFIG_INTERNAL: 605 p->mode = PHY_INTERFACE_MODE_INTERNAL; 606 break; 607 default: 608 p->mode = PHY_INTERFACE_MODE_NA; 609 break; 610 } 611 612 if (p->mode != PHY_INTERFACE_MODE_NA) 613 dev_info(&pdev->dev, "Port %d mode: %s\n", 614 port, phy_modes(p->mode)); 615 } 616} 617 618static int b53_srab_probe(struct platform_device *pdev) 619{ 620 struct b53_platform_data *pdata = pdev->dev.platform_data; 621 struct device_node *dn = pdev->dev.of_node; 622 const struct of_device_id *of_id = NULL; 623 struct b53_srab_priv *priv; 624 struct b53_device *dev; 625 626 if (dn) 627 of_id = of_match_node(b53_srab_of_match, dn); 628 629 if (of_id) { 630 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 631 if (!pdata) 632 return -ENOMEM; 633 634 pdata->chip_id = (u32)(unsigned long)of_id->data; 635 } 636 637 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 638 if (!priv) 639 return -ENOMEM; 640 641 priv->regs = devm_platform_ioremap_resource(pdev, 0); 642 if (IS_ERR(priv->regs)) 643 return PTR_ERR(priv->regs); 644 645 dev = b53_switch_alloc(&pdev->dev, &b53_srab_ops, priv); 646 if (!dev) 647 return -ENOMEM; 648 649 if (pdata) 650 dev->pdata = pdata; 651 652 platform_set_drvdata(pdev, dev); 653 654 b53_srab_prepare_irq(pdev); 655 b53_srab_mux_init(pdev); 656 657 return b53_switch_register(dev); 658} 659 660static int b53_srab_remove(struct platform_device *pdev) 661{ 662 struct b53_device *dev = platform_get_drvdata(pdev); 663 664 if (!dev) 665 return 0; 666 667 b53_srab_intr_set(dev->priv, false); 668 b53_switch_remove(dev); 669 670 platform_set_drvdata(pdev, NULL); 671 672 return 0; 673} 674 675static void b53_srab_shutdown(struct platform_device *pdev) 676{ 677 struct b53_device *dev = platform_get_drvdata(pdev); 678 679 if (!dev) 680 return; 681 682 b53_switch_shutdown(dev); 683 684 platform_set_drvdata(pdev, NULL); 685} 686 687static struct platform_driver b53_srab_driver = { 688 .probe = b53_srab_probe, 689 .remove = b53_srab_remove, 690 .shutdown = b53_srab_shutdown, 691 .driver = { 692 .name = "b53-srab-switch", 693 .of_match_table = b53_srab_of_match, 694 }, 695}; 696 697module_platform_driver(b53_srab_driver); 698MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); 699MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver"); 700MODULE_LICENSE("Dual BSD/GPL");