Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Broadcom specific Advanced Microcontroller Bus
0004  * Broadcom USB-core driver (BCMA bus glue)
0005  *
0006  * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
0007  * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
0008  *
0009  * Based on ssb-ohci driver
0010  * Copyright 2007 Michael Buesch <m@bues.ch>
0011  *
0012  * Derived from the OHCI-PCI driver
0013  * Copyright 1999 Roman Weissgaerber
0014  * Copyright 2000-2002 David Brownell
0015  * Copyright 1999 Linus Torvalds
0016  * Copyright 1999 Gregory P. Smith
0017  *
0018  * Derived from the USBcore related parts of Broadcom-SB
0019  * Copyright 2005-2011 Broadcom Corporation
0020  */
0021 #include <linux/bcma/bcma.h>
0022 #include <linux/delay.h>
0023 #include <linux/gpio/consumer.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/module.h>
0026 #include <linux/slab.h>
0027 #include <linux/of.h>
0028 #include <linux/of_gpio.h>
0029 #include <linux/of_platform.h>
0030 #include <linux/usb/ehci_pdriver.h>
0031 #include <linux/usb/ohci_pdriver.h>
0032 
0033 MODULE_AUTHOR("Hauke Mehrtens");
0034 MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
0035 MODULE_LICENSE("GPL");
0036 
0037 /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
0038 #define USB_BCMA_CLKCTLST_USB_CLK_REQ           0x00000100
0039 
0040 struct bcma_hcd_device {
0041     struct bcma_device *core;
0042     struct platform_device *ehci_dev;
0043     struct platform_device *ohci_dev;
0044     struct gpio_desc *gpio_desc;
0045 };
0046 
0047 /* Wait for bitmask in a register to get set or cleared.
0048  * timeout is in units of ten-microseconds.
0049  */
0050 static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
0051               int timeout)
0052 {
0053     int i;
0054     u32 val;
0055 
0056     for (i = 0; i < timeout; i++) {
0057         val = bcma_read32(dev, reg);
0058         if ((val & bitmask) == bitmask)
0059             return 0;
0060         udelay(10);
0061     }
0062 
0063     return -ETIMEDOUT;
0064 }
0065 
0066 static void bcma_hcd_4716wa(struct bcma_device *dev)
0067 {
0068 #ifdef CONFIG_BCMA_DRIVER_MIPS
0069     /* Work around for 4716 failures. */
0070     if (dev->bus->chipinfo.id == 0x4716) {
0071         u32 tmp;
0072 
0073         tmp = bcma_cpu_clock(&dev->bus->drv_mips);
0074         if (tmp >= 480000000)
0075             tmp = 0x1846b; /* set CDR to 0x11(fast) */
0076         else if (tmp == 453000000)
0077             tmp = 0x1046b; /* set CDR to 0x10(slow) */
0078         else
0079             tmp = 0;
0080 
0081         /* Change Shim mdio control reg to fix host not acking at
0082          * high frequencies
0083          */
0084         if (tmp) {
0085             bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
0086             udelay(500);
0087 
0088             bcma_write32(dev, 0x524, tmp);
0089             udelay(500);
0090             bcma_write32(dev, 0x524, 0x4ab);
0091             udelay(500);
0092             bcma_read32(dev, 0x528);
0093             bcma_write32(dev, 0x528, 0x80000000);
0094         }
0095     }
0096 #endif /* CONFIG_BCMA_DRIVER_MIPS */
0097 }
0098 
0099 /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
0100 static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
0101 {
0102     u32 tmp;
0103 
0104     /*
0105      * USB 2.0 special considerations:
0106      *
0107      * 1. Since the core supports both OHCI and EHCI functions, it must
0108      *    only be reset once.
0109      *
0110      * 2. In addition to the standard SI reset sequence, the Host Control
0111      *    Register must be programmed to bring the USB core and various
0112      *    phy components out of reset.
0113      */
0114     if (!bcma_core_is_enabled(dev)) {
0115         bcma_core_enable(dev, 0);
0116         mdelay(10);
0117         if (dev->id.rev >= 5) {
0118             /* Enable Misc PLL */
0119             tmp = bcma_read32(dev, 0x1e0);
0120             tmp |= 0x100;
0121             bcma_write32(dev, 0x1e0, tmp);
0122             if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
0123                 printk(KERN_EMERG "Failed to enable misc PPL!\n");
0124 
0125             /* Take out of resets */
0126             bcma_write32(dev, 0x200, 0x4ff);
0127             udelay(25);
0128             bcma_write32(dev, 0x200, 0x6ff);
0129             udelay(25);
0130 
0131             /* Make sure digital and AFE are locked in USB PHY */
0132             bcma_write32(dev, 0x524, 0x6b);
0133             udelay(50);
0134             tmp = bcma_read32(dev, 0x524);
0135             udelay(50);
0136             bcma_write32(dev, 0x524, 0xab);
0137             udelay(50);
0138             tmp = bcma_read32(dev, 0x524);
0139             udelay(50);
0140             bcma_write32(dev, 0x524, 0x2b);
0141             udelay(50);
0142             tmp = bcma_read32(dev, 0x524);
0143             udelay(50);
0144             bcma_write32(dev, 0x524, 0x10ab);
0145             udelay(50);
0146             tmp = bcma_read32(dev, 0x524);
0147 
0148             if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
0149                 tmp = bcma_read32(dev, 0x528);
0150                 printk(KERN_EMERG
0151                        "USB20H mdio_rddata 0x%08x\n", tmp);
0152             }
0153             bcma_write32(dev, 0x528, 0x80000000);
0154             tmp = bcma_read32(dev, 0x314);
0155             udelay(265);
0156             bcma_write32(dev, 0x200, 0x7ff);
0157             udelay(10);
0158 
0159             /* Take USB and HSIC out of non-driving modes */
0160             bcma_write32(dev, 0x510, 0);
0161         } else {
0162             bcma_write32(dev, 0x200, 0x7ff);
0163 
0164             udelay(1);
0165         }
0166 
0167         bcma_hcd_4716wa(dev);
0168     }
0169 }
0170 
0171 /*
0172  * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
0173  *
0174  * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
0175  * long before Northstar devices. It seems some cheaper chipsets like BCM53573
0176  * still use it.
0177  * Initialization of this old core differs between MIPS and ARM.
0178  */
0179 static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
0180 {
0181     struct bcma_device *core = usb_dev->core;
0182     struct device *dev = &core->dev;
0183     struct bcma_device *pmu_core;
0184 
0185     usleep_range(10000, 20000);
0186     if (core->id.rev < 5)
0187         return 0;
0188 
0189     pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
0190     if (!pmu_core) {
0191         dev_err(dev, "Could not find PMU core\n");
0192         return -ENOENT;
0193     }
0194 
0195     /* Take USB core out of reset */
0196     bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
0197     usleep_range(100, 200);
0198     bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
0199     usleep_range(100, 200);
0200     bcma_awrite32(core, BCMA_RESET_CTL, 0);
0201     usleep_range(100, 200);
0202     bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
0203     usleep_range(100, 200);
0204 
0205     /* Enable Misc PLL */
0206     bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
0207                       BCMA_CLKCTLST_HQCLKREQ |
0208                       USB_BCMA_CLKCTLST_USB_CLK_REQ);
0209     usleep_range(100, 200);
0210 
0211     bcma_write32(core, 0x510, 0xc7f85000);
0212     bcma_write32(core, 0x510, 0xc7f85003);
0213     usleep_range(300, 600);
0214 
0215     /* Program USB PHY PLL parameters */
0216     bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
0217     bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
0218     usleep_range(100, 200);
0219     bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
0220     bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
0221     usleep_range(100, 200);
0222     bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
0223     usleep_range(100, 200);
0224 
0225     bcma_write32(core, 0x510, 0x7f8d007);
0226     udelay(1000);
0227 
0228     /* Take controller out of reset */
0229     bcma_write32(core, 0x200, 0x4ff);
0230     usleep_range(25, 50);
0231     bcma_write32(core, 0x200, 0x6ff);
0232     usleep_range(25, 50);
0233     bcma_write32(core, 0x200, 0x7ff);
0234     usleep_range(25, 50);
0235 
0236     of_platform_default_populate(dev->of_node, NULL, dev);
0237 
0238     return 0;
0239 }
0240 
0241 static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev)
0242 {
0243     u32 val;
0244 
0245     /* Set packet buffer OUT threshold */
0246     val = bcma_read32(dev, 0x94);
0247     val &= 0xffff;
0248     val |= 0x80 << 16;
0249     bcma_write32(dev, 0x94, val);
0250 
0251     /* Enable break memory transfer */
0252     val = bcma_read32(dev, 0x9c);
0253     val |= 1;
0254     bcma_write32(dev, 0x9c, val);
0255 
0256     /*
0257      * Broadcom initializes PHY and then waits to ensure HC is ready to be
0258      * configured. In our case the order is reversed. We just initialized
0259      * controller and we let HCD initialize PHY, so let's wait (sleep) now.
0260      */
0261     usleep_range(1000, 2000);
0262 }
0263 
0264 /*
0265  * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller
0266  */
0267 static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd)
0268 {
0269     struct bcma_device *core = bcma_hcd->core;
0270     struct bcma_chipinfo *ci = &core->bus->chipinfo;
0271     struct device *dev = &core->dev;
0272 
0273     bcma_core_enable(core, 0);
0274 
0275     if (ci->id == BCMA_CHIP_ID_BCM4707 ||
0276         ci->id == BCMA_CHIP_ID_BCM53018)
0277         bcma_hcd_usb20_ns_init_hc(core);
0278 
0279     of_platform_default_populate(dev->of_node, NULL, dev);
0280 
0281     return 0;
0282 }
0283 
0284 static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
0285 {
0286     struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
0287 
0288     if (IS_ERR_OR_NULL(usb_dev->gpio_desc))
0289         return;
0290 
0291     gpiod_set_value(usb_dev->gpio_desc, val);
0292 }
0293 
0294 static const struct usb_ehci_pdata ehci_pdata = {
0295 };
0296 
0297 static const struct usb_ohci_pdata ohci_pdata = {
0298 };
0299 
0300 static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
0301                             const char *name, u32 addr,
0302                             const void *data,
0303                             size_t size)
0304 {
0305     struct platform_device *hci_dev;
0306     struct resource hci_res[2];
0307     int ret;
0308 
0309     memset(hci_res, 0, sizeof(hci_res));
0310 
0311     hci_res[0].start = addr;
0312     hci_res[0].end = hci_res[0].start + 0x1000 - 1;
0313     hci_res[0].flags = IORESOURCE_MEM;
0314 
0315     hci_res[1].start = dev->irq;
0316     hci_res[1].flags = IORESOURCE_IRQ;
0317 
0318     hci_dev = platform_device_alloc(name, 0);
0319     if (!hci_dev)
0320         return ERR_PTR(-ENOMEM);
0321 
0322     hci_dev->dev.parent = &dev->dev;
0323     hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
0324 
0325     ret = platform_device_add_resources(hci_dev, hci_res,
0326                         ARRAY_SIZE(hci_res));
0327     if (ret)
0328         goto err_alloc;
0329     if (data)
0330         ret = platform_device_add_data(hci_dev, data, size);
0331     if (ret)
0332         goto err_alloc;
0333     ret = platform_device_add(hci_dev);
0334     if (ret)
0335         goto err_alloc;
0336 
0337     return hci_dev;
0338 
0339 err_alloc:
0340     platform_device_put(hci_dev);
0341     return ERR_PTR(ret);
0342 }
0343 
0344 static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev)
0345 {
0346     struct bcma_device *dev = usb_dev->core;
0347     struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
0348     u32 ohci_addr;
0349     int err;
0350 
0351     if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
0352         return -EOPNOTSUPP;
0353 
0354     bcma_hcd_init_chip_mips(dev);
0355 
0356     /* In AI chips EHCI is addrspace 0, OHCI is 1 */
0357     ohci_addr = dev->addr_s[0];
0358     if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
0359          chipinfo->id == BCMA_CHIP_ID_BCM4749)
0360         && chipinfo->rev == 0)
0361         ohci_addr = 0x18009000;
0362 
0363     usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
0364                          ohci_addr, &ohci_pdata,
0365                          sizeof(ohci_pdata));
0366     if (IS_ERR(usb_dev->ohci_dev))
0367         return PTR_ERR(usb_dev->ohci_dev);
0368 
0369     usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
0370                          dev->addr, &ehci_pdata,
0371                          sizeof(ehci_pdata));
0372     if (IS_ERR(usb_dev->ehci_dev)) {
0373         err = PTR_ERR(usb_dev->ehci_dev);
0374         goto err_unregister_ohci_dev;
0375     }
0376 
0377     return 0;
0378 
0379 err_unregister_ohci_dev:
0380     platform_device_unregister(usb_dev->ohci_dev);
0381     return err;
0382 }
0383 
0384 static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
0385 {
0386     struct bcma_device *core = bcma_hcd->core;
0387     struct device *dev = &core->dev;
0388 
0389     bcma_core_enable(core, 0);
0390 
0391     of_platform_default_populate(dev->of_node, NULL, dev);
0392 
0393     return 0;
0394 }
0395 
0396 static int bcma_hcd_probe(struct bcma_device *core)
0397 {
0398     int err;
0399     struct bcma_hcd_device *usb_dev;
0400 
0401     /* TODO: Probably need checks here; is the core connected? */
0402 
0403     usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device),
0404                    GFP_KERNEL);
0405     if (!usb_dev)
0406         return -ENOMEM;
0407     usb_dev->core = core;
0408 
0409     if (core->dev.of_node)
0410         usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc",
0411                             GPIOD_OUT_HIGH);
0412 
0413     switch (core->id.id) {
0414     case BCMA_CORE_USB20_HOST:
0415         if (IS_ENABLED(CONFIG_ARM))
0416             err = bcma_hcd_usb20_old_arm_init(usb_dev);
0417         else if (IS_ENABLED(CONFIG_MIPS))
0418             err = bcma_hcd_usb20_init(usb_dev);
0419         else
0420             err = -ENOTSUPP;
0421         break;
0422     case BCMA_CORE_NS_USB20:
0423         err = bcma_hcd_usb20_ns_init(usb_dev);
0424         break;
0425     case BCMA_CORE_NS_USB30:
0426         err = bcma_hcd_usb30_init(usb_dev);
0427         break;
0428     default:
0429         return -ENODEV;
0430     }
0431     if (err)
0432         return err;
0433 
0434     bcma_set_drvdata(core, usb_dev);
0435     return 0;
0436 }
0437 
0438 static void bcma_hcd_remove(struct bcma_device *dev)
0439 {
0440     struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
0441     struct platform_device *ohci_dev = usb_dev->ohci_dev;
0442     struct platform_device *ehci_dev = usb_dev->ehci_dev;
0443 
0444     if (ohci_dev)
0445         platform_device_unregister(ohci_dev);
0446     if (ehci_dev)
0447         platform_device_unregister(ehci_dev);
0448 
0449     bcma_core_disable(dev, 0);
0450 }
0451 
0452 static void bcma_hcd_shutdown(struct bcma_device *dev)
0453 {
0454     bcma_hci_platform_power_gpio(dev, false);
0455     bcma_core_disable(dev, 0);
0456 }
0457 
0458 #ifdef CONFIG_PM
0459 
0460 static int bcma_hcd_suspend(struct bcma_device *dev)
0461 {
0462     bcma_hci_platform_power_gpio(dev, false);
0463     bcma_core_disable(dev, 0);
0464 
0465     return 0;
0466 }
0467 
0468 static int bcma_hcd_resume(struct bcma_device *dev)
0469 {
0470     bcma_hci_platform_power_gpio(dev, true);
0471     bcma_core_enable(dev, 0);
0472 
0473     return 0;
0474 }
0475 
0476 #else /* !CONFIG_PM */
0477 #define bcma_hcd_suspend    NULL
0478 #define bcma_hcd_resume NULL
0479 #endif /* CONFIG_PM */
0480 
0481 static const struct bcma_device_id bcma_hcd_table[] = {
0482     BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
0483     BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
0484     BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
0485     {},
0486 };
0487 MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
0488 
0489 static struct bcma_driver bcma_hcd_driver = {
0490     .name       = KBUILD_MODNAME,
0491     .id_table   = bcma_hcd_table,
0492     .probe      = bcma_hcd_probe,
0493     .remove     = bcma_hcd_remove,
0494     .shutdown   = bcma_hcd_shutdown,
0495     .suspend    = bcma_hcd_suspend,
0496     .resume     = bcma_hcd_resume,
0497 };
0498 module_bcma_driver(bcma_hcd_driver);