@ -1,5 +1,11 @@
/*
* URB OHCI HCD ( Host Controller Driver ) for USB on the AT91RM9200 .
* URB OHCI HCD ( Host Controller Driver ) for USB on the AT91RM9200 and PCI bus .
*
* Interrupt support is added . Now , it has been tested
* on ULI1575 chip and works well with USB keyboard .
*
* ( C ) Copyright 2007
* Zhang Wei , Freescale Semiconductor , Inc . < wei . zhang @ freescale . com >
*
* ( C ) Copyright 2003
* Gary Jennejohn , DENX Software Engineering < gj @ denx . de >
@ -35,7 +41,7 @@
* 1 - you MUST define LITTLEENDIAN in the configuration file for the
* board or this driver will NOT work !
* 2 - this driver is intended for use with USB Mass Storage Devices
* ( BBB ) ONLY . There is NO support for Interrupt or Isochronous pipes !
* ( BBB ) and USB keyboard . There is NO support for Isochronous pipes !
* 3 - when running on a PQFP208 AT91RM9200 , define CONFIG_AT91C_PQFP_UHPBUG
* to activate workaround for bug # 41 or this driver will NOT work !
*/
@ -56,6 +62,8 @@
# include <asm / arch / pxa-regs.h>
# elif defined(CONFIG_MPC5200)
# include <mpc5xxx.h>
# elif defined(CONFIG_PCI_OHCI)
# include <pci.h>
# endif
# include <malloc.h>
@ -66,6 +74,7 @@
defined ( CONFIG_S3C2400 ) | | \
defined ( CONFIG_S3C2410 ) | | \
defined ( CONFIG_440EP ) | | \
defined ( CONFIG_PCI_OHCI ) | | \
defined ( CONFIG_MPC5200 )
# define OHCI_USE_NPS /* force NoPowerSwitching mode */
# endif
@ -79,12 +88,19 @@
# define OHCI_CONTROL_INIT \
( OHCI_CTRL_CBSR & 0x3 ) | OHCI_CTRL_IE | OHCI_CTRL_PLE
# define readl(a) (*((vu_long *)(a)))
# define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a))
# define readl(a) m32_swap (*((vu_long *)(a)))
# define writel(a, b) (*((vu_long *)(b)) = m32_swap ((vu_long)a))
# define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
# undef DEBUG
# ifdef CONFIG_PCI_OHCI
static struct pci_device_id ohci_pci_ids [ ] = {
{ 0x10b9 , 0x5237 } , /* ULI1575 PCI OHCI module ids */
/* Please add supported PCI OHCI controller ids here */
{ 0 , 0 }
} ;
# endif
# ifdef DEBUG
# define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
# else
@ -114,15 +130,11 @@ struct ohci_hcca ghcca[1];
struct ohci_hcca * phcca ;
/* this allocates EDs for all possible endpoints */
struct ohci_device ohci_dev ;
/* urb_priv */
urb_priv_t urb_priv ;
/* RHSC flag */
int got_rhsc ;
/* device which was disconnected */
struct usb_device * devgone ;
/* flag guarding URB transation */
int urb_finished = 0 ;
/*-------------------------------------------------------------------------*/
@ -177,6 +189,7 @@ static void urb_free_priv (urb_priv_t * urb)
}
}
}
free ( urb ) ;
}
/*-------------------------------------------------------------------------*/
@ -187,11 +200,10 @@ static int sohci_get_current_frame_number (struct usb_device * dev);
/* debug| print the main components of an URB
* small : 0 ) header + data packets 1 ) just header */
static void pkt_print ( struct usb_device * dev , unsigned long pipe , void * buffer ,
static void pkt_print ( urb_priv_t * purb , struct usb_device * dev ,
unsigned long pipe , void * buffer ,
int transfer_len , struct devrequest * setup , char * str , int small )
{
urb_priv_t * purb = & urb_priv ;
dbg ( " %s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx " ,
str ,
sohci_get_current_frame_number ( dev ) ,
@ -200,7 +212,7 @@ static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffe
usb_pipeout ( pipe ) ? ' O ' : ' I ' ,
usb_pipetype ( pipe ) < 2 ? ( usb_pipeint ( pipe ) ? " INTR " : " ISOC " ) :
( usb_pipecontrol ( pipe ) ? " CTRL " : " BULK " ) ,
purb - > actual_length ,
( purb ? purb - > actual_length : 0 ) ,
transfer_len , dev - > status ) ;
# ifdef OHCI_VERBOSE_DEBUG
if ( ! small ) {
@ -214,10 +226,11 @@ static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffe
}
if ( transfer_len > 0 & & buffer ) {
printf ( __FILE__ " : data(%d/%d): " ,
purb - > actual_length ,
( purb ? purb - > actual_length : 0 ) ,
transfer_len ) ;
len = usb_pipeout ( pipe ) ?
transfer_len : purb - > actual_length ;
transfer_len :
( purb ? purb - > actual_length : 0 ) ;
for ( i = 0 ; i < 16 & & i < len ; i + + )
printf ( " %02x " , ( ( __u8 * ) buffer ) [ i ] ) ;
printf ( " %s \n " , i < len ? " ... " : " " ) ;
@ -413,13 +426,17 @@ static void ohci_dump (ohci_t *controller, int verbose)
/* get a transfer request */
int sohci_submit_job ( struct usb_device * dev , unsigned long pipe , void * buffer ,
int transfer_len , struct devrequest * setup , int interval )
int sohci_submit_job ( urb_priv_t * urb , struct devrequest * setup )
{
ohci_t * ohci ;
ed_t * ed ;
urb_priv_t * purb_priv ;
urb_priv_t * purb_priv = urb ;
int i , size = 0 ;
struct usb_device * dev = urb - > dev ;
unsigned long pipe = urb - > pipe ;
void * buffer = urb - > transfer_buffer ;
int transfer_len = urb - > transfer_buffer_length ;
int interval = urb - > interval ;
ohci = & gohci ;
@ -430,18 +447,11 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
return - 1 ;
}
/* if we have an unfinished URB from previous transaction let's
* fail and scream as quickly as possible so as not to corrupt
* further communication */
if ( ! urb_finished ) {
err ( " sohci_submit_job: URB NOT FINISHED " ) ;
return - 1 ;
}
/* we're about to begin a new transaction here so mark the URB unfinished */
urb_ finished = 0 ;
urb - > finished = 0 ;
/* every endpoint has a ed, locate and fill it */
if ( ! ( ed = ep_add_ed ( dev , pipe ) ) ) {
if ( ! ( ed = ep_add_ed ( dev , pipe , interval , 1 ) ) ) {
err ( " sohci_submit_job: ENOMEM " ) ;
return - 1 ;
}
@ -455,13 +465,17 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
size = ( transfer_len = = 0 ) ? 2 :
( transfer_len - 1 ) / 4096 + 3 ;
break ;
case PIPE_INTERRUPT : /* 1 TD */
size = 1 ;
break ;
}
ed - > purb = urb ;
if ( size > = ( N_URB_TD - 1 ) ) {
err ( " need %d TDs, only have %d " , size , N_URB_TD ) ;
return - 1 ;
}
purb_priv = & urb_priv ;
purb_priv - > pipe = pipe ;
/* fill the private part of the URB */
@ -497,6 +511,40 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
return 0 ;
}
static inline int sohci_return_job ( struct ohci * hc , urb_priv_t * urb )
{
struct ohci_regs * regs = hc - > regs ;
switch ( usb_pipetype ( urb - > pipe ) ) {
case PIPE_INTERRUPT :
/* implicitly requeued */
if ( urb - > dev - > irq_handle & &
( urb - > dev - > irq_act_len = urb - > actual_length ) ) {
writel ( OHCI_INTR_WDH , & regs - > intrenable ) ;
readl ( & regs - > intrenable ) ; /* PCI posting flush */
urb - > dev - > irq_handle ( urb - > dev ) ;
writel ( OHCI_INTR_WDH , & regs - > intrdisable ) ;
readl ( & regs - > intrdisable ) ; /* PCI posting flush */
}
urb - > actual_length = 0 ;
td_submit_job (
urb - > dev ,
urb - > pipe ,
urb - > transfer_buffer ,
urb - > transfer_buffer_length ,
NULL ,
urb ,
urb - > interval ) ;
break ;
case PIPE_CONTROL :
case PIPE_BULK :
break ;
default :
return 0 ;
}
return 1 ;
}
/*-------------------------------------------------------------------------*/
# ifdef DEBUG
@ -514,13 +562,73 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev)
* ED handling functions
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* search for the right branch to insert an interrupt ed into the int tree
* do some load ballancing ;
* returns the branch and
* sets the interval to interval = 2 ^ integer ( ld ( interval ) ) */
static int ep_int_ballance ( ohci_t * ohci , int interval , int load )
{
int i , branch = 0 ;
/* search for the least loaded interrupt endpoint
* branch of all 32 branches
*/
for ( i = 0 ; i < 32 ; i + + )
if ( ohci - > ohci_int_load [ branch ] > ohci - > ohci_int_load [ i ] )
branch = i ;
branch = branch % interval ;
for ( i = branch ; i < 32 ; i + = interval )
ohci - > ohci_int_load [ i ] + = load ;
return branch ;
}
/*-------------------------------------------------------------------------*/
/* 2^int( ld (inter)) */
static int ep_2_n_interval ( int inter )
{
int i ;
for ( i = 0 ; ( ( inter > > i ) > 1 ) & & ( i < 5 ) ; i + + ) ;
return 1 < < i ;
}
/*-------------------------------------------------------------------------*/
/* the int tree is a binary tree
* in order to process it sequentially the indexes of the branches have to be mapped
* the mapping reverses the bits of a word of num_bits length */
static int ep_rev ( int num_bits , int word )
{
int i , wout = 0 ;
for ( i = 0 ; i < num_bits ; i + + )
wout | = ( ( ( word > > i ) & 1 ) < < ( num_bits - i - 1 ) ) ;
return wout ;
}
/*-------------------------------------------------------------------------*
* ED handling functions
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* link an ed into one of the HC chains */
static int ep_link ( ohci_t * ohci , ed_t * edi )
{
volatile ed_t * ed = edi ;
int int_branch ;
int i ;
int inter ;
int interval ;
int load ;
__u32 * ed_p ;
ed - > state = ED_OPER ;
ed - > int_interval = 0 ;
switch ( ed - > type ) {
case PIPE_CONTROL :
@ -554,12 +662,49 @@ static int ep_link (ohci_t *ohci, ed_t *edi)
}
ohci - > ed_bulktail = edi ;
break ;
case PIPE_INTERRUPT :
load = ed - > int_load ;
interval = ep_2_n_interval ( ed - > int_period ) ;
ed - > int_interval = interval ;
int_branch = ep_int_ballance ( ohci , interval , load ) ;
ed - > int_branch = int_branch ;
for ( i = 0 ; i < ep_rev ( 6 , interval ) ; i + = inter ) {
inter = 1 ;
for ( ed_p = & ( ohci - > hcca - > int_table [ ep_rev ( 5 , i ) + int_branch ] ) ;
( * ed_p ! = 0 ) & & ( ( ( ed_t * ) ed_p ) - > int_interval > = interval ) ;
ed_p = & ( ( ( ed_t * ) ed_p ) - > hwNextED ) )
inter = ep_rev ( 6 , ( ( ed_t * ) ed_p ) - > int_interval ) ;
ed - > hwNextED = * ed_p ;
* ed_p = m32_swap ( ed ) ;
}
break ;
}
return 0 ;
}
/*-------------------------------------------------------------------------*/
/* scan the periodic table to find and unlink this ED */
static void periodic_unlink ( struct ohci * ohci , volatile struct ed * ed ,
unsigned index , unsigned period )
{
for ( ; index < NUM_INTS ; index + = period ) {
__u32 * ed_p = & ohci - > hcca - > int_table [ index ] ;
/* ED might have been unlinked through another path */
while ( * ed_p ! = 0 ) {
if ( ( ( struct ed * ) m32_swap ( ed_p ) ) = = ed ) {
* ed_p = ed - > hwNextED ;
break ;
}
ed_p = & ( ( ( struct ed * ) m32_swap ( ed_p ) ) - > hwNextED ) ;
}
}
}
/* unlink an ed from one of the HC chains.
* just the link to the ed is unlinked .
* the link from the ed still points to another operational ed or 0
@ -568,6 +713,7 @@ static int ep_link (ohci_t *ohci, ed_t *edi)
static int ep_unlink ( ohci_t * ohci , ed_t * edi )
{
volatile ed_t * ed = edi ;
int i ;
ed - > hwINFO | = m32_swap ( OHCI_ED_SKIP ) ;
@ -605,6 +751,12 @@ static int ep_unlink (ohci_t *ohci, ed_t *edi)
( ( ed_t * ) m32_swap ( * ( ( __u32 * ) & ed - > hwNextED ) ) ) - > ed_prev = ed - > ed_prev ;
}
break ;
case PIPE_INTERRUPT :
periodic_unlink ( ohci , ed , 0 , 1 ) ;
for ( i = ed - > int_branch ; i < 32 ; i + = ed - > int_interval )
ohci - > ohci_int_load [ i ] - = ed - > int_load ;
break ;
}
ed - > state = ED_UNLINK ;
return 0 ;
@ -621,7 +773,8 @@ static int ep_unlink (ohci_t *ohci, ed_t *edi)
* info fields are setted anyway even though most of them should not
* change
*/
static ed_t * ep_add_ed ( struct usb_device * usb_dev , unsigned long pipe )
static ed_t * ep_add_ed ( struct usb_device * usb_dev , unsigned long pipe ,
int interval , int load )
{
td_t * td ;
ed_t * ed_ret ;
@ -654,6 +807,11 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
| usb_pipeslow ( pipe ) < < 13
| usb_maxpacket ( usb_dev , pipe ) < < 16 ) ;
if ( ed - > type = = PIPE_INTERRUPT & & ed - > state = = ED_UNLINK ) {
ed - > int_period = interval ;
ed - > int_load = load ;
}
return ed_ret ;
}
@ -768,6 +926,13 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf
if ( ! ohci - > sleeping )
writel ( OHCI_CLF , & ohci - > regs - > cmdstatus ) ; /* start Control list */
break ;
case PIPE_INTERRUPT :
info = usb_pipeout ( urb - > pipe ) ?
TD_CC | TD_DP_OUT | toggle :
TD_CC | TD_R | TD_DP_IN | toggle ;
td_fill ( ohci , info , data , data_len , dev , cnt + + , urb ) ;
break ;
}
if ( urb - > length ! = cnt )
dbg ( " TD LENGTH %d != CNT %d " , urb - > length , cnt ) ;
@ -783,7 +948,7 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf
static void dl_transfer_length ( td_t * td )
{
__u32 tdINFO , tdBE , tdCBP ;
urb_priv_t * lurb_priv = & urb_priv ;
urb_priv_t * lurb_priv = td - > ed - > purb ;
tdINFO = m32_swap ( td - > hwINFO ) ;
tdBE = m32_swap ( td - > hwBE ) ;
@ -820,7 +985,7 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)
td_list = ( td_t * ) td_list_hc ;
if ( TD_CC_GET ( m32_swap ( td_list - > hwINFO ) ) ) {
lurb_priv = & urb_priv ;
lurb_priv = td_list - > ed - > purb ;
dbg ( " USB-error/status: %x : %p " ,
TD_CC_GET ( m32_swap ( td_list - > hwINFO ) ) , td_list ) ;
if ( td_list - > ed - > hwHeadP & m32_swap ( 0x1 ) ) {
@ -860,10 +1025,10 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)
while ( td_list ) {
td_list_next = td_list - > next_dl_td ;
lurb_priv = & urb_priv ;
tdINFO = m32_swap ( td_list - > hwINFO ) ;
ed = td_list - > ed ;
lurb_priv = ed - > purb ;
dl_transfer_length ( td_list ) ;
@ -882,14 +1047,16 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)
( lurb_priv - > state ! = URB_DEL ) )
# else
if ( ( ed - > state & ( ED_OPER | ED_UNLINK ) ) )
urb_finished = 1 ;
# endif
lurb_priv - > finished = sohci_return_job ( ohci ,
lurb_priv ) ;
else
dbg ( " dl_done_list: strange.., ED state %x, ed->state \n " ) ;
} else
dbg ( " dl_done_list: processing TD %x, len %x \n " , lurb_priv - > td_cnt ,
lurb_priv - > length ) ;
# endif
if ( ed - > state ! = ED_NEW ) {
if ( ed - > state ! = ED_NEW & &
( usb_pipetype ( lurb_priv - > pipe ) ! = PIPE_INTERRUPT ) ) {
edHeadP = m32_swap ( ed - > hwHeadP ) & 0xfffffff0 ;
edTailP = m32_swap ( ed - > hwTailP ) ;
@ -1063,8 +1230,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
__u16 wLength ;
# ifdef DEBUG
urb_priv . actual_length = 0 ;
pkt_print ( dev , pipe , buffer , transfer_len , cmd , " SUB(rh) " , usb_pipein ( pipe ) ) ;
pkt_print ( NULL , dev , pipe , buffer , transfer_len , cmd , " SUB(rh) " , usb_pipein ( pipe ) ) ;
# else
wait_ms ( 1 ) ;
# endif
@ -1279,9 +1445,7 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
dev - > status = stat ;
# ifdef DEBUG
if ( transfer_len )
urb_priv . actual_length = transfer_len ;
pkt_print ( dev , pipe , buffer , transfer_len , cmd , " RET(rh) " , 0 /*usb_pipein(pipe)*/ ) ;
pkt_print ( NULL , dev , pipe , buffer , transfer_len , cmd , " RET(rh) " , 0 /*usb_pipein(pipe)*/ ) ;
# else
wait_ms ( 1 ) ;
# endif
@ -1299,6 +1463,16 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int stat = 0 ;
int maxsize = usb_maxpacket ( dev , pipe ) ;
int timeout ;
urb_priv_t * urb ;
urb = malloc ( sizeof ( urb_priv_t ) ) ;
memset ( urb , 0 , sizeof ( urb_priv_t ) ) ;
urb - > dev = dev ;
urb - > pipe = pipe ;
urb - > transfer_buffer = buffer ;
urb - > transfer_buffer_length = transfer_len ;
urb - > interval = interval ;
/* device pulled? Shortcut the action. */
if ( devgone = = dev ) {
@ -1307,8 +1481,8 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
}
# ifdef DEBUG
urb_priv . actual_length = 0 ;
pkt_print ( dev , pipe , buffer , transfer_len , setup , " SUB " , usb_pipein ( pipe ) ) ;
urb - > actual_length = 0 ;
pkt_print ( urb , dev , pipe , buffer , transfer_len , setup , " SUB " , usb_pipein ( pipe ) ) ;
# else
wait_ms ( 1 ) ;
# endif
@ -1318,7 +1492,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
return - 1 ;
}
if ( sohci_submit_job ( dev , pipe , buffer , transfer_len , setup , interval ) < 0 ) {
if ( sohci_submit_job ( urb , setup ) < 0 ) {
err ( " sohci_submit_job failed " ) ;
return - 1 ;
}
@ -1353,18 +1527,20 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
* finished we need to re - iterate this loop so as
* hc_interrupt ( ) gets called again as there needs to be some
* more TD ' s to process still */
if ( ( stat > = 0 ) & & ( stat ! = 0xff ) & & ( urb_ finished ) ) {
if ( ( stat > = 0 ) & & ( stat ! = 0xff ) & & ( urb - > finished ) ) {
/* 0xff is returned for an SF-interrupt */
break ;
}
if ( - - timeout ) {
wait_ms ( 1 ) ;
if ( ! urb - > finished )
dbg ( " \ % " ) ;
} else {
err ( " CTL:TIMEOUT " ) ;
dbg ( " submit_common_msg: TO status %x \n " , stat ) ;
stat = USB_ST_CRC_ERR ;
urb_finished = 1 ;
urb - > finished = 1 ;
stat = USB_ST_CRC_ERR ;
break ;
}
@ -1374,13 +1550,14 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
dev - > act_len = transfer_len ;
# ifdef DEBUG
pkt_print ( dev , pipe , buffer , transfer_len , setup , " RET(ctlr) " , usb_pipein ( pipe ) ) ;
pkt_print ( urb , dev , pipe , buffer , transfer_len , setup , " RET(ctlr) " , usb_pipein ( pipe ) ) ;
# else
wait_ms ( 1 ) ;
# endif
/* free TDs in urb_priv */
urb_free_priv ( & urb_priv ) ;
if ( usb_pipetype ( pipe ) ! = PIPE_INTERRUPT )
urb_free_priv ( urb ) ;
return 0 ;
}
@ -1399,8 +1576,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
info ( " submit_control_msg " ) ;
# ifdef DEBUG
urb_priv . actual_length = 0 ;
pkt_print ( dev , pipe , buffer , transfer_len , setup , " SUB " , usb_pipein ( pipe ) ) ;
pkt_print ( NULL , dev , pipe , buffer , transfer_len , setup , " SUB " , usb_pipein ( pipe ) ) ;
# else
wait_ms ( 1 ) ;
# endif
@ -1423,7 +1599,8 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len , int interval )
{
info ( " submit_int_msg " ) ;
return - 1 ;
return submit_common_msg ( dev , pipe , buffer , transfer_len , NULL ,
interval ) ;
}
/*-------------------------------------------------------------------------*
@ -1537,6 +1714,12 @@ static int hc_start (ohci_t * ohci)
/*-------------------------------------------------------------------------*/
/* Poll USB interrupt. */
void usb_event_poll ( void )
{
hc_interrupt ( ) ;
}
/* an interrupt happens */
static int hc_interrupt ( void )
@ -1587,8 +1770,10 @@ static int hc_interrupt (void)
if ( ints & OHCI_INTR_WDH ) {
wait_ms ( 1 ) ;
writel ( OHCI_INTR_WDH , & regs - > intrdisable ) ;
( void ) readl ( & regs - > intrdisable ) ; /* flush */
stat = dl_done_list ( & gohci , dl_reverse_done_list ( & gohci ) ) ;
writel ( OHCI_INTR_WDH , & regs - > intrenable ) ;
( void ) readl ( & regs - > intrdisable ) ; /* flush */
}
if ( ints & OHCI_INTR_SO ) {
@ -1634,6 +1819,9 @@ static char ohci_inited = 0;
int usb_lowlevel_init ( void )
{
# ifdef CONFIG_PCI_OHCI
pci_dev_t pdev ;
# endif
# ifdef CFG_USB_OHCI_CPU_INIT
/* cpu dependant init */
@ -1647,7 +1835,6 @@ int usb_lowlevel_init(void)
return - 1 ;
# endif
memset ( & gohci , 0 , sizeof ( ohci_t ) ) ;
memset ( & urb_priv , 0 , sizeof ( urb_priv_t ) ) ;
/* align the storage */
if ( ( __u32 ) & ghcca [ 0 ] & 0xff ) {
@ -1673,7 +1860,25 @@ int usb_lowlevel_init(void)
gohci . disabled = 1 ;
gohci . sleeping = 0 ;
gohci . irq = - 1 ;
# ifdef CONFIG_PCI_OHCI
pdev = pci_find_devices ( ohci_pci_ids , 0 ) ;
if ( pdev ! = - 1 ) {
u16 vid , did ;
u32 base ;
pci_read_config_word ( pdev , PCI_VENDOR_ID , & vid ) ;
pci_read_config_word ( pdev , PCI_DEVICE_ID , & did ) ;
printf ( " OHCI pci controller (%04x, %04x) found @(%d:%d:%d) \n " ,
vid , did , ( pdev > > 16 ) & 0xff ,
( pdev > > 11 ) & 0x1f , ( pdev > > 8 ) & 0x7 ) ;
pci_read_config_dword ( pdev , PCI_BASE_ADDRESS_0 , & base ) ;
printf ( " OHCI regs address 0x%08x \n " , base ) ;
gohci . regs = ( struct ohci_regs * ) base ;
} else
return - 1 ;
# else
gohci . regs = ( struct ohci_regs * ) CFG_USB_OHCI_REGS_BASE ;
# endif
gohci . flags = 0 ;
gohci . slot_name = CFG_USB_OHCI_SLOT_NAME ;
@ -1716,7 +1921,6 @@ int usb_lowlevel_init(void)
ohci_dump ( & gohci , 1 ) ;
# else
wait_ms ( 1 ) ;
urb_finished = 1 ;
# endif
ohci_inited = 1 ;
return 0 ;