@ -14,53 +14,88 @@
# include <asm/arch/clock.h>
# include <asm/arch/usb_phy.h>
# include <asm/io.h>
# include <dm.h>
# include "ehci.h"
int ehci_hcd_init ( int index , enum usb_init_type init , struct ehci_hccr * * hccr ,
struct ehci_hcor * * hcor )
struct ehci_sunxi_priv {
struct ehci_ctrl ehci ;
int ahb_gate_mask ; /* Mask of ahb_gate0 clk gate bits for this hcd */
int phy_index ; /* Index of the usb-phy attached to this hcd */
} ;
static int ehci_usb_probe ( struct udevice * dev )
{
struct sunxi_ccm_reg * ccm = ( struct sunxi_ccm_reg * ) SUNXI_CCM_BASE ;
int ahb_gate_offset ;
struct usb_platdata * plat = dev_get_platdata ( dev ) ;
struct ehci_sunxi_priv * priv = dev_get_priv ( dev ) ;
struct ehci_hccr * hccr = ( struct ehci_hccr * ) dev_get_addr ( dev ) ;
struct ehci_hcor * hcor ;
/*
* This should go away once we ' ve moved to the driver model for
* clocks resp . phys .
*/
if ( hccr = = ( void * ) SUNXI_USB1_BASE ) {
priv - > ahb_gate_mask = 1 < < AHB_GATE_OFFSET_USB_EHCI0 ;
priv - > phy_index = 1 ;
} else {
priv - > ahb_gate_mask = 1 < < AHB_GATE_OFFSET_USB_EHCI1 ;
priv - > phy_index = 2 ;
}
ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
AHB_GATE_OFFSET_USB_EHCI0 ;
setbits_le32 ( & ccm - > ahb_gate0 , 1 < < ahb_gate_offset ) ;
setbits_le32 ( & ccm - > ahb_gate0 , priv - > ahb_gate_mask ) ;
# ifdef CONFIG_SUNXI_GEN_SUN6I
setbits_le32 ( & ccm - > ahb_reset0_cfg , 1 < < ahb_gate_offset ) ;
setbits_le32 ( & ccm - > ahb_reset0_cfg , priv - > ahb_gate_mask ) ;
# endif
sunxi_usb_phy_init ( index + 1 ) ;
sunxi_usb_phy_power_on ( index + 1 ) ;
if ( index = = 0 )
* hccr = ( void * ) SUNXI_USB1_BASE ;
else
* hccr = ( void * ) SUNXI_USB2_BASE ;
* hcor = ( struct ehci_hcor * ) ( ( uint32_t ) * hccr
+ HC_LENGTH ( ehci_readl ( & ( * hccr ) - > cr_capbase ) ) ) ;
sunxi_usb_phy_init ( priv - > phy_index ) ;
sunxi_usb_phy_power_on ( priv - > phy_index ) ;
debug ( " sunxi-ehci: init hccr %x and hcor %x hc_length %d \n " ,
( uint32_t ) * hccr , ( uint32_t ) * hcor ,
( uint32_t ) HC_LENGTH ( ehci_readl ( & ( * hccr ) - > cr_capbase ) ) ) ;
hcor = ( struct ehci_hcor * ) ( ( uint32_t ) hccr +
HC_LENGTH ( ehci_readl ( & hccr - > cr_capbase ) ) ) ;
return 0 ;
return ehci_register ( dev , hccr , hcor , NULL , 0 , plat - > init_type ) ;
}
int ehci_hcd_stop ( int index )
static int ehci_usb_remove ( struct udevice * dev )
{
struct sunxi_ccm_reg * ccm = ( struct sunxi_ccm_reg * ) SUNXI_CCM_BASE ;
int ahb_gate_offset ;
struct ehci_sunxi_priv * priv = dev_get_priv ( dev ) ;
int ret ;
ret = ehci_deregister ( dev ) ;
if ( ret )
return ret ;
sunxi_usb_phy_power_off ( index + 1 ) ;
sunxi_usb_phy_exit ( index + 1 ) ;
sunxi_usb_phy_power_off ( priv - > phy_index ) ;
sunxi_usb_phy_exit ( priv - > phy_index ) ;
ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
AHB_GATE_OFFSET_USB_EHCI0 ;
# ifdef CONFIG_SUNXI_GEN_SUN6I
clrbits_le32 ( & ccm - > ahb_reset0_cfg , 1 < < ahb_gate_offset ) ;
clrbits_le32 ( & ccm - > ahb_reset0_cfg , priv - > ahb_gate_mask ) ;
# endif
clrbits_le32 ( & ccm - > ahb_gate0 , 1 < < ahb_gate_offset ) ;
clrbits_le32 ( & ccm - > ahb_gate0 , priv - > ahb_gate_mask ) ;
return 0 ;
}
static const struct udevice_id ehci_usb_ids [ ] = {
{ . compatible = " allwinner,sun4i-a10-ehci " , } ,
{ . compatible = " allwinner,sun5i-a13-ehci " , } ,
{ . compatible = " allwinner,sun6i-a31-ehci " , } ,
{ . compatible = " allwinner,sun7i-a20-ehci " , } ,
{ . compatible = " allwinner,sun8i-a23-ehci " , } ,
{ . compatible = " allwinner,sun9i-a80-ehci " , } ,
{ }
} ;
U_BOOT_DRIVER ( usb_ehci ) = {
. name = " ehci_sunxi " ,
. id = UCLASS_USB ,
. of_match = ehci_usb_ids ,
. probe = ehci_usb_probe ,
. remove = ehci_usb_remove ,
. ops = & ehci_usb_ops ,
. platdata_auto_alloc_size = sizeof ( struct usb_platdata ) ,
. priv_auto_alloc_size = sizeof ( struct ehci_sunxi_priv ) ,
. flags = DM_FLAG_ALLOC_PRIV_DMA ,
} ;