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> 2462e11d1bSHauke Mehrtens #include <linux/platform_device.h> 2562e11d1bSHauke Mehrtens #include <linux/module.h> 266ba0d809SGeert Uytterhoeven #include <linux/slab.h> 27eb4861c3SHauke Mehrtens #include <linux/of.h> 28eb4861c3SHauke Mehrtens #include <linux/of_gpio.h> 2962e11d1bSHauke Mehrtens #include <linux/usb/ehci_pdriver.h> 3062e11d1bSHauke Mehrtens #include <linux/usb/ohci_pdriver.h> 3162e11d1bSHauke Mehrtens 3262e11d1bSHauke Mehrtens MODULE_AUTHOR("Hauke Mehrtens"); 3362e11d1bSHauke Mehrtens MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); 3462e11d1bSHauke Mehrtens MODULE_LICENSE("GPL"); 3562e11d1bSHauke Mehrtens 3662e11d1bSHauke Mehrtens struct bcma_hcd_device { 3762e11d1bSHauke Mehrtens struct platform_device *ehci_dev; 3862e11d1bSHauke Mehrtens struct platform_device *ohci_dev; 3962e11d1bSHauke Mehrtens }; 4062e11d1bSHauke Mehrtens 4162e11d1bSHauke Mehrtens /* Wait for bitmask in a register to get set or cleared. 4262e11d1bSHauke Mehrtens * timeout is in units of ten-microseconds. 4362e11d1bSHauke Mehrtens */ 4462e11d1bSHauke Mehrtens static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, 4562e11d1bSHauke Mehrtens int timeout) 4662e11d1bSHauke Mehrtens { 4762e11d1bSHauke Mehrtens int i; 4862e11d1bSHauke Mehrtens u32 val; 4962e11d1bSHauke Mehrtens 5062e11d1bSHauke Mehrtens for (i = 0; i < timeout; i++) { 5162e11d1bSHauke Mehrtens val = bcma_read32(dev, reg); 5262e11d1bSHauke Mehrtens if ((val & bitmask) == bitmask) 5362e11d1bSHauke Mehrtens return 0; 5462e11d1bSHauke Mehrtens udelay(10); 5562e11d1bSHauke Mehrtens } 5662e11d1bSHauke Mehrtens 5762e11d1bSHauke Mehrtens return -ETIMEDOUT; 5862e11d1bSHauke Mehrtens } 5962e11d1bSHauke Mehrtens 6041ac7b3aSBill Pemberton static void bcma_hcd_4716wa(struct bcma_device *dev) 6162e11d1bSHauke Mehrtens { 6262e11d1bSHauke Mehrtens #ifdef CONFIG_BCMA_DRIVER_MIPS 6362e11d1bSHauke Mehrtens /* Work around for 4716 failures. */ 6462e11d1bSHauke Mehrtens if (dev->bus->chipinfo.id == 0x4716) { 6562e11d1bSHauke Mehrtens u32 tmp; 6662e11d1bSHauke Mehrtens 6762e11d1bSHauke Mehrtens tmp = bcma_cpu_clock(&dev->bus->drv_mips); 6862e11d1bSHauke Mehrtens if (tmp >= 480000000) 6962e11d1bSHauke Mehrtens tmp = 0x1846b; /* set CDR to 0x11(fast) */ 7062e11d1bSHauke Mehrtens else if (tmp == 453000000) 7162e11d1bSHauke Mehrtens tmp = 0x1046b; /* set CDR to 0x10(slow) */ 7262e11d1bSHauke Mehrtens else 7362e11d1bSHauke Mehrtens tmp = 0; 7462e11d1bSHauke Mehrtens 7562e11d1bSHauke Mehrtens /* Change Shim mdio control reg to fix host not acking at 7662e11d1bSHauke Mehrtens * high frequencies 7762e11d1bSHauke Mehrtens */ 7862e11d1bSHauke Mehrtens if (tmp) { 7962e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ 8062e11d1bSHauke Mehrtens udelay(500); 8162e11d1bSHauke Mehrtens 8262e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, tmp); 8362e11d1bSHauke Mehrtens udelay(500); 8462e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x4ab); 8562e11d1bSHauke Mehrtens udelay(500); 8662e11d1bSHauke Mehrtens bcma_read32(dev, 0x528); 8762e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 8862e11d1bSHauke Mehrtens } 8962e11d1bSHauke Mehrtens } 9062e11d1bSHauke Mehrtens #endif /* CONFIG_BCMA_DRIVER_MIPS */ 9162e11d1bSHauke Mehrtens } 9262e11d1bSHauke Mehrtens 9362e11d1bSHauke Mehrtens /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ 9410bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_mips(struct bcma_device *dev) 9562e11d1bSHauke Mehrtens { 9662e11d1bSHauke Mehrtens u32 tmp; 9762e11d1bSHauke Mehrtens 9862e11d1bSHauke Mehrtens /* 9962e11d1bSHauke Mehrtens * USB 2.0 special considerations: 10062e11d1bSHauke Mehrtens * 10162e11d1bSHauke Mehrtens * 1. Since the core supports both OHCI and EHCI functions, it must 10262e11d1bSHauke Mehrtens * only be reset once. 10362e11d1bSHauke Mehrtens * 10462e11d1bSHauke Mehrtens * 2. In addition to the standard SI reset sequence, the Host Control 10562e11d1bSHauke Mehrtens * Register must be programmed to bring the USB core and various 10662e11d1bSHauke Mehrtens * phy components out of reset. 10762e11d1bSHauke Mehrtens */ 10862e11d1bSHauke Mehrtens if (!bcma_core_is_enabled(dev)) { 10962e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 11062e11d1bSHauke Mehrtens mdelay(10); 11162e11d1bSHauke Mehrtens if (dev->id.rev >= 5) { 11262e11d1bSHauke Mehrtens /* Enable Misc PLL */ 11362e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x1e0); 11462e11d1bSHauke Mehrtens tmp |= 0x100; 11562e11d1bSHauke Mehrtens bcma_write32(dev, 0x1e0, tmp); 11662e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) 11762e11d1bSHauke Mehrtens printk(KERN_EMERG "Failed to enable misc PPL!\n"); 11862e11d1bSHauke Mehrtens 11962e11d1bSHauke Mehrtens /* Take out of resets */ 12062e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x4ff); 12162e11d1bSHauke Mehrtens udelay(25); 12262e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x6ff); 12362e11d1bSHauke Mehrtens udelay(25); 12462e11d1bSHauke Mehrtens 12562e11d1bSHauke Mehrtens /* Make sure digital and AFE are locked in USB PHY */ 12662e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x6b); 12762e11d1bSHauke Mehrtens udelay(50); 12862e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 12962e11d1bSHauke Mehrtens udelay(50); 13062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0xab); 13162e11d1bSHauke Mehrtens udelay(50); 13262e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13362e11d1bSHauke Mehrtens udelay(50); 13462e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x2b); 13562e11d1bSHauke Mehrtens udelay(50); 13662e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13762e11d1bSHauke Mehrtens udelay(50); 13862e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x10ab); 13962e11d1bSHauke Mehrtens udelay(50); 14062e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 14162e11d1bSHauke Mehrtens 14262e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { 14362e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x528); 14462e11d1bSHauke Mehrtens printk(KERN_EMERG 14562e11d1bSHauke Mehrtens "USB20H mdio_rddata 0x%08x\n", tmp); 14662e11d1bSHauke Mehrtens } 14762e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 14862e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x314); 14962e11d1bSHauke Mehrtens udelay(265); 15062e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 15162e11d1bSHauke Mehrtens udelay(10); 15262e11d1bSHauke Mehrtens 15362e11d1bSHauke Mehrtens /* Take USB and HSIC out of non-driving modes */ 15462e11d1bSHauke Mehrtens bcma_write32(dev, 0x510, 0); 15562e11d1bSHauke Mehrtens } else { 15662e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 15762e11d1bSHauke Mehrtens 15862e11d1bSHauke Mehrtens udelay(1); 15962e11d1bSHauke Mehrtens } 16062e11d1bSHauke Mehrtens 16162e11d1bSHauke Mehrtens bcma_hcd_4716wa(dev); 16262e11d1bSHauke Mehrtens } 16362e11d1bSHauke Mehrtens } 16462e11d1bSHauke Mehrtens 16510bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) 16610bc04b7SHauke Mehrtens { 16710bc04b7SHauke Mehrtens struct bcma_device *arm_core; 16810bc04b7SHauke Mehrtens void __iomem *dmu; 16910bc04b7SHauke Mehrtens 17010bc04b7SHauke Mehrtens arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); 17110bc04b7SHauke Mehrtens if (!arm_core) { 17210bc04b7SHauke Mehrtens dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); 17310bc04b7SHauke Mehrtens return; 17410bc04b7SHauke Mehrtens } 17510bc04b7SHauke Mehrtens 17610bc04b7SHauke Mehrtens dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); 17710bc04b7SHauke Mehrtens if (!dmu) { 17810bc04b7SHauke Mehrtens dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); 17910bc04b7SHauke Mehrtens return; 18010bc04b7SHauke Mehrtens } 18110bc04b7SHauke Mehrtens 18210bc04b7SHauke Mehrtens /* Unlock DMU PLL settings */ 18310bc04b7SHauke Mehrtens iowrite32(0x0000ea68, dmu + 0x180); 18410bc04b7SHauke Mehrtens 18510bc04b7SHauke Mehrtens /* Write USB 2.0 PLL control setting */ 18610bc04b7SHauke Mehrtens iowrite32(0x00dd10c3, dmu + 0x164); 18710bc04b7SHauke Mehrtens 18810bc04b7SHauke Mehrtens /* Lock DMU PLL settings */ 18910bc04b7SHauke Mehrtens iowrite32(0x00000000, dmu + 0x180); 19010bc04b7SHauke Mehrtens 19110bc04b7SHauke Mehrtens iounmap(dmu); 19210bc04b7SHauke Mehrtens } 19310bc04b7SHauke Mehrtens 19410bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) 19510bc04b7SHauke Mehrtens { 19610bc04b7SHauke Mehrtens u32 val; 19710bc04b7SHauke Mehrtens 19810bc04b7SHauke Mehrtens /* 19910bc04b7SHauke Mehrtens * Delay after PHY initialized to ensure HC is ready to be configured 20010bc04b7SHauke Mehrtens */ 20110bc04b7SHauke Mehrtens usleep_range(1000, 2000); 20210bc04b7SHauke Mehrtens 20310bc04b7SHauke Mehrtens /* Set packet buffer OUT threshold */ 20410bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x94); 20510bc04b7SHauke Mehrtens val &= 0xffff; 20610bc04b7SHauke Mehrtens val |= 0x80 << 16; 20710bc04b7SHauke Mehrtens bcma_write32(dev, 0x94, val); 20810bc04b7SHauke Mehrtens 20910bc04b7SHauke Mehrtens /* Enable break memory transfer */ 21010bc04b7SHauke Mehrtens val = bcma_read32(dev, 0x9c); 21110bc04b7SHauke Mehrtens val |= 1; 21210bc04b7SHauke Mehrtens bcma_write32(dev, 0x9c, val); 21310bc04b7SHauke Mehrtens } 21410bc04b7SHauke Mehrtens 21510bc04b7SHauke Mehrtens static void bcma_hcd_init_chip_arm(struct bcma_device *dev) 21610bc04b7SHauke Mehrtens { 21710bc04b7SHauke Mehrtens bcma_core_enable(dev, 0); 21810bc04b7SHauke Mehrtens 21910bc04b7SHauke Mehrtens if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || 22010bc04b7SHauke Mehrtens dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { 22110bc04b7SHauke Mehrtens if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || 22210bc04b7SHauke Mehrtens dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) 22310bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm_phy(dev); 22410bc04b7SHauke Mehrtens 22510bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm_hc(dev); 22610bc04b7SHauke Mehrtens } 22710bc04b7SHauke Mehrtens } 22810bc04b7SHauke Mehrtens 229eb4861c3SHauke Mehrtens static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) 230eb4861c3SHauke Mehrtens { 231eb4861c3SHauke Mehrtens int gpio; 232eb4861c3SHauke Mehrtens 233eb4861c3SHauke Mehrtens gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0); 234eb4861c3SHauke Mehrtens if (!gpio_is_valid(gpio)) 235eb4861c3SHauke Mehrtens return; 236eb4861c3SHauke Mehrtens 237eb4861c3SHauke Mehrtens if (val) { 238eb4861c3SHauke Mehrtens gpio_request(gpio, "bcma-hcd-gpio"); 239eb4861c3SHauke Mehrtens gpio_set_value(gpio, 1); 240eb4861c3SHauke Mehrtens } else { 241eb4861c3SHauke Mehrtens gpio_set_value(gpio, 0); 242eb4861c3SHauke Mehrtens gpio_free(gpio); 243eb4861c3SHauke Mehrtens } 244eb4861c3SHauke Mehrtens } 245eb4861c3SHauke Mehrtens 24662e11d1bSHauke Mehrtens static const struct usb_ehci_pdata ehci_pdata = { 24762e11d1bSHauke Mehrtens }; 24862e11d1bSHauke Mehrtens 24962e11d1bSHauke Mehrtens static const struct usb_ohci_pdata ohci_pdata = { 25062e11d1bSHauke Mehrtens }; 25162e11d1bSHauke Mehrtens 25241ac7b3aSBill Pemberton static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) 25362e11d1bSHauke Mehrtens { 25462e11d1bSHauke Mehrtens struct platform_device *hci_dev; 25562e11d1bSHauke Mehrtens struct resource hci_res[2]; 256ab2de579SHauke Mehrtens int ret; 25762e11d1bSHauke Mehrtens 25862e11d1bSHauke Mehrtens memset(hci_res, 0, sizeof(hci_res)); 25962e11d1bSHauke Mehrtens 26062e11d1bSHauke Mehrtens hci_res[0].start = addr; 26162e11d1bSHauke Mehrtens hci_res[0].end = hci_res[0].start + 0x1000 - 1; 26262e11d1bSHauke Mehrtens hci_res[0].flags = IORESOURCE_MEM; 26362e11d1bSHauke Mehrtens 26462e11d1bSHauke Mehrtens hci_res[1].start = dev->irq; 26562e11d1bSHauke Mehrtens hci_res[1].flags = IORESOURCE_IRQ; 26662e11d1bSHauke Mehrtens 26762e11d1bSHauke Mehrtens hci_dev = platform_device_alloc(ohci ? "ohci-platform" : 26862e11d1bSHauke Mehrtens "ehci-platform" , 0); 26962e11d1bSHauke Mehrtens if (!hci_dev) 270ab2de579SHauke Mehrtens return ERR_PTR(-ENOMEM); 27162e11d1bSHauke Mehrtens 27262e11d1bSHauke Mehrtens hci_dev->dev.parent = &dev->dev; 27362e11d1bSHauke Mehrtens hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; 27462e11d1bSHauke Mehrtens 27562e11d1bSHauke Mehrtens ret = platform_device_add_resources(hci_dev, hci_res, 27662e11d1bSHauke Mehrtens ARRAY_SIZE(hci_res)); 27762e11d1bSHauke Mehrtens if (ret) 27862e11d1bSHauke Mehrtens goto err_alloc; 27962e11d1bSHauke Mehrtens if (ohci) 28062e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ohci_pdata, 28162e11d1bSHauke Mehrtens sizeof(ohci_pdata)); 28262e11d1bSHauke Mehrtens else 28362e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ehci_pdata, 28462e11d1bSHauke Mehrtens sizeof(ehci_pdata)); 28562e11d1bSHauke Mehrtens if (ret) 28662e11d1bSHauke Mehrtens goto err_alloc; 28762e11d1bSHauke Mehrtens ret = platform_device_add(hci_dev); 28862e11d1bSHauke Mehrtens if (ret) 28962e11d1bSHauke Mehrtens goto err_alloc; 29062e11d1bSHauke Mehrtens 29162e11d1bSHauke Mehrtens return hci_dev; 29262e11d1bSHauke Mehrtens 29362e11d1bSHauke Mehrtens err_alloc: 29462e11d1bSHauke Mehrtens platform_device_put(hci_dev); 29562e11d1bSHauke Mehrtens return ERR_PTR(ret); 29662e11d1bSHauke Mehrtens } 29762e11d1bSHauke Mehrtens 29841ac7b3aSBill Pemberton static int bcma_hcd_probe(struct bcma_device *dev) 29962e11d1bSHauke Mehrtens { 30062e11d1bSHauke Mehrtens int err; 30162e11d1bSHauke Mehrtens u32 ohci_addr; 30262e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev; 30362e11d1bSHauke Mehrtens struct bcma_chipinfo *chipinfo; 30462e11d1bSHauke Mehrtens 30562e11d1bSHauke Mehrtens chipinfo = &dev->bus->chipinfo; 30662e11d1bSHauke Mehrtens 30762e11d1bSHauke Mehrtens /* TODO: Probably need checks here; is the core connected? */ 30862e11d1bSHauke Mehrtens 309d288059eSRussell King if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) 31062e11d1bSHauke Mehrtens return -EOPNOTSUPP; 31162e11d1bSHauke Mehrtens 312c27da2b2SHauke Mehrtens usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), 313c27da2b2SHauke Mehrtens GFP_KERNEL); 31462e11d1bSHauke Mehrtens if (!usb_dev) 31562e11d1bSHauke Mehrtens return -ENOMEM; 31662e11d1bSHauke Mehrtens 317eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, true); 318eb4861c3SHauke Mehrtens 31910bc04b7SHauke Mehrtens switch (dev->id.id) { 32010bc04b7SHauke Mehrtens case BCMA_CORE_NS_USB20: 32110bc04b7SHauke Mehrtens bcma_hcd_init_chip_arm(dev); 32210bc04b7SHauke Mehrtens break; 32310bc04b7SHauke Mehrtens case BCMA_CORE_USB20_HOST: 32410bc04b7SHauke Mehrtens bcma_hcd_init_chip_mips(dev); 32510bc04b7SHauke Mehrtens break; 32610bc04b7SHauke Mehrtens default: 32710bc04b7SHauke Mehrtens return -ENODEV; 32810bc04b7SHauke Mehrtens } 32962e11d1bSHauke Mehrtens 33062e11d1bSHauke Mehrtens /* In AI chips EHCI is addrspace 0, OHCI is 1 */ 33123a2f39cSHauke Mehrtens ohci_addr = dev->addr_s[0]; 33298e13e05SHauke Mehrtens if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || 33398e13e05SHauke Mehrtens chipinfo->id == BCMA_CHIP_ID_BCM4749) 33462e11d1bSHauke Mehrtens && chipinfo->rev == 0) 33562e11d1bSHauke Mehrtens ohci_addr = 0x18009000; 33662e11d1bSHauke Mehrtens 33762e11d1bSHauke Mehrtens usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); 338c27da2b2SHauke Mehrtens if (IS_ERR(usb_dev->ohci_dev)) 339c27da2b2SHauke Mehrtens return PTR_ERR(usb_dev->ohci_dev); 34062e11d1bSHauke Mehrtens 34162e11d1bSHauke Mehrtens usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); 34262e11d1bSHauke Mehrtens if (IS_ERR(usb_dev->ehci_dev)) { 34362e11d1bSHauke Mehrtens err = PTR_ERR(usb_dev->ehci_dev); 34462e11d1bSHauke Mehrtens goto err_unregister_ohci_dev; 34562e11d1bSHauke Mehrtens } 34662e11d1bSHauke Mehrtens 34762e11d1bSHauke Mehrtens bcma_set_drvdata(dev, usb_dev); 34862e11d1bSHauke Mehrtens return 0; 34962e11d1bSHauke Mehrtens 35062e11d1bSHauke Mehrtens err_unregister_ohci_dev: 35162e11d1bSHauke Mehrtens platform_device_unregister(usb_dev->ohci_dev); 35262e11d1bSHauke Mehrtens return err; 35362e11d1bSHauke Mehrtens } 35462e11d1bSHauke Mehrtens 355fb4e98abSBill Pemberton static void bcma_hcd_remove(struct bcma_device *dev) 35662e11d1bSHauke Mehrtens { 35762e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 35862e11d1bSHauke Mehrtens struct platform_device *ohci_dev = usb_dev->ohci_dev; 35962e11d1bSHauke Mehrtens struct platform_device *ehci_dev = usb_dev->ehci_dev; 36062e11d1bSHauke Mehrtens 36162e11d1bSHauke Mehrtens if (ohci_dev) 36262e11d1bSHauke Mehrtens platform_device_unregister(ohci_dev); 36362e11d1bSHauke Mehrtens if (ehci_dev) 36462e11d1bSHauke Mehrtens platform_device_unregister(ehci_dev); 36562e11d1bSHauke Mehrtens 36662e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 36762e11d1bSHauke Mehrtens } 36862e11d1bSHauke Mehrtens 36962e11d1bSHauke Mehrtens static void bcma_hcd_shutdown(struct bcma_device *dev) 37062e11d1bSHauke Mehrtens { 371eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false); 37262e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 37362e11d1bSHauke Mehrtens } 37462e11d1bSHauke Mehrtens 37562e11d1bSHauke Mehrtens #ifdef CONFIG_PM 37662e11d1bSHauke Mehrtens 3771f6155f5SDan Carpenter static int bcma_hcd_suspend(struct bcma_device *dev) 37862e11d1bSHauke Mehrtens { 379eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, false); 38062e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 38162e11d1bSHauke Mehrtens 38262e11d1bSHauke Mehrtens return 0; 38362e11d1bSHauke Mehrtens } 38462e11d1bSHauke Mehrtens 38562e11d1bSHauke Mehrtens static int bcma_hcd_resume(struct bcma_device *dev) 38662e11d1bSHauke Mehrtens { 387eb4861c3SHauke Mehrtens bcma_hci_platform_power_gpio(dev, true); 38862e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 38962e11d1bSHauke Mehrtens 39062e11d1bSHauke Mehrtens return 0; 39162e11d1bSHauke Mehrtens } 39262e11d1bSHauke Mehrtens 39362e11d1bSHauke Mehrtens #else /* !CONFIG_PM */ 39462e11d1bSHauke Mehrtens #define bcma_hcd_suspend NULL 39562e11d1bSHauke Mehrtens #define bcma_hcd_resume NULL 39662e11d1bSHauke Mehrtens #endif /* CONFIG_PM */ 39762e11d1bSHauke Mehrtens 3982f82686eSBill Pemberton static const struct bcma_device_id bcma_hcd_table[] = { 39962e11d1bSHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), 40010bc04b7SHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), 401f7219b52SJoe Perches {}, 40262e11d1bSHauke Mehrtens }; 40362e11d1bSHauke Mehrtens MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); 40462e11d1bSHauke Mehrtens 40562e11d1bSHauke Mehrtens static struct bcma_driver bcma_hcd_driver = { 40662e11d1bSHauke Mehrtens .name = KBUILD_MODNAME, 40762e11d1bSHauke Mehrtens .id_table = bcma_hcd_table, 40862e11d1bSHauke Mehrtens .probe = bcma_hcd_probe, 4097690417dSBill Pemberton .remove = bcma_hcd_remove, 41062e11d1bSHauke Mehrtens .shutdown = bcma_hcd_shutdown, 41162e11d1bSHauke Mehrtens .suspend = bcma_hcd_suspend, 41262e11d1bSHauke Mehrtens .resume = bcma_hcd_resume, 41362e11d1bSHauke Mehrtens }; 41462e11d1bSHauke Mehrtens 41562e11d1bSHauke Mehrtens static int __init bcma_hcd_init(void) 41662e11d1bSHauke Mehrtens { 41762e11d1bSHauke Mehrtens return bcma_driver_register(&bcma_hcd_driver); 41862e11d1bSHauke Mehrtens } 41962e11d1bSHauke Mehrtens module_init(bcma_hcd_init); 42062e11d1bSHauke Mehrtens 42162e11d1bSHauke Mehrtens static void __exit bcma_hcd_exit(void) 42262e11d1bSHauke Mehrtens { 42362e11d1bSHauke Mehrtens bcma_driver_unregister(&bcma_hcd_driver); 42462e11d1bSHauke Mehrtens } 42562e11d1bSHauke Mehrtens module_exit(bcma_hcd_exit); 426