2005-04-17 02:20:36 +04:00
/*
* OHCI HCD ( Host Controller Driver ) for USB .
*
* ( C ) Copyright 1999 Roman Weissgaerber < weissg @ vienna . at >
* ( C ) Copyright 2000 - 2002 David Brownell < dbrownell @ users . sourceforge . net >
* ( C ) Copyright 2002 Hewlett - Packard Company
* ( C ) Copyright 2003 - 2005 MontaVista Software Inc .
2006-12-05 14:18:31 +03:00
*
2005-04-17 02:20:36 +04:00
* Bus Glue for PPC On - Chip OHCI driver
* Tested on Freescale MPC5200 and IBM STB04xxx
*
* Modified by Dale Farnsworth < dale @ farnsworth . org > from ohci - sa1111 . c
*
* This file is licenced under the GPL .
*/
2005-10-29 22:07:23 +04:00
# include <linux/platform_device.h>
2006-01-08 12:02:05 +03:00
# include <linux/signal.h>
2005-10-29 22:07:23 +04:00
2005-04-17 02:20:36 +04:00
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
/**
* usb_hcd_ppc_soc_probe - initialize On - Chip HCDs
* Context : ! in_interrupt ( )
*
2005-08-11 04:25:25 +04:00
* Allocates basic resources for this USB host controller .
2005-04-17 02:20:36 +04:00
*
* Store this function in the HCD ' s struct pci_driver as probe ( ) .
*/
static int usb_hcd_ppc_soc_probe ( const struct hc_driver * driver ,
struct platform_device * pdev )
{
int retval ;
struct usb_hcd * hcd ;
struct ohci_hcd * ohci ;
struct resource * res ;
int irq ;
pr_debug ( " initializing PPC-SOC USB Controller \n " ) ;
res = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( ! res ) {
pr_debug ( __FILE__ " : no irq \n " ) ;
return - ENODEV ;
}
irq = res - > start ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res ) {
pr_debug ( __FILE__ " : no reg addr \n " ) ;
return - ENODEV ;
}
hcd = usb_create_hcd ( driver , & pdev - > dev , " PPC-SOC USB " ) ;
if ( ! hcd )
return - ENOMEM ;
hcd - > rsrc_start = res - > start ;
hcd - > rsrc_len = res - > end - res - > start + 1 ;
if ( ! request_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len , hcd_name ) ) {
pr_debug ( __FILE__ " : request_mem_region failed \n " ) ;
retval = - EBUSY ;
goto err1 ;
}
hcd - > regs = ioremap ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
if ( ! hcd - > regs ) {
pr_debug ( __FILE__ " : ioremap failed \n " ) ;
retval = - ENOMEM ;
goto err2 ;
}
ohci = hcd_to_ohci ( hcd ) ;
2006-12-14 22:54:03 +03:00
ohci - > flags | = OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC ;
2007-10-10 02:00:05 +04:00
# ifdef CONFIG_PPC_MPC52xx
/* MPC52xx doesn't need frame_no shift */
ohci - > flags | = OHCI_QUIRK_FRAME_NO ;
# endif
2005-04-17 02:20:36 +04:00
ohci_hcd_init ( ohci ) ;
2006-07-02 06:29:44 +04:00
retval = usb_add_hcd ( hcd , irq , IRQF_DISABLED ) ;
2005-04-17 02:20:36 +04:00
if ( retval = = 0 )
return retval ;
pr_debug ( " Removing PPC-SOC USB Controller \n " ) ;
2005-08-11 04:25:25 +04:00
2005-04-17 02:20:36 +04:00
iounmap ( hcd - > regs ) ;
err2 :
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
err1 :
2006-12-05 14:18:31 +03:00
usb_put_hcd ( hcd ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
* usb_hcd_ppc_soc_remove - shutdown processing for On - Chip HCDs
* @ pdev : USB Host Controller being removed
* Context : ! in_interrupt ( )
*
2005-08-11 04:25:25 +04:00
* Reverses the effect of usb_hcd_ppc_soc_probe ( ) .
* It is always called from a thread
2005-04-17 02:20:36 +04:00
* context , normally " rmmod " , " apmd " , or something similar .
*
*/
static void usb_hcd_ppc_soc_remove ( struct usb_hcd * hcd ,
struct platform_device * pdev )
{
usb_remove_hcd ( hcd ) ;
pr_debug ( " stopping PPC-SOC USB Controller \n " ) ;
iounmap ( hcd - > regs ) ;
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
2005-08-09 23:13:35 +04:00
usb_put_hcd ( hcd ) ;
2005-04-17 02:20:36 +04:00
}
static int __devinit
ohci_ppc_soc_start ( struct usb_hcd * hcd )
{
struct ohci_hcd * ohci = hcd_to_ohci ( hcd ) ;
int ret ;
if ( ( ret = ohci_init ( ohci ) ) < 0 )
return ret ;
if ( ( ret = ohci_run ( ohci ) ) < 0 ) {
err ( " can't start %s " , ohci_to_hcd ( ohci ) - > self . bus_name ) ;
ohci_stop ( hcd ) ;
return ret ;
}
return 0 ;
}
static const struct hc_driver ohci_ppc_soc_hc_driver = {
. description = hcd_name ,
. hcd_priv_size = sizeof ( struct ohci_hcd ) ,
/*
* generic hardware linkage
*/
. irq = ohci_irq ,
. flags = HCD_USB11 | HCD_MEMORY ,
/*
* basic lifecycle operations
*/
. start = ohci_ppc_soc_start ,
. stop = ohci_stop ,
2006-12-05 14:18:31 +03:00
. shutdown = ohci_shutdown ,
2005-04-17 02:20:36 +04:00
/*
* managing i / o requests and associated device resources
*/
. urb_enqueue = ohci_urb_enqueue ,
. urb_dequeue = ohci_urb_dequeue ,
. endpoint_disable = ohci_endpoint_disable ,
/*
* scheduling support
*/
. get_frame_number = ohci_get_frame ,
/*
* root hub support
*/
. hub_status_data = ohci_hub_status_data ,
. hub_control = ohci_hub_control ,
2005-09-14 06:59:11 +04:00
# ifdef CONFIG_PM
2005-10-14 01:08:02 +04:00
. bus_suspend = ohci_bus_suspend ,
. bus_resume = ohci_bus_resume ,
2005-04-17 02:20:36 +04:00
# endif
. start_port_reset = ohci_start_port_reset ,
} ;
2005-11-10 01:32:44 +03:00
static int ohci_hcd_ppc_soc_drv_probe ( struct platform_device * pdev )
2005-04-17 02:20:36 +04:00
{
int ret ;
if ( usb_disabled ( ) )
return - ENODEV ;
ret = usb_hcd_ppc_soc_probe ( & ohci_ppc_soc_hc_driver , pdev ) ;
return ret ;
}
2005-11-10 01:32:44 +03:00
static int ohci_hcd_ppc_soc_drv_remove ( struct platform_device * pdev )
2005-04-17 02:20:36 +04:00
{
2005-11-18 12:10:48 +03:00
struct usb_hcd * hcd = platform_get_drvdata ( pdev ) ;
2005-04-17 02:20:36 +04:00
usb_hcd_ppc_soc_remove ( hcd , pdev ) ;
return 0 ;
}
2005-11-10 01:32:44 +03:00
static struct platform_driver ohci_hcd_ppc_soc_driver = {
2005-04-17 02:20:36 +04:00
. probe = ohci_hcd_ppc_soc_drv_probe ,
. remove = ohci_hcd_ppc_soc_drv_remove ,
2006-12-05 14:18:31 +03:00
. shutdown = usb_hcd_platform_shutdown ,
2005-09-14 06:59:11 +04:00
# ifdef CONFIG_PM
2005-04-17 02:20:36 +04:00
/*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
/*.resume = ohci_hcd_ppc_soc_drv_resume,*/
# endif
2005-11-10 01:32:44 +03:00
. driver = {
. name = " ppc-soc-ohci " ,
. owner = THIS_MODULE ,
} ,
2005-04-17 02:20:36 +04:00
} ;
2008-04-11 08:29:22 +04:00
MODULE_ALIAS ( " platform:ppc-soc-ohci " ) ;