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 77 struct 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 85 struct 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 91 static 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 114 static 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 125 static 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 153 static 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 169 err: 170 b53_srab_release_grant(dev); 171 172 return ret; 173 } 174 175 static 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 191 err: 192 b53_srab_release_grant(dev); 193 194 return ret; 195 } 196 197 static 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 213 err: 214 b53_srab_release_grant(dev); 215 216 return ret; 217 } 218 219 static 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 236 err: 237 b53_srab_release_grant(dev); 238 239 return ret; 240 } 241 242 static 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 259 err: 260 b53_srab_release_grant(dev); 261 262 return ret; 263 } 264 265 static 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 279 err: 280 b53_srab_release_grant(dev); 281 282 return ret; 283 } 284 285 static 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 300 err: 301 b53_srab_release_grant(dev); 302 303 return ret; 304 } 305 306 static 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 321 err: 322 b53_srab_release_grant(dev); 323 324 return ret; 325 } 326 327 static 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 343 err: 344 b53_srab_release_grant(dev); 345 346 return ret; 347 } 348 349 static 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 365 err: 366 b53_srab_release_grant(dev); 367 368 return ret; 369 } 370 371 static 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 382 static 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) 395 static 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 414 static 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 435 static 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 446 static 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 479 static 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 500 static 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 }; 520 MODULE_DEVICE_TABLE(of, b53_srab_of_match); 521 522 static 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 534 static 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 565 static 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 618 static 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 660 static 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 return 0; 671 } 672 673 static void b53_srab_shutdown(struct platform_device *pdev) 674 { 675 struct b53_device *dev = platform_get_drvdata(pdev); 676 677 if (!dev) 678 return; 679 680 b53_switch_shutdown(dev); 681 682 platform_set_drvdata(pdev, NULL); 683 } 684 685 static struct platform_driver b53_srab_driver = { 686 .probe = b53_srab_probe, 687 .remove = b53_srab_remove, 688 .shutdown = b53_srab_shutdown, 689 .driver = { 690 .name = "b53-srab-switch", 691 .of_match_table = b53_srab_of_match, 692 }, 693 }; 694 695 module_platform_driver(b53_srab_driver); 696 MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); 697 MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver"); 698 MODULE_LICENSE("Dual BSD/GPL"); 699