@ -12,6 +12,7 @@
# include "ehci.h"
# include <linux/mbus.h>
# include <asm/arch/cpu.h>
# include <dm.h>
# if defined(CONFIG_KIRKWOOD)
# include <asm/arch/soc.h>
@ -28,24 +29,19 @@ DECLARE_GLOBAL_DATA_PTR;
/*
* USB 2.0 Bridge Address Decoding registers setup
*/
# ifdef CONFIG_ARMADA_XP
# ifdef CONFIG_DM_USB
/*
* Armada XP and Armada 38 x have different base addresses for
* the USB 2.0 EHCI host controller . So we need to provide
* a mechnism to support both here .
*/
# define MVUSB0_BASE \
( mvebu_soc_family ( ) = = MVEBU_SOC_A38X ? \
MVEBU_USB20_BASE : MVEBU_AXP_USB_BASE )
# define MVUSB_BASE(port) MVUSB0_BASE + ((port) << 12)
struct ehci_mvebu_priv {
struct ehci_ctrl ehci ;
fdt_addr_t hcd_base ;
} ;
/*
* Once all the older Marvell SoC ' s ( Orion , Kirkwood ) are converted
* to the common mvebu archticture including the mbus setup , this
* will be the only function needed to configure the access windows
*/
static void usb_brg_adrdec_setup ( int index )
static void usb_brg_adrdec_setup ( u32 base )
{
const struct mbus_dram_target_info * dram ;
int i ;
@ -53,8 +49,8 @@ static void usb_brg_adrdec_setup(int index)
dram = mvebu_mbus_dram_info ( ) ;
for ( i = 0 ; i < 4 ; i + + ) {
writel ( 0 , MVUSB_BASE ( index ) + USB_WINDOW_CTRL ( i ) ) ;
writel ( 0 , MVUSB_BASE ( index ) + USB_WINDOW_BASE ( i ) ) ;
writel ( 0 , base + USB_WINDOW_CTRL ( i ) ) ;
writel ( 0 , base + USB_WINDOW_BASE ( i ) ) ;
}
for ( i = 0 ; i < dram - > num_cs ; i + + ) {
@ -63,12 +59,69 @@ static void usb_brg_adrdec_setup(int index)
/* Write size, attributes and target id to control register */
writel ( ( ( cs - > size - 1 ) & 0xffff0000 ) | ( cs - > mbus_attr < < 8 ) |
( dram - > mbus_dram_target_id < < 4 ) | 1 ,
MVUSB_BASE ( index ) + USB_WINDOW_CTRL ( i ) ) ;
base + USB_WINDOW_CTRL ( i ) ) ;
/* Write base address to base register */
writel ( cs - > base , MVUSB_BASE ( index ) + USB_WINDOW_BASE ( i ) ) ;
writel ( cs - > base , base + USB_WINDOW_BASE ( i ) ) ;
}
}
static int ehci_mvebu_probe ( struct udevice * dev )
{
struct ehci_mvebu_priv * priv = dev_get_priv ( dev ) ;
struct ehci_hccr * hccr ;
struct ehci_hcor * hcor ;
/*
* Get the base address for EHCI controller from the device node
*/
priv - > hcd_base = dev_get_addr ( dev ) ;
if ( priv - > hcd_base = = FDT_ADDR_T_NONE ) {
debug ( " Can't get the EHCI register base address \n " ) ;
return - ENXIO ;
}
usb_brg_adrdec_setup ( priv - > hcd_base ) ;
hccr = ( struct ehci_hccr * ) ( priv - > hcd_base + 0x100 ) ;
hcor = ( struct ehci_hcor * )
( ( u32 ) hccr + HC_LENGTH ( ehci_readl ( & hccr - > cr_capbase ) ) ) ;
debug ( " ehci-marvell: init hccr %x and hcor %x hc_length %d \n " ,
( u32 ) hccr , ( u32 ) hcor ,
( u32 ) HC_LENGTH ( ehci_readl ( & hccr - > cr_capbase ) ) ) ;
return ehci_register ( dev , hccr , hcor , NULL , 0 , USB_INIT_HOST ) ;
}
static int ehci_mvebu_remove ( struct udevice * dev )
{
int ret ;
ret = ehci_deregister ( dev ) ;
if ( ret )
return ret ;
return 0 ;
}
static const struct udevice_id ehci_usb_ids [ ] = {
{ . compatible = " marvell,orion-ehci " , } ,
{ }
} ;
U_BOOT_DRIVER ( ehci_mvebu ) = {
. name = " ehci_mvebu " ,
. id = UCLASS_USB ,
. of_match = ehci_usb_ids ,
. probe = ehci_mvebu_probe ,
. remove = ehci_mvebu_remove ,
. ops = & ehci_usb_ops ,
. platdata_auto_alloc_size = sizeof ( struct usb_platdata ) ,
. priv_auto_alloc_size = sizeof ( struct ehci_mvebu_priv ) ,
. flags = DM_FLAG_ALLOC_PRIV_DMA ,
} ;
# else
# define MVUSB_BASE(port) MVUSB0_BASE
@ -112,7 +165,6 @@ static void usb_brg_adrdec_setup(int index)
writel ( base , MVUSB0_BASE + USB_WINDOW_BASE ( i ) ) ;
}
}
# endif
/*
* Create the appropriate control structures to manage
@ -142,3 +194,5 @@ int ehci_hcd_stop(int index)
{
return 0 ;
}
# endif /* CONFIG_DM_USB */