xref: /openbmc/linux/drivers/usb/host/bcma-hcd.c (revision 1f6155f5)
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