162e11d1bSHauke Mehrtens /* 262e11d1bSHauke Mehrtens * Broadcom specific Advanced Microcontroller Bus 362e11d1bSHauke Mehrtens * Broadcom USB-core driver (BCMA bus glue) 462e11d1bSHauke Mehrtens * 510bc04b7SHauke Mehrtens * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de> 610bc04b7SHauke Mehrtens * Copyright 2015 Felix Fietkau <nbd@openwrt.org> 762e11d1bSHauke Mehrtens * 862e11d1bSHauke Mehrtens * Based on ssb-ohci driver 962e11d1bSHauke Mehrtens * Copyright 2007 Michael Buesch <m@bues.ch> 1062e11d1bSHauke Mehrtens * 1162e11d1bSHauke Mehrtens * Derived from the OHCI-PCI driver 1262e11d1bSHauke Mehrtens * Copyright 1999 Roman Weissgaerber 1362e11d1bSHauke Mehrtens * Copyright 2000-2002 David Brownell 1462e11d1bSHauke Mehrtens * Copyright 1999 Linus Torvalds 1562e11d1bSHauke Mehrtens * Copyright 1999 Gregory P. Smith 1662e11d1bSHauke Mehrtens * 1762e11d1bSHauke Mehrtens * Derived from the USBcore related parts of Broadcom-SB 1862e11d1bSHauke Mehrtens * Copyright 2005-2011 Broadcom Corporation 1962e11d1bSHauke Mehrtens * 2062e11d1bSHauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details. 2162e11d1bSHauke Mehrtens */ 2262e11d1bSHauke Mehrtens #include <linux/bcma/bcma.h> 2362e11d1bSHauke Mehrtens #include <linux/delay.h> 249faae5a3SRafał Miłecki #include <linux/gpio/consumer.h> 2562e11d1bSHauke Mehrtens #include <linux/platform_device.h> 2662e11d1bSHauke Mehrtens #include <linux/module.h> 276ba0d809SGeert Uytterhoeven #include <linux/slab.h> 28eb4861c3SHauke Mehrtens #include <linux/of.h> 29eb4861c3SHauke Mehrtens #include <linux/of_gpio.h> 3062e11d1bSHauke Mehrtens #include <linux/usb/ehci_pdriver.h> 3162e11d1bSHauke Mehrtens #include <linux/usb/ohci_pdriver.h> 3262e11d1bSHauke Mehrtens 3362e11d1bSHauke Mehrtens MODULE_AUTHOR("Hauke Mehrtens"); 3462e11d1bSHauke Mehrtens MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); 3562e11d1bSHauke Mehrtens MODULE_LICENSE("GPL"); 3662e11d1bSHauke Mehrtens 3762e11d1bSHauke Mehrtens struct bcma_hcd_device { 3862e11d1bSHauke Mehrtens struct platform_device *ehci_dev; 3962e11d1bSHauke Mehrtens struct platform_device *ohci_dev; 409faae5a3SRafał Miłecki struct gpio_desc *gpio_desc; 4162e11d1bSHauke Mehrtens }; 4262e11d1bSHauke Mehrtens 4362e11d1bSHauke Mehrtens /* Wait for bitmask in a register to get set or cleared. 4462e11d1bSHauke Mehrtens * timeout is in units of ten-microseconds. 4562e11d1bSHauke Mehrtens */ 4662e11d1bSHauke Mehrtens static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, 4762e11d1bSHauke Mehrtens int timeout) 4862e11d1bSHauke Mehrtens { 4962e11d1bSHauke Mehrtens int i; 5062e11d1bSHauke Mehrtens u32 val; 5162e11d1bSHauke Mehrtens 5262e11d1bSHauke Mehrtens for (i = 0; i < timeout; i++) { 5362e11d1bSHauke Mehrtens val = bcma_read32(dev, reg); 5462e11d1bSHauke Mehrtens if ((val & bitmask) == bitmask) 5562e11d1bSHauke Mehrtens return 0; 5662e11d1bSHauke Mehrtens udelay(10); 5762e11d1bSHauke Mehrtens } 5862e11d1bSHauke Mehrtens 5962e11d1bSHauke Mehrtens return -ETIMEDOUT; 6062e11d1bSHauke Mehrtens } 6162e11d1bSHauke Mehrtens 6241ac7b3aSBill Pemberton static void bcma_hcd_4716wa(struct bcma_device *dev) 6362e11d1bSHauke Mehrtens { 6462e11d1bSHauke Mehrtens #ifdef CONFIG_BCMA_DRIVER_MIPS 6562e11d1bSHauke Mehrtens /* Work around for 4716 failures. */ 6662e11d1bSHauke Mehrtens if (dev->bus->chipinfo.id == 0x4716) { 6762e11d1bSHauke Mehrtens u32 tmp; 6862e11d1bSHauke Mehrtens 6962e11d1bSHauke Mehrtens tmp = bcma_cpu_clock(&dev->bus->drv_mips); 7062e11d1bSHauke Mehrtens if (tmp >= 480000000) 7162e11d1bSHauke Mehrtens tmp = 0x1846b; /* set CDR to 0x11(fast) */ 7262e11d1bSHauke Mehrtens else if (tmp == 453000000) 7362e11d1bSHauke Mehrtens tmp = 0x1046b; /* set CDR to 0x10(slow) */ 7462e11d1bSHauke Mehrtens else 7562e11d1bSHauke Mehrtens tmp = 0; 7662e11d1bSHauke Mehrtens 7762e11d1bSHauke Mehrtens /* Change Shim mdio control reg to fix host not acking at 7862e11d1bSHauke Mehrtens * high frequencies 7962e11d1bSHauke Mehrtens */ 8062e11d1bSHauke Mehrtens if (tmp) { 8162e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ 8262e11d1bSHauke Mehrtens udelay(500); 8362e11d1bSHauke Mehrtens 8462e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, tmp); 8562e11d1bSHauke Mehrtens udelay(500); 8662e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x4ab); 8762e11d1bSHauke Mehrtens udelay(500); 8862e11d1bSHauke Mehrtens bcma_read32(dev, 0x528); 8962e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 9062e11d1bSHauke Mehrtens } 9162e11d1bSHauke Mehrtens } 9262e11d1bSHauke Mehrtens #endif /* CONFIG_BCMA_DRIVER_MIPS */ 9362e11d1bSHauke Mehrtens } 9462e11d1bSHauke Mehrtens 9562e11d1bSHauke Mehrtens /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ 9610bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_mips(struct bcma_device *dev) 9762e11d1bSHauke Mehrtens { 9862e11d1bSHauke Mehrtens u32 tmp; 9962e11d1bSHauke Mehrtens 10062e11d1bSHauke Mehrtens /* 10162e11d1bSHauke Mehrtens * USB 2.0 special considerations: 10262e11d1bSHauke Mehrtens * 10362e11d1bSHauke Mehrtens * 1. Since the core supports both OHCI and EHCI functions, it must 10462e11d1bSHauke Mehrtens * only be reset once. 10562e11d1bSHauke Mehrtens * 10662e11d1bSHauke Mehrtens * 2. In addition to the standard SI reset sequence, the Host Control 10762e11d1bSHauke Mehrtens * Register must be programmed to bring the USB core and various 10862e11d1bSHauke Mehrtens * phy components out of reset. 10962e11d1bSHauke Mehrtens */ 11062e11d1bSHauke Mehrtens if (!bcma_core_is_enabled(dev)) { 11162e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 11262e11d1bSHauke Mehrtens mdelay(10); 11362e11d1bSHauke Mehrtens if (dev->id.rev >= 5) { 11462e11d1bSHauke Mehrtens /* Enable Misc PLL */ 11562e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x1e0); 11662e11d1bSHauke Mehrtens tmp |= 0x100; 11762e11d1bSHauke Mehrtens bcma_write32(dev, 0x1e0, tmp); 11862e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) 11962e11d1bSHauke Mehrtens printk(KERN_EMERG "Failed to enable misc PPL!\n"); 12062e11d1bSHauke Mehrtens 12162e11d1bSHauke Mehrtens /* Take out of resets */ 12262e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x4ff); 12362e11d1bSHauke Mehrtens udelay(25); 12462e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x6ff); 12562e11d1bSHauke Mehrtens udelay(25); 12662e11d1bSHauke Mehrtens 12762e11d1bSHauke Mehrtens /* Make sure digital and AFE are locked in USB PHY */ 12862e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x6b); 12962e11d1bSHauke Mehrtens udelay(50); 13062e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13162e11d1bSHauke Mehrtens udelay(50); 13262e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0xab); 13362e11d1bSHauke Mehrtens udelay(50); 13462e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13562e11d1bSHauke Mehrtens udelay(50); 13662e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x2b); 13762e11d1bSHauke Mehrtens udelay(50); 13862e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13962e11d1bSHauke Mehrtens udelay(50); 14062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x10ab); 14162e11d1bSHauke Mehrtens udelay(50); 14262e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 14362e11d1bSHauke Mehrtens 14462e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { 14562e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x528); 14662e11d1bSHauke Mehrtens printk(KERN_EMERG 14762e11d1bSHauke Mehrtens "USB20H mdio_rddata 0x%08x\n", tmp); 14862e11d1bSHauke Mehrtens } 14962e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 15062e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x314); 15162e11d1bSHauke Mehrtens udelay(265); 15262e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 15362e11d1bSHauke Mehrtens udelay(10); 15462e11d1bSHauke Mehrtens 15562e11d1bSHauke Mehrtens /* Take USB and HSIC out of non-driving modes */ 15662e11d1bSHauke Mehrtens bcma_write32(dev, 0x510, 0); 15762e11d1bSHauke Mehrtens } else { 15862e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 15962e11d1bSHauke Mehrtens 16062e11d1bSHauke Mehrtens udelay(1); 16162e11d1bSHauke Mehrtens } 16262e11d1bSHauke Mehrtens 16362e11d1bSHauke Mehrtens bcma_hcd_4716wa(dev); 16462e11d1bSHauke Mehrtens } 16562e11d1bSHauke Mehrtens } 16662e11d1bSHauke Mehrtens 16710bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) 16810bc04b7SHauke Mehrtens { 16910bc04b7SHauke Mehrtens struct bcma_device *arm_core; 17010bc04b7SHauke Mehrtens void __iomem *dmu; 17110bc04b7SHauke Mehrtens 17210bc04b7SHauke Mehrtens arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); 17310bc04b7SHauke Mehrtens if (!arm_core) { 17410bc04b7SHauke Mehrtens dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); 17510bc04b7SHauke Mehrtens return; 17610bc04b7SHauke Mehrtens } 17710bc04b7SHauke Mehrtens 17810bc04b7SHauke Mehrtens dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); 17910bc04b7SHauke Mehrtens if (!dmu) { 18010bc04b7SHauke Mehrtens dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); 18110bc04b7SHauke Mehrtens return; 18210bc04b7SHauke Mehrtens } 18310bc04b7SHauke Mehrtens 18410bc04b7SHauke Mehrtens /* Unlock DMU PLL settings */ 18510bc04b7SHauke Mehrtens iowrite32(0x0000ea68, dmu + 0x180); 18610bc04b7SHauke Mehrtens 18710bc04b7SHauke Mehrtens /* Write USB 2.0 PLL control setting */ 18810bc04b7SHauke Mehrtens iowrite32(0x00dd10c3, dmu + 0x164); 18910bc04b7SHauke Mehrtens 19010bc04b7SHauke Mehrtens /* Lock DMU PLL settings */ 19110bc04b7SHauke Mehrtens iowrite32(0x00000000, dmu + 0x180); 19210bc04b7SHauke Mehrtens 19310bc04b7SHauke Mehrtens iounmap(dmu); 19410bc04b7SHauke Mehrtens } 19510bc04b7SHauke Mehrtens 19610bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) 19710bc04b7SHauke Mehrtens { 19810bc04b7SHauke Mehrtens u32 val; 19910bc04b7SHauke Mehrtens 20010bc04b7SHauke Mehrtens /* 20110bc04b7SHauke Mehrtens * Delay after PHY initialized to ensure HC is ready to be configured 20210bc04b7SHauke Mehrtens */ 20310bc04b7SHauke Mehrtens usleep_range(1000, 2000); 20410bc04b7SHauke Mehrtens 20510bc04b7SHauke Mehrtens /* Set packet buffer OUT threshold */ 20610bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x94); 20710bc04b7SHauke Mehrtens val &= 0xffff; 20810bc04b7SHauke Mehrtens val |= 0x80 << 16; 20910bc04b7SHauke Mehrtens bcma_write32(dev, 0x94, val); 21010bc04b7SHauke Mehrtens 21110bc04b7SHauke Mehrtens /* Enable break memory transfer */ 21210bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x9c); 21310bc04b7SHauke Mehrtens val |= 1; 21410bc04b7SHauke Mehrtens bcma_write32(dev, 0x9c, val); 21510bc04b7SHauke Mehrtens } 21610bc04b7SHauke Mehrtens 21710bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm(struct bcma_device *dev) 21810bc04b7SHauke Mehrtens { 21910bc04b7SHauke Mehrtens bcma_core_enable(dev, 0); 22010bc04b7SHauke Mehrtens 22110bc04b7SHauke Mehrtens if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || 22210bc04b7SHauke Mehrtens dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { 22310bc04b7SHauke Mehrtens if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || 22410bc04b7SHauke Mehrtens dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) 22510bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm_phy(dev); 22610bc04b7SHauke Mehrtens 22710bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm_hc(dev); 22810bc04b7SHauke Mehrtens } 22910bc04b7SHauke Mehrtens } 23010bc04b7SHauke Mehrtens 231eb4861c3SHauke Mehrtens static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) 232eb4861c3SHauke Mehrtens { 2339faae5a3SRafał Miłecki struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 234eb4861c3SHauke Mehrtens 2359faae5a3SRafał Miłecki if (IS_ERR_OR_NULL(usb_dev->gpio_desc)) 236eb4861c3SHauke Mehrtens return; 237eb4861c3SHauke Mehrtens 2389faae5a3SRafał Miłecki gpiod_set_value(usb_dev->gpio_desc, val); 239eb4861c3SHauke Mehrtens } 240eb4861c3SHauke Mehrtens 24162e11d1bSHauke Mehrtens static const struct usb_ehci_pdata ehci_pdata = { 24262e11d1bSHauke Mehrtens }; 24362e11d1bSHauke Mehrtens 24462e11d1bSHauke Mehrtens static const struct usb_ohci_pdata ohci_pdata = { 24562e11d1bSHauke Mehrtens }; 24662e11d1bSHauke Mehrtens 24741ac7b3aSBill Pemberton static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) 24862e11d1bSHauke Mehrtens { 24962e11d1bSHauke Mehrtens struct platform_device *hci_dev; 25062e11d1bSHauke Mehrtens struct resource hci_res[2]; 251ab2de579SHauke Mehrtens int ret; 25262e11d1bSHauke Mehrtens 25362e11d1bSHauke Mehrtens memset(hci_res, 0, sizeof(hci_res)); 25462e11d1bSHauke Mehrtens 25562e11d1bSHauke Mehrtens hci_res[0].start = addr; 25662e11d1bSHauke Mehrtens hci_res[0].end = hci_res[0].start + 0x1000 - 1; 25762e11d1bSHauke Mehrtens hci_res[0].flags = IORESOURCE_MEM; 25862e11d1bSHauke Mehrtens 25962e11d1bSHauke Mehrtens hci_res[1].start = dev->irq; 26062e11d1bSHauke Mehrtens hci_res[1].flags = IORESOURCE_IRQ; 26162e11d1bSHauke Mehrtens 26262e11d1bSHauke Mehrtens hci_dev = platform_device_alloc(ohci ? "ohci-platform" : 26362e11d1bSHauke Mehrtens "ehci-platform" , 0); 26462e11d1bSHauke Mehrtens if (!hci_dev) 265ab2de579SHauke Mehrtens return ERR_PTR(-ENOMEM); 26662e11d1bSHauke Mehrtens 26762e11d1bSHauke Mehrtens hci_dev->dev.parent = &dev->dev; 26862e11d1bSHauke Mehrtens hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; 26962e11d1bSHauke Mehrtens 27062e11d1bSHauke Mehrtens ret = platform_device_add_resources(hci_dev, hci_res, 27162e11d1bSHauke Mehrtens ARRAY_SIZE(hci_res)); 27262e11d1bSHauke Mehrtens if (ret) 27362e11d1bSHauke Mehrtens goto err_alloc; 27462e11d1bSHauke Mehrtens if (ohci) 27562e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ohci_pdata, 27662e11d1bSHauke Mehrtens sizeof(ohci_pdata)); 27762e11d1bSHauke Mehrtens else 27862e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ehci_pdata, 27962e11d1bSHauke Mehrtens sizeof(ehci_pdata)); 28062e11d1bSHauke Mehrtens if (ret) 28162e11d1bSHauke Mehrtens goto err_alloc; 28262e11d1bSHauke Mehrtens ret = platform_device_add(hci_dev); 28362e11d1bSHauke Mehrtens if (ret) 28462e11d1bSHauke Mehrtens goto err_alloc; 28562e11d1bSHauke Mehrtens 28662e11d1bSHauke Mehrtens return hci_dev; 28762e11d1bSHauke Mehrtens 28862e11d1bSHauke Mehrtens err_alloc: 28962e11d1bSHauke Mehrtens platform_device_put(hci_dev); 29062e11d1bSHauke Mehrtens return ERR_PTR(ret); 29162e11d1bSHauke Mehrtens } 29262e11d1bSHauke Mehrtens 29341ac7b3aSBill Pemberton static int bcma_hcd_probe(struct bcma_device *dev) 29462e11d1bSHauke Mehrtens { 29562e11d1bSHauke Mehrtens int err; 29662e11d1bSHauke Mehrtens u32 ohci_addr; 29762e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev; 29862e11d1bSHauke Mehrtens struct bcma_chipinfo *chipinfo; 29962e11d1bSHauke Mehrtens 30062e11d1bSHauke Mehrtens chipinfo = &dev->bus->chipinfo; 30162e11d1bSHauke Mehrtens 30262e11d1bSHauke Mehrtens /* TODO: Probably need checks here; is the core connected? */ 30362e11d1bSHauke Mehrtens 304d288059eSRussell King if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) 30562e11d1bSHauke Mehrtens return -EOPNOTSUPP; 30662e11d1bSHauke Mehrtens 307c27da2b2SHauke Mehrtens usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), 308c27da2b2SHauke Mehrtens GFP_KERNEL); 30962e11d1bSHauke Mehrtens if (!usb_dev) 31062e11d1bSHauke Mehrtens return -ENOMEM; 31162e11d1bSHauke Mehrtens 3129faae5a3SRafał Miłecki if (dev->dev.of_node) 3139faae5a3SRafał Miłecki usb_dev->gpio_desc = devm_get_gpiod_from_child(&dev->dev, "vcc", 3149faae5a3SRafał Miłecki &dev->dev.of_node->fwnode); 3159faae5a3SRafał Miłecki if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) 3169faae5a3SRafał Miłecki gpiod_direction_output(usb_dev->gpio_desc, 1); 317eb4861c3SHauke Mehrtens 31810bc04b7SHauke Mehrtens switch (dev->id.id) { 31910bc04b7SHauke Mehrtens case BCMA_CORE_NS_USB20: 32010bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm(dev); 32110bc04b7SHauke Mehrtens break; 32210bc04b7SHauke Mehrtens case BCMA_CORE_USB20_HOST: 32310bc04b7SHauke Mehrtens bcma_hcd_init_chip_mips(dev); 32410bc04b7SHauke Mehrtens break; 32510bc04b7SHauke Mehrtens default: 32610bc04b7SHauke Mehrtens return -ENODEV; 32710bc04b7SHauke Mehrtens } 32862e11d1bSHauke Mehrtens 32962e11d1bSHauke Mehrtens /* In AI chips EHCI is addrspace 0, OHCI is 1 */ 33023a2f39cSHauke Mehrtens ohci_addr = dev->addr_s[0]; 33198e13e05SHauke Mehrtens if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || 33298e13e05SHauke Mehrtens chipinfo->id == BCMA_CHIP_ID_BCM4749) 33362e11d1bSHauke Mehrtens && chipinfo->rev == 0) 33462e11d1bSHauke Mehrtens ohci_addr = 0x18009000; 33562e11d1bSHauke Mehrtens 33662e11d1bSHauke Mehrtens usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); 337c27da2b2SHauke Mehrtens if (IS_ERR(usb_dev->ohci_dev)) 338c27da2b2SHauke Mehrtens return PTR_ERR(usb_dev->ohci_dev); 33962e11d1bSHauke Mehrtens 34062e11d1bSHauke Mehrtens usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); 34162e11d1bSHauke Mehrtens if (IS_ERR(usb_dev->ehci_dev)) { 34262e11d1bSHauke Mehrtens err = PTR_ERR(usb_dev->ehci_dev); 34362e11d1bSHauke Mehrtens goto err_unregister_ohci_dev; 34462e11d1bSHauke Mehrtens } 34562e11d1bSHauke Mehrtens 34662e11d1bSHauke Mehrtens bcma_set_drvdata(dev, usb_dev); 34762e11d1bSHauke Mehrtens return 0; 34862e11d1bSHauke Mehrtens 34962e11d1bSHauke Mehrtens err_unregister_ohci_dev: 35062e11d1bSHauke Mehrtens platform_device_unregister(usb_dev->ohci_dev); 35162e11d1bSHauke Mehrtens return err; 35262e11d1bSHauke Mehrtens } 35362e11d1bSHauke Mehrtens 354fb4e98abSBill Pemberton static void bcma_hcd_remove(struct bcma_device *dev) 35562e11d1bSHauke Mehrtens { 35662e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 35762e11d1bSHauke Mehrtens struct platform_device *ohci_dev = usb_dev->ohci_dev; 35862e11d1bSHauke Mehrtens struct platform_device *ehci_dev = usb_dev->ehci_dev; 35962e11d1bSHauke Mehrtens 36062e11d1bSHauke Mehrtens if (ohci_dev) 36162e11d1bSHauke Mehrtens platform_device_unregister(ohci_dev); 36262e11d1bSHauke Mehrtens if (ehci_dev) 36362e11d1bSHauke Mehrtens platform_device_unregister(ehci_dev); 36462e11d1bSHauke Mehrtens 36562e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 36662e11d1bSHauke Mehrtens } 36762e11d1bSHauke Mehrtens 36862e11d1bSHauke Mehrtens static void bcma_hcd_shutdown(struct bcma_device *dev) 36962e11d1bSHauke Mehrtens { 370eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false); 37162e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 37262e11d1bSHauke Mehrtens } 37362e11d1bSHauke Mehrtens 37462e11d1bSHauke Mehrtens #ifdef CONFIG_PM 37562e11d1bSHauke Mehrtens 3761f6155f5SDan Carpenter static int bcma_hcd_suspend(struct bcma_device *dev) 37762e11d1bSHauke Mehrtens { 378eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false); 37962e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 38062e11d1bSHauke Mehrtens 38162e11d1bSHauke Mehrtens return 0; 38262e11d1bSHauke Mehrtens } 38362e11d1bSHauke Mehrtens 38462e11d1bSHauke Mehrtens static int bcma_hcd_resume(struct bcma_device *dev) 38562e11d1bSHauke Mehrtens { 386eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, true); 38762e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 38862e11d1bSHauke Mehrtens 38962e11d1bSHauke Mehrtens return 0; 39062e11d1bSHauke Mehrtens } 39162e11d1bSHauke Mehrtens 39262e11d1bSHauke Mehrtens #else /* !CONFIG_PM */ 39362e11d1bSHauke Mehrtens #define bcma_hcd_suspend NULL 39462e11d1bSHauke Mehrtens #define bcma_hcd_resume NULL 39562e11d1bSHauke Mehrtens #endif /* CONFIG_PM */ 39662e11d1bSHauke Mehrtens 3972f82686eSBill Pemberton static const struct bcma_device_id bcma_hcd_table[] = { 39862e11d1bSHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), 39910bc04b7SHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), 400f7219b52SJoe Perches {}, 40162e11d1bSHauke Mehrtens }; 40262e11d1bSHauke Mehrtens MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); 40362e11d1bSHauke Mehrtens 40462e11d1bSHauke Mehrtens static struct bcma_driver bcma_hcd_driver = { 40562e11d1bSHauke Mehrtens .name = KBUILD_MODNAME, 40662e11d1bSHauke Mehrtens .id_table = bcma_hcd_table, 40762e11d1bSHauke Mehrtens .probe = bcma_hcd_probe, 4087690417dSBill Pemberton .remove = bcma_hcd_remove, 40962e11d1bSHauke Mehrtens .shutdown = bcma_hcd_shutdown, 41062e11d1bSHauke Mehrtens .suspend = bcma_hcd_suspend, 41162e11d1bSHauke Mehrtens .resume = bcma_hcd_resume, 41262e11d1bSHauke Mehrtens }; 41362e11d1bSHauke Mehrtens 41462e11d1bSHauke Mehrtens static int __init bcma_hcd_init(void) 41562e11d1bSHauke Mehrtens { 41662e11d1bSHauke Mehrtens return bcma_driver_register(&bcma_hcd_driver); 41762e11d1bSHauke Mehrtens } 41862e11d1bSHauke Mehrtens module_init(bcma_hcd_init); 41962e11d1bSHauke Mehrtens 42062e11d1bSHauke Mehrtens static void __exit bcma_hcd_exit(void) 42162e11d1bSHauke Mehrtens { 42262e11d1bSHauke Mehrtens bcma_driver_unregister(&bcma_hcd_driver); 42362e11d1bSHauke Mehrtens } 42462e11d1bSHauke Mehrtens module_exit(bcma_hcd_exit); 425