@ -35,6 +35,7 @@
# define USBPHY_CTRL_CLKGATE 0x40000000
# define USBPHY_CTRL_ENUTMILEVEL3 0x00008000
# define USBPHY_CTRL_ENUTMILEVEL2 0x00004000
# define USBPHY_CTRL_OTG_ID 0x08000000
# define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000
# define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000
@ -49,52 +50,84 @@
# define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */
/* USBCMD */
# define UH1_USBCMD_OFFSET 0x140
# define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
# define UCMD_RESET (1 << 1) /* controller reset */
static void usbh1_internal_phy_clock_gate ( int on )
static const unsigned phy_bases [ ] = {
USB_PHY0_BASE_ADDR ,
USB_PHY1_BASE_ADDR ,
} ;
static void usb_internal_phy_clock_gate ( int index , int on )
{
void __iomem * phy_reg = ( void __iomem * ) USB_PHY1_BASE_ADDR ;
void __iomem * phy_reg ;
if ( index > = ARRAY_SIZE ( phy_bases ) )
return ;
phy_reg = ( void __iomem * ) phy_bases [ index ] ;
phy_reg + = on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET ;
__raw_writel ( USBPHY_CTRL_CLKGATE , phy_reg ) ;
}
static void usbh1 _power_config ( vo id)
static void usb_power_config ( int in dex )
{
struct anatop_regs __iomem * anatop =
( struct anatop_regs __iomem * ) ANATOP_BASE_ADDR ;
void __iomem * chrg_detect ;
void __iomem * pll_480_ctrl_clr ;
void __iomem * pll_480_ctrl_set ;
switch ( index ) {
case 0 :
chrg_detect = & anatop - > usb1_chrg_detect ;
pll_480_ctrl_clr = & anatop - > usb1_pll_480_ctrl_clr ;
pll_480_ctrl_set = & anatop - > usb1_pll_480_ctrl_set ;
break ;
case 1 :
chrg_detect = & anatop - > usb2_chrg_detect ;
pll_480_ctrl_clr = & anatop - > usb2_pll_480_ctrl_clr ;
pll_480_ctrl_set = & anatop - > usb2_pll_480_ctrl_set ;
break ;
default :
return ;
}
/*
* Some phy and power ' s special controls for host1
* Some phy and power ' s special controls
* 1. The external charger detector needs to be disabled
* or the signal at DP will be poor
* 2. The PLL ' s power and output to usb for host 1
* 2. The PLL ' s power and output to usb
* is totally controlled by IC , so the Software only needs
* to enable them at initializtion .
*/
__raw_writel ( ANADIG_USB2_CHRG_DETECT_EN_B |
ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B ,
& anatop - > usb2_chrg_detect ) ;
chrg_detect ) ;
__raw_writel ( ANADIG_USB2_PLL_480_CTRL_BYPASS ,
& anatop - > usb2_pll_480_ctrl_clr ) ;
pll_480_ctrl_clr ) ;
__raw_writel ( ANADIG_USB2_PLL_480_CTRL_ENABLE |
ANADIG_USB2_PLL_480_CTRL_POWER |
ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS ,
& anatop - > usb2_ pll_480_ctrl_set) ;
pll_480_ctrl_set ) ;
}
static int usbh1_phy_enable ( void )
/* Return 0 : host node, <>0 : device mode */
static int usb_phy_enable ( int index , struct usb_ehci * ehci )
{
void __iomem * phy_reg = ( void __iomem * ) USB_PHY1_BASE_ADDR ;
void __iomem * phy_ctrl = ( void __iomem * ) ( phy_reg + USBPHY_CTRL ) ;
void __iomem * usb_cmd = ( void __iomem * ) ( USBOH3_USB_BASE_ADDR +
USB_H1REGS_OFFSET +
UH1_USBCMD_OFFSET ) ;
void __iomem * phy_reg ;
void __iomem * phy_ctrl ;
void __iomem * usb_cmd ;
u32 val ;
if ( index > = ARRAY_SIZE ( phy_bases ) )
return 0 ;
phy_reg = ( void __iomem * ) phy_bases [ index ] ;
phy_ctrl = ( void __iomem * ) ( phy_reg + USBPHY_CTRL ) ;
usb_cmd = ( void __iomem * ) & ehci - > usbcmd ;
/* Stop then Reset */
val = __raw_readl ( usb_cmd ) ;
val & = ~ UCMD_RUN_STOP ;
@ -123,31 +156,41 @@ static int usbh1_phy_enable(void)
/* Power up the PHY */
__raw_writel ( 0 , phy_reg + USBPHY_PWD ) ;
/* enable FS/LS device */
val = __raw_readl ( phy_reg + USBPHY_CTRL ) ;
val = __raw_readl ( phy_ctrl ) ;
val | = ( USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3 ) ;
__raw_writel ( val , phy_reg + USBPHY_CTRL ) ;
__raw_writel ( val , phy_ctrl ) ;
return 0 ;
return val & USBPHY_CTRL_OTG_ID ;
}
static void usbh1_oc_config ( void )
/* Base address for this IP block is 0x02184800 */
struct usbnc_regs {
u32 ctrl [ 4 ] ; /* otg/host1-3 */
u32 uh2_hsic_ctrl ;
u32 uh3_hsic_ctrl ;
u32 otg_phy_ctrl_0 ;
u32 uh1_phy_ctrl_0 ;
} ;
static void usb_oc_config ( int index )
{
void __iomem * usb_base = ( void __iomem * ) USBOH3_USB_BASE_ADDR ;
void __iomem * usbother_base = usb_base + USB_OTHERREGS_OFFSET ;
struct usbnc_regs * usbnc = ( struct usbnc_regs * ) ( USBOH3_USB_BASE_ADDR +
USB_OTHERREGS_OFFSET ) ;
void __iomem * ctrl = ( void __iomem * ) ( & usbnc - > ctrl [ index ] ) ;
u32 val ;
val = __raw_readl ( usbother_base + USB_H1_CTRL_OFFSET ) ;
val = __raw_readl ( ctrl ) ;
# if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
/* mx6qarm2 seems to required a different setting*/
val & = ~ UCTRL_OVER_CUR_POL ;
# else
val | = UCTRL_OVER_CUR_POL ;
# endif
__raw_writel ( val , usbother_base + USB_H1_CTRL_OFFSET ) ;
__raw_writel ( val , ctrl ) ;
val = __raw_readl ( usbother_base + USB_H1_CTRL_OFFSET ) ;
val = __raw_readl ( ctrl ) ;
val | = UCTRL_OVER_CUR_DIS ;
__raw_writel ( val , usbother_base + USB_H1_CTRL_OFFSET ) ;
__raw_writel ( val , ctrl ) ;
}
int __weak board_ehci_hcd_init ( int port )
@ -155,34 +198,42 @@ int __weak board_ehci_hcd_init(int port)
return 0 ;
}
int __weak board_ehci_power ( int port , int on )
{
return 0 ;
}
int ehci_hcd_init ( int index , enum usb_init_type init ,
struct ehci_hccr * * hccr , struct ehci_hcor * * hcor )
{
struct usb_ehci * ehci ;
enum usb_init_type type ;
struct usb_ehci * ehci = ( struct usb_ehci * ) ( USBOH3_USB_BASE_ADDR +
( 0x200 * index ) ) ;
if ( index > 3 )
return - EINVAL ;
enable_usboh3_clk ( 1 ) ;
mdelay ( 1 ) ;
/* Do board specific initialization */
board_ehci_hcd_init ( CONFIG_MXC_USB_PORT ) ;
# if CONFIG_MXC_USB_PORT == 1
/* USB Host 1 */
usbh1_power_config ( ) ;
usbh1_oc_config ( ) ;
usbh1_internal_phy_clock_gate ( 1 ) ;
usbh1_phy_enable ( ) ;
# else
# error "MXC USB port not yet supported"
# endif
board_ehci_hcd_init ( index ) ;
usb_power_config ( index ) ;
usb_oc_config ( index ) ;
usb_internal_phy_clock_gate ( index , 1 ) ;
type = usb_phy_enable ( index , ehci ) ? USB_INIT_DEVICE : USB_INIT_HOST ;
ehci = ( struct usb_ehci * ) ( USBOH3_USB_BASE_ADDR +
( 0x200 * CONFIG_MXC_USB_PORT ) ) ;
* hccr = ( struct ehci_hccr * ) ( ( uint32_t ) & ehci - > caplength ) ;
* hcor = ( struct ehci_hcor * ) ( ( uint32_t ) * hccr +
HC_LENGTH ( ehci_readl ( & ( * hccr ) - > cr_capbase ) ) ) ;
setbits_le32 ( & ehci - > usbmode , CM_HOST ) ;
if ( ( type = = init ) | | ( type = = USB_INIT_DEVICE ) )
board_ehci_power ( index , ( type = = USB_INIT_DEVICE ) ? 0 : 1 ) ;
if ( type ! = init )
return - ENODEV ;
if ( type = = USB_INIT_DEVICE )
return 0 ;
setbits_le32 ( & ehci - > usbmode , CM_HOST ) ;
__raw_writel ( CONFIG_MXC_USB_PORTSC , & ehci - > portsc ) ;
setbits_le32 ( & ehci - > portsc , USB_EN ) ;