diff options
| -rw-r--r-- | drivers/usb/host/ehci-mx6.c | 129 | ||||
| -rw-r--r-- | include/configs/mx6qsabreauto.h | 3 | ||||
| -rw-r--r-- | include/configs/nitrogen6x.h | 3 | 
3 files changed, 94 insertions, 41 deletions
| diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 4d7da5288..c0a557b2a 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -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(void) +static void usb_power_config(int index)  {  	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); +	board_ehci_hcd_init(index); -#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 +	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); diff --git a/include/configs/mx6qsabreauto.h b/include/configs/mx6qsabreauto.h index 5530fc6f2..9e48a4918 100644 --- a/include/configs/mx6qsabreauto.h +++ b/include/configs/mx6qsabreauto.h @@ -23,7 +23,8 @@  #define CONFIG_USB_STORAGE  #define CONFIG_USB_HOST_ETHER  #define CONFIG_USB_ETHER_ASIX -#define CONFIG_MXC_USB_PORT	1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET	/* For OTG port */  #define CONFIG_MXC_USB_PORTSC	(PORT_PTS_UTMI | PORT_PTS_PTW)  #define CONFIG_MXC_USB_FLAGS	0 diff --git a/include/configs/nitrogen6x.h b/include/configs/nitrogen6x.h index 065dc9711..a08eea65c 100644 --- a/include/configs/nitrogen6x.h +++ b/include/configs/nitrogen6x.h @@ -125,7 +125,8 @@  #define CONFIG_USB_HOST_ETHER  #define CONFIG_USB_ETHER_ASIX  #define CONFIG_USB_ETHER_SMSC95XX -#define CONFIG_MXC_USB_PORT	1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET	/* For OTG port */  #define CONFIG_MXC_USB_PORTSC	(PORT_PTS_UTMI | PORT_PTS_PTW)  #define CONFIG_MXC_USB_FLAGS	0 |