xref: /linux/drivers/usb/host/ohci-pxa27x.c (revision 0c27c5d5b93339df4def7ced77ea5be26df4d84b)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * OHCI HCD (Host Controller Driver) for USB.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
51da177e4SLinus Torvalds  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
61da177e4SLinus Torvalds  * (C) Copyright 2002 Hewlett-Packard Company
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * Bus Glue for pxa27x
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Written by Christopher Hoover <ch@hpl.hp.com>
111da177e4SLinus Torvalds  * Based on fragments of previous driver by Russell King et al.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  * Modified for LH7A404 from ohci-sa1111.c
141da177e4SLinus Torvalds  *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  * Modified for pxa27x from ohci-lh7a404.c
171da177e4SLinus Torvalds  *  by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
181da177e4SLinus Torvalds  *
191da177e4SLinus Torvalds  * This file is licenced under the GPL.
201da177e4SLinus Torvalds  */
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds #include <linux/device.h>
234e57b681STim Schmielau #include <linux/signal.h>
24d052d1beSRussell King #include <linux/platform_device.h>
254fd5f826SLinus Torvalds 
261da177e4SLinus Torvalds #include <asm/mach-types.h>
271da177e4SLinus Torvalds #include <asm/hardware.h>
281da177e4SLinus Torvalds #include <asm/arch/pxa-regs.h>
2981f280e2SRichard Purdie #include <asm/arch/ohci.h>
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #define PXA_UHC_MAX_PORTNUM    3
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds #define UHCRHPS(x)              __REG2( 0x4C000050, (x)<<2 )
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds /*
361da177e4SLinus Torvalds   PMM_NPS_MODE -- PMM Non-power switching mode
371da177e4SLinus Torvalds       Ports are powered continuously.
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds   PMM_GLOBAL_MODE -- PMM global switching mode
401da177e4SLinus Torvalds       All ports are powered at the same time.
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds   PMM_PERPORT_MODE -- PMM per port switching mode
431da177e4SLinus Torvalds       Ports are powered individually.
441da177e4SLinus Torvalds  */
451da177e4SLinus Torvalds static int pxa27x_ohci_select_pmm( int mode )
461da177e4SLinus Torvalds {
471da177e4SLinus Torvalds 	switch ( mode ) {
481da177e4SLinus Torvalds 	case PMM_NPS_MODE:
491da177e4SLinus Torvalds 		UHCRHDA |= RH_A_NPS;
501da177e4SLinus Torvalds 		break;
511da177e4SLinus Torvalds 	case PMM_GLOBAL_MODE:
521da177e4SLinus Torvalds 		UHCRHDA &= ~(RH_A_NPS & RH_A_PSM);
531da177e4SLinus Torvalds 		break;
541da177e4SLinus Torvalds 	case PMM_PERPORT_MODE:
551da177e4SLinus Torvalds 		UHCRHDA &= ~(RH_A_NPS);
561da177e4SLinus Torvalds 		UHCRHDA |= RH_A_PSM;
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds 		/* Set port power control mask bits, only 3 ports. */
591da177e4SLinus Torvalds 		UHCRHDB |= (0x7<<17);
601da177e4SLinus Torvalds 		break;
611da177e4SLinus Torvalds 	default:
621da177e4SLinus Torvalds 		printk( KERN_ERR
631da177e4SLinus Torvalds 			"Invalid mode %d, set to non-power switch mode.\n",
641da177e4SLinus Torvalds 			mode );
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds 		UHCRHDA |= RH_A_NPS;
671da177e4SLinus Torvalds 	}
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	return 0;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds extern int usb_disabled(void);
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/
751da177e4SLinus Torvalds 
7681f280e2SRichard Purdie static int pxa27x_start_hc(struct device *dev)
771da177e4SLinus Torvalds {
7881f280e2SRichard Purdie 	int retval = 0;
7981f280e2SRichard Purdie 	struct pxaohci_platform_data *inf;
8081f280e2SRichard Purdie 
8181f280e2SRichard Purdie 	inf = dev->platform_data;
8281f280e2SRichard Purdie 
831da177e4SLinus Torvalds 	pxa_set_cken(CKEN10_USBHOST, 1);
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	UHCHR |= UHCHR_FHR;
861da177e4SLinus Torvalds 	udelay(11);
871da177e4SLinus Torvalds 	UHCHR &= ~UHCHR_FHR;
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds 	UHCHR |= UHCHR_FSBIR;
901da177e4SLinus Torvalds 	while (UHCHR & UHCHR_FSBIR)
911da177e4SLinus Torvalds 		cpu_relax();
921da177e4SLinus Torvalds 
9381f280e2SRichard Purdie 	if (inf->init)
9481f280e2SRichard Purdie 		retval = inf->init(dev);
951da177e4SLinus Torvalds 
9681f280e2SRichard Purdie 	if (retval < 0)
9781f280e2SRichard Purdie 		return retval;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	UHCHR &= ~UHCHR_SSE;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
102155faf5eSDavid Brownell 
103155faf5eSDavid Brownell 	/* Clear any OTG Pin Hold */
104155faf5eSDavid Brownell 	if (PSSR & PSSR_OTGPH)
105155faf5eSDavid Brownell 		PSSR |= PSSR_OTGPH;
10681f280e2SRichard Purdie 
10781f280e2SRichard Purdie 	return 0;
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds 
11081f280e2SRichard Purdie static void pxa27x_stop_hc(struct device *dev)
1111da177e4SLinus Torvalds {
11281f280e2SRichard Purdie 	struct pxaohci_platform_data *inf;
11381f280e2SRichard Purdie 
11481f280e2SRichard Purdie 	inf = dev->platform_data;
11581f280e2SRichard Purdie 
11681f280e2SRichard Purdie 	if (inf->exit)
11781f280e2SRichard Purdie 		inf->exit(dev);
11881f280e2SRichard Purdie 
1191da177e4SLinus Torvalds 	UHCHR |= UHCHR_FHR;
1201da177e4SLinus Torvalds 	udelay(11);
1211da177e4SLinus Torvalds 	UHCHR &= ~UHCHR_FHR;
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds 	UHCCOMS |= 1;
1241da177e4SLinus Torvalds 	udelay(10);
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds 	pxa_set_cken(CKEN10_USBHOST, 0);
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds /* configure so an HC device and id are always provided */
1331da177e4SLinus Torvalds /* always called with process context; sleeping is OK */
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /**
1371da177e4SLinus Torvalds  * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs
1381da177e4SLinus Torvalds  * Context: !in_interrupt()
1391da177e4SLinus Torvalds  *
1401da177e4SLinus Torvalds  * Allocates basic resources for this USB host controller, and
1411da177e4SLinus Torvalds  * then invokes the start() method for the HCD associated with it
1421da177e4SLinus Torvalds  * through the hotplug entry's driver_data.
1431da177e4SLinus Torvalds  *
1441da177e4SLinus Torvalds  */
14581f280e2SRichard Purdie int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
1461da177e4SLinus Torvalds {
1471da177e4SLinus Torvalds 	int retval;
1481da177e4SLinus Torvalds 	struct usb_hcd *hcd;
14981f280e2SRichard Purdie 	struct pxaohci_platform_data *inf;
1501da177e4SLinus Torvalds 
15181f280e2SRichard Purdie 	inf = pdev->dev.platform_data;
15281f280e2SRichard Purdie 
15381f280e2SRichard Purdie 	if (!inf)
15481f280e2SRichard Purdie 		return -ENODEV;
15581f280e2SRichard Purdie 
15681f280e2SRichard Purdie 	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
1571da177e4SLinus Torvalds 		pr_debug ("resource[1] is not IORESOURCE_IRQ");
1581da177e4SLinus Torvalds 		return -ENOMEM;
1591da177e4SLinus Torvalds 	}
1601da177e4SLinus Torvalds 
16181f280e2SRichard Purdie 	hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
1621da177e4SLinus Torvalds 	if (!hcd)
1631da177e4SLinus Torvalds 		return -ENOMEM;
16481f280e2SRichard Purdie 	hcd->rsrc_start = pdev->resource[0].start;
16581f280e2SRichard Purdie 	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
1681da177e4SLinus Torvalds 		pr_debug("request_mem_region failed");
1691da177e4SLinus Torvalds 		retval = -EBUSY;
1701da177e4SLinus Torvalds 		goto err1;
1711da177e4SLinus Torvalds 	}
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1741da177e4SLinus Torvalds 	if (!hcd->regs) {
1751da177e4SLinus Torvalds 		pr_debug("ioremap failed");
1761da177e4SLinus Torvalds 		retval = -ENOMEM;
1771da177e4SLinus Torvalds 		goto err2;
1781da177e4SLinus Torvalds 	}
1791da177e4SLinus Torvalds 
18081f280e2SRichard Purdie 	if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
18181f280e2SRichard Purdie 		pr_debug("pxa27x_start_hc failed");
18281f280e2SRichard Purdie 		goto err3;
18381f280e2SRichard Purdie 	}
1841da177e4SLinus Torvalds 
1851da177e4SLinus Torvalds 	/* Select Power Management Mode */
18681f280e2SRichard Purdie 	pxa27x_ohci_select_pmm(inf->port_mode);
1871da177e4SLinus Torvalds 
188*0c27c5d5SRichard Purdie 	if (inf->power_budget)
189*0c27c5d5SRichard Purdie 		hcd->power_budget = inf->power_budget;
190*0c27c5d5SRichard Purdie 
1911da177e4SLinus Torvalds 	ohci_hcd_init(hcd_to_ohci(hcd));
1921da177e4SLinus Torvalds 
19381f280e2SRichard Purdie 	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
1941da177e4SLinus Torvalds 	if (retval == 0)
1951da177e4SLinus Torvalds 		return retval;
1961da177e4SLinus Torvalds 
19781f280e2SRichard Purdie 	pxa27x_stop_hc(&pdev->dev);
19881f280e2SRichard Purdie  err3:
1991da177e4SLinus Torvalds 	iounmap(hcd->regs);
2001da177e4SLinus Torvalds  err2:
2011da177e4SLinus Torvalds 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
2021da177e4SLinus Torvalds  err1:
2031da177e4SLinus Torvalds 	usb_put_hcd(hcd);
2041da177e4SLinus Torvalds 	return retval;
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds 
2081da177e4SLinus Torvalds /* may be called without controller electrically present */
2091da177e4SLinus Torvalds /* may be called with controller, bus, and devices active */
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds /**
2121da177e4SLinus Torvalds  * usb_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs
2131da177e4SLinus Torvalds  * @dev: USB Host Controller being removed
2141da177e4SLinus Torvalds  * Context: !in_interrupt()
2151da177e4SLinus Torvalds  *
2161da177e4SLinus Torvalds  * Reverses the effect of usb_hcd_pxa27x_probe(), first invoking
2171da177e4SLinus Torvalds  * the HCD's stop() method.  It is always called from a thread
2181da177e4SLinus Torvalds  * context, normally "rmmod", "apmd", or something similar.
2191da177e4SLinus Torvalds  *
2201da177e4SLinus Torvalds  */
22181f280e2SRichard Purdie void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
2221da177e4SLinus Torvalds {
2231da177e4SLinus Torvalds 	usb_remove_hcd(hcd);
22481f280e2SRichard Purdie 	pxa27x_stop_hc(&pdev->dev);
2251da177e4SLinus Torvalds 	iounmap(hcd->regs);
2261da177e4SLinus Torvalds 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
2271da177e4SLinus Torvalds 	usb_put_hcd(hcd);
2281da177e4SLinus Torvalds }
2291da177e4SLinus Torvalds 
2301da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds static int __devinit
2331da177e4SLinus Torvalds ohci_pxa27x_start (struct usb_hcd *hcd)
2341da177e4SLinus Torvalds {
2351da177e4SLinus Torvalds 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
2361da177e4SLinus Torvalds 	int		ret;
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
2391da177e4SLinus Torvalds 
240fdd13b36SDavid Brownell 	/* The value of NDP in roothub_a is incorrect on this hardware */
241fdd13b36SDavid Brownell 	ohci->num_ports = 3;
242fdd13b36SDavid Brownell 
2431da177e4SLinus Torvalds 	if ((ret = ohci_init(ohci)) < 0)
2441da177e4SLinus Torvalds 		return ret;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds 	if ((ret = ohci_run (ohci)) < 0) {
2471da177e4SLinus Torvalds 		err ("can't start %s", hcd->self.bus_name);
2481da177e4SLinus Torvalds 		ohci_stop (hcd);
2491da177e4SLinus Torvalds 		return ret;
2501da177e4SLinus Torvalds 	}
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	return 0;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds static const struct hc_driver ohci_pxa27x_hc_driver = {
2581da177e4SLinus Torvalds 	.description =		hcd_name,
2591da177e4SLinus Torvalds 	.product_desc =		"PXA27x OHCI",
2601da177e4SLinus Torvalds 	.hcd_priv_size =	sizeof(struct ohci_hcd),
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	/*
2631da177e4SLinus Torvalds 	 * generic hardware linkage
2641da177e4SLinus Torvalds 	 */
2651da177e4SLinus Torvalds 	.irq =			ohci_irq,
2661da177e4SLinus Torvalds 	.flags =		HCD_USB11 | HCD_MEMORY,
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	/*
2691da177e4SLinus Torvalds 	 * basic lifecycle operations
2701da177e4SLinus Torvalds 	 */
2711da177e4SLinus Torvalds 	.start =		ohci_pxa27x_start,
2721da177e4SLinus Torvalds 	.stop =			ohci_stop,
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	/*
2751da177e4SLinus Torvalds 	 * managing i/o requests and associated device resources
2761da177e4SLinus Torvalds 	 */
2771da177e4SLinus Torvalds 	.urb_enqueue =		ohci_urb_enqueue,
2781da177e4SLinus Torvalds 	.urb_dequeue =		ohci_urb_dequeue,
2791da177e4SLinus Torvalds 	.endpoint_disable =	ohci_endpoint_disable,
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	/*
2821da177e4SLinus Torvalds 	 * scheduling support
2831da177e4SLinus Torvalds 	 */
2841da177e4SLinus Torvalds 	.get_frame_number =	ohci_get_frame,
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	/*
2871da177e4SLinus Torvalds 	 * root hub support
2881da177e4SLinus Torvalds 	 */
2891da177e4SLinus Torvalds 	.hub_status_data =	ohci_hub_status_data,
2901da177e4SLinus Torvalds 	.hub_control =		ohci_hub_control,
2918ad7fe16SDavid Brownell #ifdef  CONFIG_PM
2920c0382e3SAlan Stern 	.bus_suspend =		ohci_bus_suspend,
2930c0382e3SAlan Stern 	.bus_resume =		ohci_bus_resume,
2941da177e4SLinus Torvalds #endif
2959293677aSDavid Brownell 	.start_port_reset =	ohci_start_port_reset,
2961da177e4SLinus Torvalds };
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/
2991da177e4SLinus Torvalds 
3003ae5eaecSRussell King static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
3011da177e4SLinus Torvalds {
3021da177e4SLinus Torvalds 	pr_debug ("In ohci_hcd_pxa27x_drv_probe");
3031da177e4SLinus Torvalds 
3041da177e4SLinus Torvalds 	if (usb_disabled())
3051da177e4SLinus Torvalds 		return -ENODEV;
3061da177e4SLinus Torvalds 
30781f280e2SRichard Purdie 	return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
3081da177e4SLinus Torvalds }
3091da177e4SLinus Torvalds 
3103ae5eaecSRussell King static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
3111da177e4SLinus Torvalds {
3123ae5eaecSRussell King 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	usb_hcd_pxa27x_remove(hcd, pdev);
315a5e36d20SRichard Purdie 	platform_set_drvdata(pdev, NULL);
3161da177e4SLinus Torvalds 	return 0;
3171da177e4SLinus Torvalds }
3181da177e4SLinus Torvalds 
3192e1dcc16SRichard Purdie #ifdef	CONFIG_PM
3202e1dcc16SRichard Purdie static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
3211da177e4SLinus Torvalds {
322a5e36d20SRichard Purdie 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
323a5e36d20SRichard Purdie 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
3242e1dcc16SRichard Purdie 
3252e1dcc16SRichard Purdie 	if (time_before(jiffies, ohci->next_statechange))
3262e1dcc16SRichard Purdie 		msleep(5);
3272e1dcc16SRichard Purdie 	ohci->next_statechange = jiffies;
3282e1dcc16SRichard Purdie 
3292e1dcc16SRichard Purdie 	pxa27x_stop_hc(&pdev->dev);
330a5e36d20SRichard Purdie 	hcd->state = HC_STATE_SUSPENDED;
3312e1dcc16SRichard Purdie 	pdev->dev.power.power_state = PMSG_SUSPEND;
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds 	return 0;
3341da177e4SLinus Torvalds }
3351da177e4SLinus Torvalds 
3362e1dcc16SRichard Purdie static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
3371da177e4SLinus Torvalds {
338a5e36d20SRichard Purdie 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
339a5e36d20SRichard Purdie 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
3402e1dcc16SRichard Purdie 	int status;
3412e1dcc16SRichard Purdie 
3422e1dcc16SRichard Purdie 	if (time_before(jiffies, ohci->next_statechange))
3432e1dcc16SRichard Purdie 		msleep(5);
3442e1dcc16SRichard Purdie 	ohci->next_statechange = jiffies;
3452e1dcc16SRichard Purdie 
3462e1dcc16SRichard Purdie 	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
3472e1dcc16SRichard Purdie 		return status;
3482e1dcc16SRichard Purdie 
3492e1dcc16SRichard Purdie 	pdev->dev.power.power_state = PMSG_ON;
350a5e36d20SRichard Purdie 	usb_hcd_resume_root_hub(hcd);
3511da177e4SLinus Torvalds 
3521da177e4SLinus Torvalds 	return 0;
3531da177e4SLinus Torvalds }
3542e1dcc16SRichard Purdie #endif
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds 
3573ae5eaecSRussell King static struct platform_driver ohci_hcd_pxa27x_driver = {
3581da177e4SLinus Torvalds 	.probe		= ohci_hcd_pxa27x_drv_probe,
3591da177e4SLinus Torvalds 	.remove		= ohci_hcd_pxa27x_drv_remove,
3602e1dcc16SRichard Purdie #ifdef CONFIG_PM
3611da177e4SLinus Torvalds 	.suspend	= ohci_hcd_pxa27x_drv_suspend,
3621da177e4SLinus Torvalds 	.resume		= ohci_hcd_pxa27x_drv_resume,
3632e1dcc16SRichard Purdie #endif
3643ae5eaecSRussell King 	.driver		= {
3653ae5eaecSRussell King 		.name	= "pxa27x-ohci",
3663ae5eaecSRussell King 	},
3671da177e4SLinus Torvalds };
3681da177e4SLinus Torvalds 
3691da177e4SLinus Torvalds static int __init ohci_hcd_pxa27x_init (void)
3701da177e4SLinus Torvalds {
3711da177e4SLinus Torvalds 	pr_debug (DRIVER_INFO " (pxa27x)");
3721da177e4SLinus Torvalds 	pr_debug ("block sizes: ed %d td %d\n",
3731da177e4SLinus Torvalds 		sizeof (struct ed), sizeof (struct td));
3741da177e4SLinus Torvalds 
3753ae5eaecSRussell King 	return platform_driver_register(&ohci_hcd_pxa27x_driver);
3761da177e4SLinus Torvalds }
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds static void __exit ohci_hcd_pxa27x_cleanup (void)
3791da177e4SLinus Torvalds {
3803ae5eaecSRussell King 	platform_driver_unregister(&ohci_hcd_pxa27x_driver);
3811da177e4SLinus Torvalds }
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds module_init (ohci_hcd_pxa27x_init);
3841da177e4SLinus Torvalds module_exit (ohci_hcd_pxa27x_cleanup);
385