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 - 2005 David Brownell
* ( C ) Copyright 2002 Hewlett - Packard Company
2006-07-31 18:29:39 +04:00
*
2005-04-17 02:20:36 +04:00
* OMAP Bus Glue
*
* Modified for OMAP by Tony Lindgren < tony @ atomide . com >
* Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc .
* and on ohci - sa1111 . c by Christopher Hoover < ch @ hpl . hp . com >
*
* This file is licenced under the GPL .
*/
2011-09-07 12:10:52 +04:00
# include <linux/signal.h>
2005-10-31 02:03:48 +03:00
# include <linux/jiffies.h>
2005-10-29 22:07:23 +04:00
# include <linux/platform_device.h>
2006-01-07 19:15:52 +03:00
# include <linux/clk.h>
2008-12-11 04:35:31 +03:00
# include <linux/gpio.h>
2005-10-31 02:03:48 +03:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/io.h>
# include <asm/mach-types.h>
2009-10-20 20:40:47 +04:00
# include <plat/mux.h>
2008-08-05 19:14:15 +04:00
# include <mach/irqs.h>
2009-10-20 20:40:47 +04:00
# include <plat/fpga.h>
# include <plat/usb.h>
2005-04-17 02:20:36 +04:00
/* OMAP-1510 OHCI has its own MMU for DMA */
# define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */
# define OMAP1510_LB_CLOCK_DIV 0xfffec10c
# define OMAP1510_LB_MMU_CTL 0xfffec208
# define OMAP1510_LB_MMU_LCK 0xfffec224
# define OMAP1510_LB_MMU_LD_TLB 0xfffec228
# define OMAP1510_LB_MMU_CAM_H 0xfffec22c
# define OMAP1510_LB_MMU_CAM_L 0xfffec230
# define OMAP1510_LB_MMU_RAM_H 0xfffec234
# define OMAP1510_LB_MMU_RAM_L 0xfffec238
# ifndef CONFIG_ARCH_OMAP
# error "This file is OMAP bus glue. CONFIG_OMAP must be defined."
# endif
# ifdef CONFIG_TPS65010
2008-01-27 20:14:49 +03:00
# include <linux/i2c/tps65010.h>
2005-04-17 02:20:36 +04:00
# else
# define LOW 0
# define HIGH 1
# define GPIO1 1
static inline int tps65010_set_gpio_out_value ( unsigned gpio , unsigned value )
{
return 0 ;
}
# endif
extern int usb_disabled ( void ) ;
extern int ocpi_enable ( void ) ;
static struct clk * usb_host_ck ;
2006-07-31 18:29:39 +04:00
static struct clk * usb_dc_ck ;
static int host_enabled ;
static int host_initialized ;
2005-04-17 02:20:36 +04:00
static void omap_ohci_clock_power ( int on )
{
if ( on ) {
2006-07-31 18:29:39 +04:00
clk_enable ( usb_dc_ck ) ;
2005-04-17 02:20:36 +04:00
clk_enable ( usb_host_ck ) ;
/* guesstimate for T5 == 1x 32K clock + APLL lock time */
udelay ( 100 ) ;
} else {
clk_disable ( usb_host_ck ) ;
2006-07-31 18:29:39 +04:00
clk_disable ( usb_dc_ck ) ;
2005-04-17 02:20:36 +04:00
}
}
/*
* Board specific gang - switched transceiver power on / off .
* NOTE : OSK supplies power from DC , not battery .
*/
static int omap_ohci_transceiver_power ( int on )
{
if ( on ) {
if ( machine_is_omap_innovator ( ) & & cpu_is_omap1510 ( ) )
fpga_write ( fpga_read ( INNOVATOR_FPGA_CAM_USB_CONTROL )
2006-07-31 18:29:39 +04:00
| ( ( 1 < < 5 /*usb1*/ ) | ( 1 < < 3 /*usb2*/ ) ) ,
2005-04-17 02:20:36 +04:00
INNOVATOR_FPGA_CAM_USB_CONTROL ) ;
else if ( machine_is_omap_osk ( ) )
tps65010_set_gpio_out_value ( GPIO1 , LOW ) ;
} else {
if ( machine_is_omap_innovator ( ) & & cpu_is_omap1510 ( ) )
fpga_write ( fpga_read ( INNOVATOR_FPGA_CAM_USB_CONTROL )
2006-07-31 18:29:39 +04:00
& ~ ( ( 1 < < 5 /*usb1*/ ) | ( 1 < < 3 /*usb2*/ ) ) ,
2005-04-17 02:20:36 +04:00
INNOVATOR_FPGA_CAM_USB_CONTROL ) ;
else if ( machine_is_omap_osk ( ) )
tps65010_set_gpio_out_value ( GPIO1 , HIGH ) ;
}
return 0 ;
}
2006-07-31 18:29:39 +04:00
# ifdef CONFIG_ARCH_OMAP15XX
2005-04-17 02:20:36 +04:00
/*
* OMAP - 1510 specific Local Bus clock on / off
*/
static int omap_1510_local_bus_power ( int on )
{
if ( on ) {
omap_writel ( ( 1 < < 1 ) | ( 1 < < 0 ) , OMAP1510_LB_MMU_CTL ) ;
udelay ( 200 ) ;
} else {
omap_writel ( 0 , OMAP1510_LB_MMU_CTL ) ;
}
return 0 ;
}
/*
* OMAP - 1510 specific Local Bus initialization
* NOTE : This assumes 32 MB memory size in OMAP1510LB_MEMSIZE .
2006-07-31 18:29:39 +04:00
* See also arch / mach - omap / memory . h for __virt_to_dma ( ) and
* __dma_to_virt ( ) which need to match with the physical
2005-04-17 02:20:36 +04:00
* Local Bus address below .
*/
static int omap_1510_local_bus_init ( void )
{
unsigned int tlb ;
unsigned long lbaddr , physaddr ;
2006-07-31 18:29:39 +04:00
omap_writel ( ( omap_readl ( OMAP1510_LB_CLOCK_DIV ) & 0xfffffff8 ) | 0x4 ,
2005-04-17 02:20:36 +04:00
OMAP1510_LB_CLOCK_DIV ) ;
/* Configure the Local Bus MMU table */
for ( tlb = 0 ; tlb < OMAP1510_LB_MEMSIZE ; tlb + + ) {
lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET ;
physaddr = tlb * 0x00100000 + PHYS_OFFSET ;
omap_writel ( ( lbaddr & 0x0fffffff ) > > 22 , OMAP1510_LB_MMU_CAM_H ) ;
2006-07-31 18:29:39 +04:00
omap_writel ( ( ( lbaddr & 0x003ffc00 ) > > 6 ) | 0xc ,
2005-04-17 02:20:36 +04:00
OMAP1510_LB_MMU_CAM_L ) ;
omap_writel ( physaddr > > 16 , OMAP1510_LB_MMU_RAM_H ) ;
omap_writel ( ( physaddr & 0x0000fc00 ) | 0x300 , OMAP1510_LB_MMU_RAM_L ) ;
omap_writel ( tlb < < 4 , OMAP1510_LB_MMU_LCK ) ;
omap_writel ( 0x1 , OMAP1510_LB_MMU_LD_TLB ) ;
}
/* Enable the walking table */
omap_writel ( omap_readl ( OMAP1510_LB_MMU_CTL ) | ( 1 < < 3 ) , OMAP1510_LB_MMU_CTL ) ;
udelay ( 200 ) ;
return 0 ;
}
2006-07-31 18:29:39 +04:00
# else
# define omap_1510_local_bus_power(x) {}
# define omap_1510_local_bus_init() {}
# endif
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_USB_OTG
static void start_hnp ( struct ohci_hcd * ohci )
{
const unsigned port = ohci_to_hcd ( ohci ) - > self . otg_port - 1 ;
unsigned long flags ;
2008-07-03 13:24:43 +04:00
u32 l ;
2005-04-17 02:20:36 +04:00
2012-02-13 15:24:20 +04:00
otg_start_hnp ( ohci - > transceiver - > otg ) ;
2005-04-17 02:20:36 +04:00
local_irq_save ( flags ) ;
ohci - > transceiver - > state = OTG_STATE_A_SUSPEND ;
writel ( RH_PS_PSS , & ohci - > regs - > roothub . portstatus [ port ] ) ;
2008-07-03 13:24:43 +04:00
l = omap_readl ( OTG_CTRL ) ;
l & = ~ OTG_A_BUSREQ ;
omap_writel ( l , OTG_CTRL ) ;
2005-04-17 02:20:36 +04:00
local_irq_restore ( flags ) ;
}
# endif
/*-------------------------------------------------------------------------*/
2006-07-31 18:29:39 +04:00
static int ohci_omap_init ( struct usb_hcd * hcd )
2005-04-17 02:20:36 +04:00
{
2006-07-31 18:29:39 +04:00
struct ohci_hcd * ohci = hcd_to_ohci ( hcd ) ;
struct omap_usb_config * config = hcd - > self . controller - > platform_data ;
2005-04-17 02:20:36 +04:00
int need_transceiver = ( config - > otg ! = 0 ) ;
int ret ;
2006-07-31 18:29:39 +04:00
dev_dbg ( hcd - > self . controller , " starting USB Controller \n " ) ;
2005-04-17 02:20:36 +04:00
if ( config - > otg ) {
ohci_to_hcd ( ohci ) - > self . otg_port = config - > otg ;
/* default/minimum OTG power budget: 8 mA */
2005-04-25 19:21:31 +04:00
ohci_to_hcd ( ohci ) - > power_budget = 8 ;
2005-04-17 02:20:36 +04:00
}
/* boards can use OTG transceivers in non-OTG modes */
need_transceiver = need_transceiver
| | machine_is_omap_h2 ( ) | | machine_is_omap_h3 ( ) ;
2012-04-13 16:34:27 +04:00
/* XXX OMAP16xx only */
if ( config - > ocpi_enable )
config - > ocpi_enable ( ) ;
2005-04-17 02:20:36 +04:00
2008-09-04 02:59:23 +04:00
# ifdef CONFIG_USB_OTG
2005-04-17 02:20:36 +04:00
if ( need_transceiver ) {
2012-02-13 15:24:18 +04:00
ohci - > transceiver = usb_get_transceiver ( ) ;
2005-04-17 02:20:36 +04:00
if ( ohci - > transceiver ) {
2012-02-13 15:24:20 +04:00
int status = otg_set_host ( ohci - > transceiver - > otg ,
2005-04-17 02:20:36 +04:00
& ohci_to_hcd ( ohci ) - > self ) ;
2006-07-31 18:29:39 +04:00
dev_dbg ( hcd - > self . controller , " init %s transceiver, status %d \n " ,
2005-04-17 02:20:36 +04:00
ohci - > transceiver - > label , status ) ;
if ( status ) {
2012-05-13 22:10:43 +04:00
usb_put_transceiver ( ohci - > transceiver ) ;
2005-04-17 02:20:36 +04:00
return status ;
}
} else {
2006-07-31 18:29:39 +04:00
dev_err ( hcd - > self . controller , " can't find transceiver \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
}
2008-07-06 14:26:30 +04:00
ohci - > start_hnp = start_hnp ;
2005-04-17 02:20:36 +04:00
}
# endif
omap_ohci_clock_power ( 1 ) ;
2008-09-05 03:29:55 +04:00
if ( cpu_is_omap15xx ( ) ) {
2005-04-17 02:20:36 +04:00
omap_1510_local_bus_power ( 1 ) ;
omap_1510_local_bus_init ( ) ;
}
if ( ( ret = ohci_init ( ohci ) ) < 0 )
return ret ;
/* board-specific power switching and overcurrent support */
if ( machine_is_omap_osk ( ) | | machine_is_omap_innovator ( ) ) {
u32 rh = roothub_a ( ohci ) ;
/* power switching (ganged by default) */
rh & = ~ RH_A_NPS ;
/* TPS2045 switch for internal transceiver (port 1) */
if ( machine_is_omap_osk ( ) ) {
2005-04-25 19:21:31 +04:00
ohci_to_hcd ( ohci ) - > power_budget = 250 ;
2005-04-17 02:20:36 +04:00
rh & = ~ RH_A_NOCP ;
/* gpio9 for overcurrent detction */
omap_cfg_reg ( W8_1610_GPIO9 ) ;
2008-12-11 04:35:31 +03:00
gpio_request ( 9 , " OHCI overcurrent " ) ;
2008-12-11 04:35:26 +03:00
gpio_direction_input ( 9 ) ;
2005-04-17 02:20:36 +04:00
/* for paranoia's sake: disable USB.PUEN */
omap_cfg_reg ( W4_USB_HIGHZ ) ;
}
ohci_writel ( ohci , rh , & ohci - > regs - > roothub . a ) ;
2008-07-06 23:35:01 +04:00
ohci - > flags & = ~ OHCI_QUIRK_HUB_POWER ;
2006-07-31 18:29:39 +04:00
} else if ( machine_is_nokia770 ( ) ) {
/* We require a self-powered hub, which should have
* plenty of power . */
ohci_to_hcd ( ohci ) - > power_budget = 0 ;
2005-04-17 02:20:36 +04:00
}
/* FIXME khubd hub requests should manage power switching */
omap_ohci_transceiver_power ( 1 ) ;
/* board init will have already handled HMC and mux setup.
* any external transceiver should already be initialized
* too , so all configured ports use the right signaling now .
*/
return 0 ;
}
2006-07-31 18:29:39 +04:00
static void ohci_omap_stop ( struct usb_hcd * hcd )
2005-04-17 02:20:36 +04:00
{
2006-07-31 18:29:39 +04:00
dev_dbg ( hcd - > self . controller , " stopping USB Controller \n " ) ;
2009-07-14 15:11:00 +04:00
ohci_stop ( hcd ) ;
2005-04-17 02:20:36 +04:00
omap_ohci_clock_power ( 0 ) ;
}
/*-------------------------------------------------------------------------*/
/**
* usb_hcd_omap_probe - initialize OMAP - based HCDs
* Context : ! in_interrupt ( )
*
* Allocates basic resources for this USB host controller , and
* then invokes the start ( ) method for the HCD associated with it
* through the hotplug entry ' s driver_data .
*/
2006-07-31 18:29:39 +04:00
static int usb_hcd_omap_probe ( const struct hc_driver * driver ,
2005-04-17 02:20:36 +04:00
struct platform_device * pdev )
{
2006-01-19 20:56:29 +03:00
int retval , irq ;
2005-04-17 02:20:36 +04:00
struct usb_hcd * hcd = 0 ;
struct ohci_hcd * ohci ;
if ( pdev - > num_resources ! = 2 ) {
2006-07-31 18:29:39 +04:00
printk ( KERN_ERR " hcd probe: invalid num_resources: %i \n " ,
2005-04-17 02:20:36 +04:00
pdev - > num_resources ) ;
return - ENODEV ;
}
2006-07-31 18:29:39 +04:00
if ( pdev - > resource [ 0 ] . flags ! = IORESOURCE_MEM
2005-04-17 02:20:36 +04:00
| | pdev - > resource [ 1 ] . flags ! = IORESOURCE_IRQ ) {
printk ( KERN_ERR " hcd probe: invalid resource type \n " ) ;
return - ENODEV ;
}
2009-01-18 15:52:38 +03:00
usb_host_ck = clk_get ( & pdev - > dev , " usb_hhc_ck " ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( usb_host_ck ) )
return PTR_ERR ( usb_host_ck ) ;
2008-09-05 03:29:55 +04:00
if ( ! cpu_is_omap15xx ( ) )
2009-01-18 15:52:38 +03:00
usb_dc_ck = clk_get ( & pdev - > dev , " usb_dc_ck " ) ;
2006-07-31 18:29:39 +04:00
else
2009-01-18 15:52:38 +03:00
usb_dc_ck = clk_get ( & pdev - > dev , " lb_ck " ) ;
2006-07-31 18:29:39 +04:00
if ( IS_ERR ( usb_dc_ck ) ) {
clk_put ( usb_host_ck ) ;
return PTR_ERR ( usb_dc_ck ) ;
}
2008-05-02 08:02:41 +04:00
hcd = usb_create_hcd ( driver , & pdev - > dev , dev_name ( & pdev - > dev ) ) ;
2005-04-17 02:20:36 +04:00
if ( ! hcd ) {
retval = - ENOMEM ;
goto err0 ;
}
hcd - > rsrc_start = pdev - > resource [ 0 ] . start ;
hcd - > rsrc_len = pdev - > resource [ 0 ] . end - pdev - > resource [ 0 ] . start + 1 ;
if ( ! request_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len , hcd_name ) ) {
dev_dbg ( & pdev - > dev , " request_mem_region failed \n " ) ;
retval = - EBUSY ;
goto err1 ;
}
2008-09-04 17:07:22 +04:00
hcd - > regs = ioremap ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
if ( ! hcd - > regs ) {
dev_err ( & pdev - > dev , " can't ioremap OHCI HCD \n " ) ;
retval = - ENOMEM ;
goto err2 ;
}
2005-04-17 02:20:36 +04:00
ohci = hcd_to_ohci ( hcd ) ;
ohci_hcd_init ( ohci ) ;
2006-07-31 18:29:39 +04:00
host_initialized = 0 ;
host_enabled = 1 ;
2005-04-17 02:20:36 +04:00
2006-01-19 20:56:29 +03:00
irq = platform_get_irq ( pdev , 0 ) ;
if ( irq < 0 ) {
retval = - ENXIO ;
2008-09-04 17:07:22 +04:00
goto err3 ;
2006-01-19 20:56:29 +03:00
}
2011-09-07 12:10:52 +04:00
retval = usb_add_hcd ( hcd , irq , 0 ) ;
2006-07-31 18:29:39 +04:00
if ( retval )
2008-09-04 17:07:22 +04:00
goto err3 ;
2006-07-31 18:29:39 +04:00
host_initialized = 1 ;
if ( ! host_enabled )
omap_ohci_clock_power ( 0 ) ;
2005-04-17 02:20:36 +04:00
2006-07-31 18:29:39 +04:00
return 0 ;
2008-09-04 17:07:22 +04:00
err3 :
iounmap ( hcd - > regs ) ;
2005-04-17 02:20:36 +04:00
err2 :
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
err1 :
usb_put_hcd ( hcd ) ;
err0 :
2006-07-31 18:29:39 +04:00
clk_put ( usb_dc_ck ) ;
2005-04-17 02:20:36 +04:00
clk_put ( usb_host_ck ) ;
return retval ;
}
/* may be called with controller, bus, and devices active */
/**
* usb_hcd_omap_remove - shutdown processing for OMAP - based HCDs
* @ dev : USB Host Controller being removed
* Context : ! in_interrupt ( )
*
* Reverses the effect of usb_hcd_omap_probe ( ) , first invoking
* the HCD ' s stop ( ) method . It is always called from a thread
* context , normally " rmmod " , " apmd " , or something similar .
*/
2006-07-31 18:29:39 +04:00
static inline void
usb_hcd_omap_remove ( struct usb_hcd * hcd , struct platform_device * pdev )
2005-04-17 02:20:36 +04:00
{
2006-07-31 18:29:39 +04:00
struct ohci_hcd * ohci = hcd_to_ohci ( hcd ) ;
2005-04-17 02:20:36 +04:00
usb_remove_hcd ( hcd ) ;
2006-07-31 18:29:39 +04:00
if ( ohci - > transceiver ) {
2012-02-13 15:24:20 +04:00
( void ) otg_set_host ( ohci - > transceiver - > otg , 0 ) ;
2012-05-13 22:10:43 +04:00
usb_put_transceiver ( ohci - > transceiver ) ;
2006-07-31 18:29:39 +04:00
}
2005-04-17 02:20:36 +04:00
if ( machine_is_omap_osk ( ) )
2008-12-11 04:35:31 +03:00
gpio_free ( 9 ) ;
2008-09-04 17:07:22 +04:00
iounmap ( hcd - > regs ) ;
2005-04-17 02:20:36 +04:00
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
usb_put_hcd ( hcd ) ;
2006-07-31 18:29:39 +04:00
clk_put ( usb_dc_ck ) ;
2005-04-17 02:20:36 +04:00
clk_put ( usb_host_ck ) ;
}
/*-------------------------------------------------------------------------*/
2006-07-31 18:29:39 +04:00
static int
2005-04-17 02:20:36 +04:00
ohci_omap_start ( struct usb_hcd * hcd )
{
struct omap_usb_config * config ;
struct ohci_hcd * ohci = hcd_to_ohci ( hcd ) ;
int ret ;
2006-07-31 18:29:39 +04:00
if ( ! host_enabled )
return 0 ;
2005-04-17 02:20:36 +04:00
config = hcd - > self . controller - > platform_data ;
2006-08-04 22:31:55 +04:00
if ( config - > otg | | config - > rwc ) {
ohci - > hc_control = OHCI_CTRL_RWC ;
2005-04-17 02:20:36 +04:00
writel ( OHCI_CTRL_RWC , & ohci - > regs - > control ) ;
2006-08-04 22:31:55 +04:00
}
2005-04-17 02:20:36 +04:00
if ( ( ret = ohci_run ( ohci ) ) < 0 ) {
dev_err ( hcd - > self . controller , " can't start \n " ) ;
ohci_stop ( hcd ) ;
return ret ;
}
return 0 ;
}
/*-------------------------------------------------------------------------*/
static const struct hc_driver ohci_omap_hc_driver = {
. description = hcd_name ,
. product_desc = " OMAP OHCI " ,
. hcd_priv_size = sizeof ( struct ohci_hcd ) ,
/*
* generic hardware linkage
*/
. irq = ohci_irq ,
. flags = HCD_USB11 | HCD_MEMORY ,
/*
* basic lifecycle operations
*/
2006-07-31 18:29:39 +04:00
. reset = ohci_omap_init ,
2005-04-17 02:20:36 +04:00
. start = ohci_omap_start ,
2006-07-31 18:29:39 +04:00
. stop = ohci_omap_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_omap_drv_probe ( struct platform_device * dev )
2005-04-17 02:20:36 +04:00
{
2005-11-10 01:32:44 +03:00
return usb_hcd_omap_probe ( & ohci_omap_hc_driver , dev ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-10 01:32:44 +03:00
static int ohci_hcd_omap_drv_remove ( struct platform_device * dev )
2005-04-17 02:20:36 +04:00
{
2005-11-10 01:32:44 +03:00
struct usb_hcd * hcd = platform_get_drvdata ( dev ) ;
2005-04-17 02:20:36 +04:00
2005-11-10 01:32:44 +03:00
usb_hcd_omap_remove ( hcd , dev ) ;
platform_set_drvdata ( dev , NULL ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*-------------------------------------------------------------------------*/
# ifdef CONFIG_PM
2005-11-10 01:32:44 +03:00
static int ohci_omap_suspend ( struct platform_device * dev , pm_message_t message )
2005-04-17 02:20:36 +04:00
{
2005-11-10 01:32:44 +03:00
struct ohci_hcd * ohci = hcd_to_ohci ( platform_get_drvdata ( dev ) ) ;
2005-09-23 09:42:53 +04:00
if ( time_before ( jiffies , ohci - > next_statechange ) )
msleep ( 5 ) ;
ohci - > next_statechange = jiffies ;
omap_ohci_clock_power ( 0 ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2005-11-10 01:32:44 +03:00
static int ohci_omap_resume ( struct platform_device * dev )
2005-04-17 02:20:36 +04:00
{
2008-04-04 02:03:17 +04:00
struct usb_hcd * hcd = platform_get_drvdata ( dev ) ;
struct ohci_hcd * ohci = hcd_to_ohci ( hcd ) ;
2005-04-17 02:20:36 +04:00
2005-06-29 17:59:14 +04:00
if ( time_before ( jiffies , ohci - > next_statechange ) )
msleep ( 5 ) ;
ohci - > next_statechange = jiffies ;
2005-09-23 09:42:53 +04:00
2005-06-29 17:59:14 +04:00
omap_ohci_clock_power ( 1 ) ;
2008-04-04 02:03:17 +04:00
ohci_finish_controller_resume ( hcd ) ;
2005-09-23 09:42:53 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
# endif
/*-------------------------------------------------------------------------*/
/*
* Driver definition to register with the OMAP bus
*/
2005-11-10 01:32:44 +03:00
static struct platform_driver ohci_hcd_omap_driver = {
2005-04-17 02:20:36 +04:00
. probe = ohci_hcd_omap_drv_probe ,
. remove = ohci_hcd_omap_drv_remove ,
2006-12-05 14:18:31 +03:00
. shutdown = usb_hcd_platform_shutdown ,
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PM
. suspend = ohci_omap_suspend ,
. resume = ohci_omap_resume ,
# endif
2005-11-10 01:32:44 +03:00
. driver = {
. owner = THIS_MODULE ,
. name = " ohci " ,
} ,
2005-04-17 02:20:36 +04:00
} ;
2008-04-11 08:29:22 +04:00
MODULE_ALIAS ( " platform:ohci " ) ;