root/drivers/usb/host/bcma-hcd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bcma_wait_bits
  2. bcma_hcd_4716wa
  3. bcma_hcd_init_chip_mips
  4. bcma_hcd_usb20_old_arm_init
  5. bcma_hcd_usb20_ns_init_hc
  6. bcma_hcd_usb20_ns_init
  7. bcma_hci_platform_power_gpio
  8. bcma_hcd_create_pdev
  9. bcma_hcd_usb20_init
  10. bcma_hcd_usb30_init
  11. bcma_hcd_probe
  12. bcma_hcd_remove
  13. bcma_hcd_shutdown
  14. bcma_hcd_suspend
  15. bcma_hcd_resume
  16. bcma_hcd_init
  17. bcma_hcd_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Broadcom specific Advanced Microcontroller Bus
   4  * Broadcom USB-core driver (BCMA bus glue)
   5  *
   6  * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
   7  * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
   8  *
   9  * Based on ssb-ohci driver
  10  * Copyright 2007 Michael Buesch <m@bues.ch>
  11  *
  12  * Derived from the OHCI-PCI driver
  13  * Copyright 1999 Roman Weissgaerber
  14  * Copyright 2000-2002 David Brownell
  15  * Copyright 1999 Linus Torvalds
  16  * Copyright 1999 Gregory P. Smith
  17  *
  18  * Derived from the USBcore related parts of Broadcom-SB
  19  * Copyright 2005-2011 Broadcom Corporation
  20  */
  21 #include <linux/bcma/bcma.h>
  22 #include <linux/delay.h>
  23 #include <linux/gpio/consumer.h>
  24 #include <linux/platform_device.h>
  25 #include <linux/module.h>
  26 #include <linux/slab.h>
  27 #include <linux/of.h>
  28 #include <linux/of_gpio.h>
  29 #include <linux/of_platform.h>
  30 #include <linux/usb/ehci_pdriver.h>
  31 #include <linux/usb/ohci_pdriver.h>
  32 
  33 MODULE_AUTHOR("Hauke Mehrtens");
  34 MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
  35 MODULE_LICENSE("GPL");
  36 
  37 /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
  38 #define USB_BCMA_CLKCTLST_USB_CLK_REQ                   0x00000100
  39 
  40 struct bcma_hcd_device {
  41         struct bcma_device *core;
  42         struct platform_device *ehci_dev;
  43         struct platform_device *ohci_dev;
  44         struct gpio_desc *gpio_desc;
  45 };
  46 
  47 /* Wait for bitmask in a register to get set or cleared.
  48  * timeout is in units of ten-microseconds.
  49  */
  50 static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
  51                           int timeout)
  52 {
  53         int i;
  54         u32 val;
  55 
  56         for (i = 0; i < timeout; i++) {
  57                 val = bcma_read32(dev, reg);
  58                 if ((val & bitmask) == bitmask)
  59                         return 0;
  60                 udelay(10);
  61         }
  62 
  63         return -ETIMEDOUT;
  64 }
  65 
  66 static void bcma_hcd_4716wa(struct bcma_device *dev)
  67 {
  68 #ifdef CONFIG_BCMA_DRIVER_MIPS
  69         /* Work around for 4716 failures. */
  70         if (dev->bus->chipinfo.id == 0x4716) {
  71                 u32 tmp;
  72 
  73                 tmp = bcma_cpu_clock(&dev->bus->drv_mips);
  74                 if (tmp >= 480000000)
  75                         tmp = 0x1846b; /* set CDR to 0x11(fast) */
  76                 else if (tmp == 453000000)
  77                         tmp = 0x1046b; /* set CDR to 0x10(slow) */
  78                 else
  79                         tmp = 0;
  80 
  81                 /* Change Shim mdio control reg to fix host not acking at
  82                  * high frequencies
  83                  */
  84                 if (tmp) {
  85                         bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
  86                         udelay(500);
  87 
  88                         bcma_write32(dev, 0x524, tmp);
  89                         udelay(500);
  90                         bcma_write32(dev, 0x524, 0x4ab);
  91                         udelay(500);
  92                         bcma_read32(dev, 0x528);
  93                         bcma_write32(dev, 0x528, 0x80000000);
  94                 }
  95         }
  96 #endif /* CONFIG_BCMA_DRIVER_MIPS */
  97 }
  98 
  99 /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
 100 static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
 101 {
 102         u32 tmp;
 103 
 104         /*
 105          * USB 2.0 special considerations:
 106          *
 107          * 1. Since the core supports both OHCI and EHCI functions, it must
 108          *    only be reset once.
 109          *
 110          * 2. In addition to the standard SI reset sequence, the Host Control
 111          *    Register must be programmed to bring the USB core and various
 112          *    phy components out of reset.
 113          */
 114         if (!bcma_core_is_enabled(dev)) {
 115                 bcma_core_enable(dev, 0);
 116                 mdelay(10);
 117                 if (dev->id.rev >= 5) {
 118                         /* Enable Misc PLL */
 119                         tmp = bcma_read32(dev, 0x1e0);
 120                         tmp |= 0x100;
 121                         bcma_write32(dev, 0x1e0, tmp);
 122                         if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
 123                                 printk(KERN_EMERG "Failed to enable misc PPL!\n");
 124 
 125                         /* Take out of resets */
 126                         bcma_write32(dev, 0x200, 0x4ff);
 127                         udelay(25);
 128                         bcma_write32(dev, 0x200, 0x6ff);
 129                         udelay(25);
 130 
 131                         /* Make sure digital and AFE are locked in USB PHY */
 132                         bcma_write32(dev, 0x524, 0x6b);
 133                         udelay(50);
 134                         tmp = bcma_read32(dev, 0x524);
 135                         udelay(50);
 136                         bcma_write32(dev, 0x524, 0xab);
 137                         udelay(50);
 138                         tmp = bcma_read32(dev, 0x524);
 139                         udelay(50);
 140                         bcma_write32(dev, 0x524, 0x2b);
 141                         udelay(50);
 142                         tmp = bcma_read32(dev, 0x524);
 143                         udelay(50);
 144                         bcma_write32(dev, 0x524, 0x10ab);
 145                         udelay(50);
 146                         tmp = bcma_read32(dev, 0x524);
 147 
 148                         if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
 149                                 tmp = bcma_read32(dev, 0x528);
 150                                 printk(KERN_EMERG
 151                                        "USB20H mdio_rddata 0x%08x\n", tmp);
 152                         }
 153                         bcma_write32(dev, 0x528, 0x80000000);
 154                         tmp = bcma_read32(dev, 0x314);
 155                         udelay(265);
 156                         bcma_write32(dev, 0x200, 0x7ff);
 157                         udelay(10);
 158 
 159                         /* Take USB and HSIC out of non-driving modes */
 160                         bcma_write32(dev, 0x510, 0);
 161                 } else {
 162                         bcma_write32(dev, 0x200, 0x7ff);
 163 
 164                         udelay(1);
 165                 }
 166 
 167                 bcma_hcd_4716wa(dev);
 168         }
 169 }
 170 
 171 /**
 172  * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
 173  *
 174  * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
 175  * long before Northstar devices. It seems some cheaper chipsets like BCM53573
 176  * still use it.
 177  * Initialization of this old core differs between MIPS and ARM.
 178  */
 179 static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
 180 {
 181         struct bcma_device *core = usb_dev->core;
 182         struct device *dev = &core->dev;
 183         struct bcma_device *pmu_core;
 184 
 185         usleep_range(10000, 20000);
 186         if (core->id.rev < 5)
 187                 return 0;
 188 
 189         pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
 190         if (!pmu_core) {
 191                 dev_err(dev, "Could not find PMU core\n");
 192                 return -ENOENT;
 193         }
 194 
 195         /* Take USB core out of reset */
 196         bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
 197         usleep_range(100, 200);
 198         bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
 199         usleep_range(100, 200);
 200         bcma_awrite32(core, BCMA_RESET_CTL, 0);
 201         usleep_range(100, 200);
 202         bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
 203         usleep_range(100, 200);
 204 
 205         /* Enable Misc PLL */
 206         bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
 207                                           BCMA_CLKCTLST_HQCLKREQ |
 208                                           USB_BCMA_CLKCTLST_USB_CLK_REQ);
 209         usleep_range(100, 200);
 210 
 211         bcma_write32(core, 0x510, 0xc7f85000);
 212         bcma_write32(core, 0x510, 0xc7f85003);
 213         usleep_range(300, 600);
 214 
 215         /* Program USB PHY PLL parameters */
 216         bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
 217         bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
 218         usleep_range(100, 200);
 219         bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
 220         bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
 221         usleep_range(100, 200);
 222         bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
 223         usleep_range(100, 200);
 224 
 225         bcma_write32(core, 0x510, 0x7f8d007);
 226         udelay(1000);
 227 
 228         /* Take controller out of reset */
 229         bcma_write32(core, 0x200, 0x4ff);
 230         usleep_range(25, 50);
 231         bcma_write32(core, 0x200, 0x6ff);
 232         usleep_range(25, 50);
 233         bcma_write32(core, 0x200, 0x7ff);
 234         usleep_range(25, 50);
 235 
 236         of_platform_default_populate(dev->of_node, NULL, dev);
 237 
 238         return 0;
 239 }
 240 
 241 static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev)
 242 {
 243         u32 val;
 244 
 245         /* Set packet buffer OUT threshold */
 246         val = bcma_read32(dev, 0x94);
 247         val &= 0xffff;
 248         val |= 0x80 << 16;
 249         bcma_write32(dev, 0x94, val);
 250 
 251         /* Enable break memory transfer */
 252         val = bcma_read32(dev, 0x9c);
 253         val |= 1;
 254         bcma_write32(dev, 0x9c, val);
 255 
 256         /*
 257          * Broadcom initializes PHY and then waits to ensure HC is ready to be
 258          * configured. In our case the order is reversed. We just initialized
 259          * controller and we let HCD initialize PHY, so let's wait (sleep) now.
 260          */
 261         usleep_range(1000, 2000);
 262 }
 263 
 264 /**
 265  * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller
 266  */
 267 static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd)
 268 {
 269         struct bcma_device *core = bcma_hcd->core;
 270         struct bcma_chipinfo *ci = &core->bus->chipinfo;
 271         struct device *dev = &core->dev;
 272 
 273         bcma_core_enable(core, 0);
 274 
 275         if (ci->id == BCMA_CHIP_ID_BCM4707 ||
 276             ci->id == BCMA_CHIP_ID_BCM53018)
 277                 bcma_hcd_usb20_ns_init_hc(core);
 278 
 279         of_platform_default_populate(dev->of_node, NULL, dev);
 280 
 281         return 0;
 282 }
 283 
 284 static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
 285 {
 286         struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
 287 
 288         if (IS_ERR_OR_NULL(usb_dev->gpio_desc))
 289                 return;
 290 
 291         gpiod_set_value(usb_dev->gpio_desc, val);
 292 }
 293 
 294 static const struct usb_ehci_pdata ehci_pdata = {
 295 };
 296 
 297 static const struct usb_ohci_pdata ohci_pdata = {
 298 };
 299 
 300 static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
 301                                                     const char *name, u32 addr,
 302                                                     const void *data,
 303                                                     size_t size)
 304 {
 305         struct platform_device *hci_dev;
 306         struct resource hci_res[2];
 307         int ret;
 308 
 309         memset(hci_res, 0, sizeof(hci_res));
 310 
 311         hci_res[0].start = addr;
 312         hci_res[0].end = hci_res[0].start + 0x1000 - 1;
 313         hci_res[0].flags = IORESOURCE_MEM;
 314 
 315         hci_res[1].start = dev->irq;
 316         hci_res[1].flags = IORESOURCE_IRQ;
 317 
 318         hci_dev = platform_device_alloc(name, 0);
 319         if (!hci_dev)
 320                 return ERR_PTR(-ENOMEM);
 321 
 322         hci_dev->dev.parent = &dev->dev;
 323         hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
 324 
 325         ret = platform_device_add_resources(hci_dev, hci_res,
 326                                             ARRAY_SIZE(hci_res));
 327         if (ret)
 328                 goto err_alloc;
 329         if (data)
 330                 ret = platform_device_add_data(hci_dev, data, size);
 331         if (ret)
 332                 goto err_alloc;
 333         ret = platform_device_add(hci_dev);
 334         if (ret)
 335                 goto err_alloc;
 336 
 337         return hci_dev;
 338 
 339 err_alloc:
 340         platform_device_put(hci_dev);
 341         return ERR_PTR(ret);
 342 }
 343 
 344 static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev)
 345 {
 346         struct bcma_device *dev = usb_dev->core;
 347         struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
 348         u32 ohci_addr;
 349         int err;
 350 
 351         if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
 352                 return -EOPNOTSUPP;
 353 
 354         bcma_hcd_init_chip_mips(dev);
 355 
 356         /* In AI chips EHCI is addrspace 0, OHCI is 1 */
 357         ohci_addr = dev->addr_s[0];
 358         if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
 359              chipinfo->id == BCMA_CHIP_ID_BCM4749)
 360             && chipinfo->rev == 0)
 361                 ohci_addr = 0x18009000;
 362 
 363         usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
 364                                                  ohci_addr, &ohci_pdata,
 365                                                  sizeof(ohci_pdata));
 366         if (IS_ERR(usb_dev->ohci_dev))
 367                 return PTR_ERR(usb_dev->ohci_dev);
 368 
 369         usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
 370                                                  dev->addr, &ehci_pdata,
 371                                                  sizeof(ehci_pdata));
 372         if (IS_ERR(usb_dev->ehci_dev)) {
 373                 err = PTR_ERR(usb_dev->ehci_dev);
 374                 goto err_unregister_ohci_dev;
 375         }
 376 
 377         return 0;
 378 
 379 err_unregister_ohci_dev:
 380         platform_device_unregister(usb_dev->ohci_dev);
 381         return err;
 382 }
 383 
 384 static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
 385 {
 386         struct bcma_device *core = bcma_hcd->core;
 387         struct device *dev = &core->dev;
 388 
 389         bcma_core_enable(core, 0);
 390 
 391         of_platform_default_populate(dev->of_node, NULL, dev);
 392 
 393         return 0;
 394 }
 395 
 396 static int bcma_hcd_probe(struct bcma_device *core)
 397 {
 398         int err;
 399         struct bcma_hcd_device *usb_dev;
 400 
 401         /* TODO: Probably need checks here; is the core connected? */
 402 
 403         usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device),
 404                                GFP_KERNEL);
 405         if (!usb_dev)
 406                 return -ENOMEM;
 407         usb_dev->core = core;
 408 
 409         if (core->dev.of_node)
 410                 usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc",
 411                                                     GPIOD_OUT_HIGH);
 412 
 413         switch (core->id.id) {
 414         case BCMA_CORE_USB20_HOST:
 415                 if (IS_ENABLED(CONFIG_ARM))
 416                         err = bcma_hcd_usb20_old_arm_init(usb_dev);
 417                 else if (IS_ENABLED(CONFIG_MIPS))
 418                         err = bcma_hcd_usb20_init(usb_dev);
 419                 else
 420                         err = -ENOTSUPP;
 421                 break;
 422         case BCMA_CORE_NS_USB20:
 423                 err = bcma_hcd_usb20_ns_init(usb_dev);
 424                 break;
 425         case BCMA_CORE_NS_USB30:
 426                 err = bcma_hcd_usb30_init(usb_dev);
 427                 break;
 428         default:
 429                 return -ENODEV;
 430         }
 431         if (err)
 432                 return err;
 433 
 434         bcma_set_drvdata(core, usb_dev);
 435         return 0;
 436 }
 437 
 438 static void bcma_hcd_remove(struct bcma_device *dev)
 439 {
 440         struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
 441         struct platform_device *ohci_dev = usb_dev->ohci_dev;
 442         struct platform_device *ehci_dev = usb_dev->ehci_dev;
 443 
 444         if (ohci_dev)
 445                 platform_device_unregister(ohci_dev);
 446         if (ehci_dev)
 447                 platform_device_unregister(ehci_dev);
 448 
 449         bcma_core_disable(dev, 0);
 450 }
 451 
 452 static void bcma_hcd_shutdown(struct bcma_device *dev)
 453 {
 454         bcma_hci_platform_power_gpio(dev, false);
 455         bcma_core_disable(dev, 0);
 456 }
 457 
 458 #ifdef CONFIG_PM
 459 
 460 static int bcma_hcd_suspend(struct bcma_device *dev)
 461 {
 462         bcma_hci_platform_power_gpio(dev, false);
 463         bcma_core_disable(dev, 0);
 464 
 465         return 0;
 466 }
 467 
 468 static int bcma_hcd_resume(struct bcma_device *dev)
 469 {
 470         bcma_hci_platform_power_gpio(dev, true);
 471         bcma_core_enable(dev, 0);
 472 
 473         return 0;
 474 }
 475 
 476 #else /* !CONFIG_PM */
 477 #define bcma_hcd_suspend        NULL
 478 #define bcma_hcd_resume NULL
 479 #endif /* CONFIG_PM */
 480 
 481 static const struct bcma_device_id bcma_hcd_table[] = {
 482         BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
 483         BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
 484         BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
 485         {},
 486 };
 487 MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
 488 
 489 static struct bcma_driver bcma_hcd_driver = {
 490         .name           = KBUILD_MODNAME,
 491         .id_table       = bcma_hcd_table,
 492         .probe          = bcma_hcd_probe,
 493         .remove         = bcma_hcd_remove,
 494         .shutdown       = bcma_hcd_shutdown,
 495         .suspend        = bcma_hcd_suspend,
 496         .resume         = bcma_hcd_resume,
 497 };
 498 
 499 static int __init bcma_hcd_init(void)
 500 {
 501         return bcma_driver_register(&bcma_hcd_driver);
 502 }
 503 module_init(bcma_hcd_init);
 504 
 505 static void __exit bcma_hcd_exit(void)
 506 {
 507         bcma_driver_unregister(&bcma_hcd_driver);
 508 }
 509 module_exit(bcma_hcd_exit);

/* [<][>][^][v][top][bottom][index][help] */