162e11d1bSHauke Mehrtens /* 262e11d1bSHauke Mehrtens * Broadcom specific Advanced Microcontroller Bus 362e11d1bSHauke Mehrtens * Broadcom USB-core driver (BCMA bus glue) 462e11d1bSHauke Mehrtens * 562e11d1bSHauke Mehrtens * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> 662e11d1bSHauke Mehrtens * 762e11d1bSHauke Mehrtens * Based on ssb-ohci driver 862e11d1bSHauke Mehrtens * Copyright 2007 Michael Buesch <m@bues.ch> 962e11d1bSHauke Mehrtens * 1062e11d1bSHauke Mehrtens * Derived from the OHCI-PCI driver 1162e11d1bSHauke Mehrtens * Copyright 1999 Roman Weissgaerber 1262e11d1bSHauke Mehrtens * Copyright 2000-2002 David Brownell 1362e11d1bSHauke Mehrtens * Copyright 1999 Linus Torvalds 1462e11d1bSHauke Mehrtens * Copyright 1999 Gregory P. Smith 1562e11d1bSHauke Mehrtens * 1662e11d1bSHauke Mehrtens * Derived from the USBcore related parts of Broadcom-SB 1762e11d1bSHauke Mehrtens * Copyright 2005-2011 Broadcom Corporation 1862e11d1bSHauke Mehrtens * 1962e11d1bSHauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details. 2062e11d1bSHauke Mehrtens */ 2162e11d1bSHauke Mehrtens #include <linux/bcma/bcma.h> 2262e11d1bSHauke Mehrtens #include <linux/delay.h> 2362e11d1bSHauke Mehrtens #include <linux/platform_device.h> 2462e11d1bSHauke Mehrtens #include <linux/module.h> 2562e11d1bSHauke Mehrtens #include <linux/usb/ehci_pdriver.h> 2662e11d1bSHauke Mehrtens #include <linux/usb/ohci_pdriver.h> 2762e11d1bSHauke Mehrtens 2862e11d1bSHauke Mehrtens MODULE_AUTHOR("Hauke Mehrtens"); 2962e11d1bSHauke Mehrtens MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); 3062e11d1bSHauke Mehrtens MODULE_LICENSE("GPL"); 3162e11d1bSHauke Mehrtens 3262e11d1bSHauke Mehrtens struct bcma_hcd_device { 3362e11d1bSHauke Mehrtens struct platform_device *ehci_dev; 3462e11d1bSHauke Mehrtens struct platform_device *ohci_dev; 3562e11d1bSHauke Mehrtens }; 3662e11d1bSHauke Mehrtens 3762e11d1bSHauke Mehrtens /* Wait for bitmask in a register to get set or cleared. 3862e11d1bSHauke Mehrtens * timeout is in units of ten-microseconds. 3962e11d1bSHauke Mehrtens */ 4062e11d1bSHauke Mehrtens static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, 4162e11d1bSHauke Mehrtens int timeout) 4262e11d1bSHauke Mehrtens { 4362e11d1bSHauke Mehrtens int i; 4462e11d1bSHauke Mehrtens u32 val; 4562e11d1bSHauke Mehrtens 4662e11d1bSHauke Mehrtens for (i = 0; i < timeout; i++) { 4762e11d1bSHauke Mehrtens val = bcma_read32(dev, reg); 4862e11d1bSHauke Mehrtens if ((val & bitmask) == bitmask) 4962e11d1bSHauke Mehrtens return 0; 5062e11d1bSHauke Mehrtens udelay(10); 5162e11d1bSHauke Mehrtens } 5262e11d1bSHauke Mehrtens 5362e11d1bSHauke Mehrtens return -ETIMEDOUT; 5462e11d1bSHauke Mehrtens } 5562e11d1bSHauke Mehrtens 5662e11d1bSHauke Mehrtens static void __devinit bcma_hcd_4716wa(struct bcma_device *dev) 5762e11d1bSHauke Mehrtens { 5862e11d1bSHauke Mehrtens #ifdef CONFIG_BCMA_DRIVER_MIPS 5962e11d1bSHauke Mehrtens /* Work around for 4716 failures. */ 6062e11d1bSHauke Mehrtens if (dev->bus->chipinfo.id == 0x4716) { 6162e11d1bSHauke Mehrtens u32 tmp; 6262e11d1bSHauke Mehrtens 6362e11d1bSHauke Mehrtens tmp = bcma_cpu_clock(&dev->bus->drv_mips); 6462e11d1bSHauke Mehrtens if (tmp >= 480000000) 6562e11d1bSHauke Mehrtens tmp = 0x1846b; /* set CDR to 0x11(fast) */ 6662e11d1bSHauke Mehrtens else if (tmp == 453000000) 6762e11d1bSHauke Mehrtens tmp = 0x1046b; /* set CDR to 0x10(slow) */ 6862e11d1bSHauke Mehrtens else 6962e11d1bSHauke Mehrtens tmp = 0; 7062e11d1bSHauke Mehrtens 7162e11d1bSHauke Mehrtens /* Change Shim mdio control reg to fix host not acking at 7262e11d1bSHauke Mehrtens * high frequencies 7362e11d1bSHauke Mehrtens */ 7462e11d1bSHauke Mehrtens if (tmp) { 7562e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ 7662e11d1bSHauke Mehrtens udelay(500); 7762e11d1bSHauke Mehrtens 7862e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, tmp); 7962e11d1bSHauke Mehrtens udelay(500); 8062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x4ab); 8162e11d1bSHauke Mehrtens udelay(500); 8262e11d1bSHauke Mehrtens bcma_read32(dev, 0x528); 8362e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 8462e11d1bSHauke Mehrtens } 8562e11d1bSHauke Mehrtens } 8662e11d1bSHauke Mehrtens #endif /* CONFIG_BCMA_DRIVER_MIPS */ 8762e11d1bSHauke Mehrtens } 8862e11d1bSHauke Mehrtens 8962e11d1bSHauke Mehrtens /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ 9062e11d1bSHauke Mehrtens static void __devinit bcma_hcd_init_chip(struct bcma_device *dev) 9162e11d1bSHauke Mehrtens { 9262e11d1bSHauke Mehrtens u32 tmp; 9362e11d1bSHauke Mehrtens 9462e11d1bSHauke Mehrtens /* 9562e11d1bSHauke Mehrtens * USB 2.0 special considerations: 9662e11d1bSHauke Mehrtens * 9762e11d1bSHauke Mehrtens * 1. Since the core supports both OHCI and EHCI functions, it must 9862e11d1bSHauke Mehrtens * only be reset once. 9962e11d1bSHauke Mehrtens * 10062e11d1bSHauke Mehrtens * 2. In addition to the standard SI reset sequence, the Host Control 10162e11d1bSHauke Mehrtens * Register must be programmed to bring the USB core and various 10262e11d1bSHauke Mehrtens * phy components out of reset. 10362e11d1bSHauke Mehrtens */ 10462e11d1bSHauke Mehrtens if (!bcma_core_is_enabled(dev)) { 10562e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 10662e11d1bSHauke Mehrtens mdelay(10); 10762e11d1bSHauke Mehrtens if (dev->id.rev >= 5) { 10862e11d1bSHauke Mehrtens /* Enable Misc PLL */ 10962e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x1e0); 11062e11d1bSHauke Mehrtens tmp |= 0x100; 11162e11d1bSHauke Mehrtens bcma_write32(dev, 0x1e0, tmp); 11262e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) 11362e11d1bSHauke Mehrtens printk(KERN_EMERG "Failed to enable misc PPL!\n"); 11462e11d1bSHauke Mehrtens 11562e11d1bSHauke Mehrtens /* Take out of resets */ 11662e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x4ff); 11762e11d1bSHauke Mehrtens udelay(25); 11862e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x6ff); 11962e11d1bSHauke Mehrtens udelay(25); 12062e11d1bSHauke Mehrtens 12162e11d1bSHauke Mehrtens /* Make sure digital and AFE are locked in USB PHY */ 12262e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x6b); 12362e11d1bSHauke Mehrtens udelay(50); 12462e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 12562e11d1bSHauke Mehrtens udelay(50); 12662e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0xab); 12762e11d1bSHauke Mehrtens udelay(50); 12862e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 12962e11d1bSHauke Mehrtens udelay(50); 13062e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x2b); 13162e11d1bSHauke Mehrtens udelay(50); 13262e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13362e11d1bSHauke Mehrtens udelay(50); 13462e11d1bSHauke Mehrtens bcma_write32(dev, 0x524, 0x10ab); 13562e11d1bSHauke Mehrtens udelay(50); 13662e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x524); 13762e11d1bSHauke Mehrtens 13862e11d1bSHauke Mehrtens if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { 13962e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x528); 14062e11d1bSHauke Mehrtens printk(KERN_EMERG 14162e11d1bSHauke Mehrtens "USB20H mdio_rddata 0x%08x\n", tmp); 14262e11d1bSHauke Mehrtens } 14362e11d1bSHauke Mehrtens bcma_write32(dev, 0x528, 0x80000000); 14462e11d1bSHauke Mehrtens tmp = bcma_read32(dev, 0x314); 14562e11d1bSHauke Mehrtens udelay(265); 14662e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 14762e11d1bSHauke Mehrtens udelay(10); 14862e11d1bSHauke Mehrtens 14962e11d1bSHauke Mehrtens /* Take USB and HSIC out of non-driving modes */ 15062e11d1bSHauke Mehrtens bcma_write32(dev, 0x510, 0); 15162e11d1bSHauke Mehrtens } else { 15262e11d1bSHauke Mehrtens bcma_write32(dev, 0x200, 0x7ff); 15362e11d1bSHauke Mehrtens 15462e11d1bSHauke Mehrtens udelay(1); 15562e11d1bSHauke Mehrtens } 15662e11d1bSHauke Mehrtens 15762e11d1bSHauke Mehrtens bcma_hcd_4716wa(dev); 15862e11d1bSHauke Mehrtens } 15962e11d1bSHauke Mehrtens } 16062e11d1bSHauke Mehrtens 16162e11d1bSHauke Mehrtens static const struct usb_ehci_pdata ehci_pdata = { 16262e11d1bSHauke Mehrtens }; 16362e11d1bSHauke Mehrtens 16462e11d1bSHauke Mehrtens static const struct usb_ohci_pdata ohci_pdata = { 16562e11d1bSHauke Mehrtens }; 16662e11d1bSHauke Mehrtens 16762e11d1bSHauke Mehrtens static struct platform_device * __devinit 16862e11d1bSHauke Mehrtens bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) 16962e11d1bSHauke Mehrtens { 17062e11d1bSHauke Mehrtens struct platform_device *hci_dev; 17162e11d1bSHauke Mehrtens struct resource hci_res[2]; 17262e11d1bSHauke Mehrtens int ret = -ENOMEM; 17362e11d1bSHauke Mehrtens 17462e11d1bSHauke Mehrtens memset(hci_res, 0, sizeof(hci_res)); 17562e11d1bSHauke Mehrtens 17662e11d1bSHauke Mehrtens hci_res[0].start = addr; 17762e11d1bSHauke Mehrtens hci_res[0].end = hci_res[0].start + 0x1000 - 1; 17862e11d1bSHauke Mehrtens hci_res[0].flags = IORESOURCE_MEM; 17962e11d1bSHauke Mehrtens 18062e11d1bSHauke Mehrtens hci_res[1].start = dev->irq; 18162e11d1bSHauke Mehrtens hci_res[1].flags = IORESOURCE_IRQ; 18262e11d1bSHauke Mehrtens 18362e11d1bSHauke Mehrtens hci_dev = platform_device_alloc(ohci ? "ohci-platform" : 18462e11d1bSHauke Mehrtens "ehci-platform" , 0); 18562e11d1bSHauke Mehrtens if (!hci_dev) 18662e11d1bSHauke Mehrtens return NULL; 18762e11d1bSHauke Mehrtens 18862e11d1bSHauke Mehrtens hci_dev->dev.parent = &dev->dev; 18962e11d1bSHauke Mehrtens hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; 19062e11d1bSHauke Mehrtens 19162e11d1bSHauke Mehrtens ret = platform_device_add_resources(hci_dev, hci_res, 19262e11d1bSHauke Mehrtens ARRAY_SIZE(hci_res)); 19362e11d1bSHauke Mehrtens if (ret) 19462e11d1bSHauke Mehrtens goto err_alloc; 19562e11d1bSHauke Mehrtens if (ohci) 19662e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ohci_pdata, 19762e11d1bSHauke Mehrtens sizeof(ohci_pdata)); 19862e11d1bSHauke Mehrtens else 19962e11d1bSHauke Mehrtens ret = platform_device_add_data(hci_dev, &ehci_pdata, 20062e11d1bSHauke Mehrtens sizeof(ehci_pdata)); 20162e11d1bSHauke Mehrtens if (ret) 20262e11d1bSHauke Mehrtens goto err_alloc; 20362e11d1bSHauke Mehrtens ret = platform_device_add(hci_dev); 20462e11d1bSHauke Mehrtens if (ret) 20562e11d1bSHauke Mehrtens goto err_alloc; 20662e11d1bSHauke Mehrtens 20762e11d1bSHauke Mehrtens return hci_dev; 20862e11d1bSHauke Mehrtens 20962e11d1bSHauke Mehrtens err_alloc: 21062e11d1bSHauke Mehrtens platform_device_put(hci_dev); 21162e11d1bSHauke Mehrtens return ERR_PTR(ret); 21262e11d1bSHauke Mehrtens } 21362e11d1bSHauke Mehrtens 21462e11d1bSHauke Mehrtens static int __devinit bcma_hcd_probe(struct bcma_device *dev) 21562e11d1bSHauke Mehrtens { 21662e11d1bSHauke Mehrtens int err; 21762e11d1bSHauke Mehrtens u16 chipid_top; 21862e11d1bSHauke Mehrtens u32 ohci_addr; 21962e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev; 22062e11d1bSHauke Mehrtens struct bcma_chipinfo *chipinfo; 22162e11d1bSHauke Mehrtens 22262e11d1bSHauke Mehrtens chipinfo = &dev->bus->chipinfo; 22362e11d1bSHauke Mehrtens /* USBcores are only connected on embedded devices. */ 22462e11d1bSHauke Mehrtens chipid_top = (chipinfo->id & 0xFF00); 22562e11d1bSHauke Mehrtens if (chipid_top != 0x4700 && chipid_top != 0x5300) 22662e11d1bSHauke Mehrtens return -ENODEV; 22762e11d1bSHauke Mehrtens 22862e11d1bSHauke Mehrtens /* TODO: Probably need checks here; is the core connected? */ 22962e11d1bSHauke Mehrtens 23062e11d1bSHauke Mehrtens if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || 23162e11d1bSHauke Mehrtens dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) 23262e11d1bSHauke Mehrtens return -EOPNOTSUPP; 23362e11d1bSHauke Mehrtens 23462e11d1bSHauke Mehrtens usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL); 23562e11d1bSHauke Mehrtens if (!usb_dev) 23662e11d1bSHauke Mehrtens return -ENOMEM; 23762e11d1bSHauke Mehrtens 23862e11d1bSHauke Mehrtens bcma_hcd_init_chip(dev); 23962e11d1bSHauke Mehrtens 24062e11d1bSHauke Mehrtens /* In AI chips EHCI is addrspace 0, OHCI is 1 */ 24162e11d1bSHauke Mehrtens ohci_addr = dev->addr1; 24262e11d1bSHauke Mehrtens if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749) 24362e11d1bSHauke Mehrtens && chipinfo->rev == 0) 24462e11d1bSHauke Mehrtens ohci_addr = 0x18009000; 24562e11d1bSHauke Mehrtens 24662e11d1bSHauke Mehrtens usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); 24762e11d1bSHauke Mehrtens if (IS_ERR(usb_dev->ohci_dev)) { 24862e11d1bSHauke Mehrtens err = PTR_ERR(usb_dev->ohci_dev); 24962e11d1bSHauke Mehrtens goto err_free_usb_dev; 25062e11d1bSHauke Mehrtens } 25162e11d1bSHauke Mehrtens 25262e11d1bSHauke Mehrtens usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); 25362e11d1bSHauke Mehrtens if (IS_ERR(usb_dev->ehci_dev)) { 25462e11d1bSHauke Mehrtens err = PTR_ERR(usb_dev->ehci_dev); 25562e11d1bSHauke Mehrtens goto err_unregister_ohci_dev; 25662e11d1bSHauke Mehrtens } 25762e11d1bSHauke Mehrtens 25862e11d1bSHauke Mehrtens bcma_set_drvdata(dev, usb_dev); 25962e11d1bSHauke Mehrtens return 0; 26062e11d1bSHauke Mehrtens 26162e11d1bSHauke Mehrtens err_unregister_ohci_dev: 26262e11d1bSHauke Mehrtens platform_device_unregister(usb_dev->ohci_dev); 26362e11d1bSHauke Mehrtens err_free_usb_dev: 26462e11d1bSHauke Mehrtens kfree(usb_dev); 26562e11d1bSHauke Mehrtens return err; 26662e11d1bSHauke Mehrtens } 26762e11d1bSHauke Mehrtens 26862e11d1bSHauke Mehrtens static void __devexit bcma_hcd_remove(struct bcma_device *dev) 26962e11d1bSHauke Mehrtens { 27062e11d1bSHauke Mehrtens struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 27162e11d1bSHauke Mehrtens struct platform_device *ohci_dev = usb_dev->ohci_dev; 27262e11d1bSHauke Mehrtens struct platform_device *ehci_dev = usb_dev->ehci_dev; 27362e11d1bSHauke Mehrtens 27462e11d1bSHauke Mehrtens if (ohci_dev) 27562e11d1bSHauke Mehrtens platform_device_unregister(ohci_dev); 27662e11d1bSHauke Mehrtens if (ehci_dev) 27762e11d1bSHauke Mehrtens platform_device_unregister(ehci_dev); 27862e11d1bSHauke Mehrtens 27962e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 28062e11d1bSHauke Mehrtens } 28162e11d1bSHauke Mehrtens 28262e11d1bSHauke Mehrtens static void bcma_hcd_shutdown(struct bcma_device *dev) 28362e11d1bSHauke Mehrtens { 28462e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 28562e11d1bSHauke Mehrtens } 28662e11d1bSHauke Mehrtens 28762e11d1bSHauke Mehrtens #ifdef CONFIG_PM 28862e11d1bSHauke Mehrtens 2891f6155f5SDan Carpenter static int bcma_hcd_suspend(struct bcma_device *dev) 29062e11d1bSHauke Mehrtens { 29162e11d1bSHauke Mehrtens bcma_core_disable(dev, 0); 29262e11d1bSHauke Mehrtens 29362e11d1bSHauke Mehrtens return 0; 29462e11d1bSHauke Mehrtens } 29562e11d1bSHauke Mehrtens 29662e11d1bSHauke Mehrtens static int bcma_hcd_resume(struct bcma_device *dev) 29762e11d1bSHauke Mehrtens { 29862e11d1bSHauke Mehrtens bcma_core_enable(dev, 0); 29962e11d1bSHauke Mehrtens 30062e11d1bSHauke Mehrtens return 0; 30162e11d1bSHauke Mehrtens } 30262e11d1bSHauke Mehrtens 30362e11d1bSHauke Mehrtens #else /* !CONFIG_PM */ 30462e11d1bSHauke Mehrtens #define bcma_hcd_suspend NULL 30562e11d1bSHauke Mehrtens #define bcma_hcd_resume NULL 30662e11d1bSHauke Mehrtens #endif /* CONFIG_PM */ 30762e11d1bSHauke Mehrtens 30862e11d1bSHauke Mehrtens static const struct bcma_device_id bcma_hcd_table[] __devinitconst = { 30962e11d1bSHauke Mehrtens BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), 31062e11d1bSHauke Mehrtens BCMA_CORETABLE_END 31162e11d1bSHauke Mehrtens }; 31262e11d1bSHauke Mehrtens MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); 31362e11d1bSHauke Mehrtens 31462e11d1bSHauke Mehrtens static struct bcma_driver bcma_hcd_driver = { 31562e11d1bSHauke Mehrtens .name = KBUILD_MODNAME, 31662e11d1bSHauke Mehrtens .id_table = bcma_hcd_table, 31762e11d1bSHauke Mehrtens .probe = bcma_hcd_probe, 31862e11d1bSHauke Mehrtens .remove = __devexit_p(bcma_hcd_remove), 31962e11d1bSHauke Mehrtens .shutdown = bcma_hcd_shutdown, 32062e11d1bSHauke Mehrtens .suspend = bcma_hcd_suspend, 32162e11d1bSHauke Mehrtens .resume = bcma_hcd_resume, 32262e11d1bSHauke Mehrtens }; 32362e11d1bSHauke Mehrtens 32462e11d1bSHauke Mehrtens static int __init bcma_hcd_init(void) 32562e11d1bSHauke Mehrtens { 32662e11d1bSHauke Mehrtens return bcma_driver_register(&bcma_hcd_driver); 32762e11d1bSHauke Mehrtens } 32862e11d1bSHauke Mehrtens module_init(bcma_hcd_init); 32962e11d1bSHauke Mehrtens 33062e11d1bSHauke Mehrtens static void __exit bcma_hcd_exit(void) 33162e11d1bSHauke Mehrtens { 33262e11d1bSHauke Mehrtens bcma_driver_unregister(&bcma_hcd_driver); 33362e11d1bSHauke Mehrtens } 33462e11d1bSHauke Mehrtens module_exit(bcma_hcd_exit); 335