diff options
| author | Marek Vasut <marex@denx.de> | 2013-02-23 02:43:02 +0000 | 
|---|---|---|
| committer | Stefano Babic <sbabic@denx.de> | 2013-03-07 17:22:57 +0100 | 
| commit | afa872109942b37fce291b592d6f2f02f55a4021 (patch) | |
| tree | bde602b85c6d3aade25d2c2a3b17b7063c2898ac | |
| parent | 47f13315061b4f931a9263924627b870ec083578 (diff) | |
| download | olio-uboot-2014.01-afa872109942b37fce291b592d6f2f02f55a4021.tar.xz olio-uboot-2014.01-afa872109942b37fce291b592d6f2f02f55a4021.zip | |
mxs: Make ehci-mxs multiport capable
Rework ehci-mxs so it supports both ports on MX28. It was necessary
to wrap the per-port configuration into struct ehci_mxs_port and pull
out the clock configuration function.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Otavio Salvador <otavio@ossystems.com.br>
Cc: Stefano Babic <sbabic@denx.de>
| -rw-r--r-- | drivers/usb/host/ehci-mxs.c | 149 | ||||
| -rw-r--r-- | include/configs/apx4devkit.h | 3 | ||||
| -rw-r--r-- | include/configs/m28evk.h | 4 | ||||
| -rw-r--r-- | include/configs/mx28evk.h | 3 | ||||
| -rw-r--r-- | include/configs/sc_sps_1.h | 3 | 
5 files changed, 90 insertions, 72 deletions
| diff --git a/drivers/usb/host/ehci-mxs.c b/drivers/usb/host/ehci-mxs.c index 0ca7545a3..f320d3eb5 100644 --- a/drivers/usb/host/ehci-mxs.c +++ b/drivers/usb/host/ehci-mxs.c @@ -22,86 +22,106 @@  #include <common.h>  #include <asm/io.h>  #include <asm/arch/imx-regs.h> +#include <errno.h>  #include "ehci.h" -#if	(CONFIG_EHCI_MXS_PORT != 0) && (CONFIG_EHCI_MXS_PORT != 1) -#error	"MXS EHCI: Invalid port selected!" -#endif - -#ifndef	CONFIG_EHCI_MXS_PORT -#error	"MXS EHCI: Please define correct port using CONFIG_EHCI_MXS_PORT!" -#endif +/* This DIGCTL register ungates clock to USB */ +#define	HW_DIGCTL_CTRL			0x8001c000 +#define	HW_DIGCTL_CTRL_USB0_CLKGATE	(1 << 2) +#define	HW_DIGCTL_CTRL_USB1_CLKGATE	(1 << 16) -static struct ehci_mxs { -	struct mxs_usb_regs	*usb_regs; +struct ehci_mxs_port { +	uint32_t		usb_regs;  	struct mxs_usbphy_regs	*phy_regs; -} ehci_mxs; -int mxs_ehci_get_port(struct ehci_mxs *mxs_usb, int port) +	struct mxs_register_32	*pll; +	uint32_t		pll_en_bits; +	uint32_t		pll_dis_bits; +	uint32_t		gate_bits; +}; + +static const struct ehci_mxs_port mxs_port[] = { +#ifdef CONFIG_EHCI_MXS_PORT0 +	{ +		MXS_USBCTRL0_BASE, +		(struct mxs_usbphy_regs *)MXS_USBPHY0_BASE, +		(struct mxs_register_32 *)(MXS_CLKCTRL_BASE + +			offsetof(struct mxs_clkctrl_regs, +			hw_clkctrl_pll0ctrl0_reg)), +		CLKCTRL_PLL0CTRL0_EN_USB_CLKS | CLKCTRL_PLL0CTRL0_POWER, +		CLKCTRL_PLL0CTRL0_EN_USB_CLKS, +		HW_DIGCTL_CTRL_USB0_CLKGATE, +	}, +#endif +#ifdef CONFIG_EHCI_MXS_PORT1 +	{ +		MXS_USBCTRL1_BASE, +		(struct mxs_usbphy_regs *)MXS_USBPHY1_BASE, +		(struct mxs_register_32 *)(MXS_CLKCTRL_BASE + +			offsetof(struct mxs_clkctrl_regs, +			hw_clkctrl_pll1ctrl0_reg)), +		CLKCTRL_PLL1CTRL0_EN_USB_CLKS | CLKCTRL_PLL1CTRL0_POWER, +		CLKCTRL_PLL1CTRL0_EN_USB_CLKS, +		HW_DIGCTL_CTRL_USB1_CLKGATE, +	}, +#endif +}; + +static int ehci_mxs_toggle_clock(const struct ehci_mxs_port *port, int enable)  { -	uint32_t usb_base, phy_base; -	switch (port) { -	case 0: -		usb_base = MXS_USBCTRL0_BASE; -		phy_base = MXS_USBPHY0_BASE; -		break; -	case 1: -		usb_base = MXS_USBCTRL1_BASE; -		phy_base = MXS_USBPHY1_BASE; -		break; -	default: -		printf("CONFIG_EHCI_MXS_PORT (port = %d)\n", port); -		return -1; +	struct mxs_register_32 *digctl_ctrl = +		(struct mxs_register_32 *)HW_DIGCTL_CTRL; +	int pll_offset, dig_offset; + +	if (enable) { +		pll_offset = offsetof(struct mxs_register_32, reg_set); +		dig_offset = offsetof(struct mxs_register_32, reg_clr); +		writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset); +		writel(port->pll_en_bits, (u32)port->pll + pll_offset); +	} else { +		pll_offset = offsetof(struct mxs_register_32, reg_clr); +		dig_offset = offsetof(struct mxs_register_32, reg_set); +		writel(port->pll_dis_bits, (u32)port->pll + pll_offset); +		writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset);  	} -	mxs_usb->usb_regs = (struct mxs_usb_regs *)usb_base; -	mxs_usb->phy_regs = (struct mxs_usbphy_regs *)phy_base;  	return 0;  } -/* This DIGCTL register ungates clock to USB */ -#define	HW_DIGCTL_CTRL			0x8001c000 -#define	HW_DIGCTL_CTRL_USB0_CLKGATE	(1 << 2) -#define	HW_DIGCTL_CTRL_USB1_CLKGATE	(1 << 16) -  int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)  {  	int ret;  	uint32_t usb_base, cap_base; -	struct mxs_register_32 *digctl_ctrl = -		(struct mxs_register_32 *)HW_DIGCTL_CTRL; -	struct mxs_clkctrl_regs *clkctrl_regs = -		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +	const struct ehci_mxs_port *port; -	ret = mxs_ehci_get_port(&ehci_mxs, CONFIG_EHCI_MXS_PORT); -	if (ret) -		return ret; +	if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { +		printf("Invalid port index (index = %d)!\n", index); +		return -EINVAL; +	} + +	port = &mxs_port[index];  	/* Reset the PHY block */ -	writel(USBPHY_CTRL_SFTRST, &ehci_mxs.phy_regs->hw_usbphy_ctrl_set); +	writel(USBPHY_CTRL_SFTRST, &port->phy_regs->hw_usbphy_ctrl_set);  	udelay(10);  	writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, -		&ehci_mxs.phy_regs->hw_usbphy_ctrl_clr); +		&port->phy_regs->hw_usbphy_ctrl_clr);  	/* Enable USB clock */ -	writel(CLKCTRL_PLL0CTRL0_EN_USB_CLKS | CLKCTRL_PLL0CTRL0_POWER, -			&clkctrl_regs->hw_clkctrl_pll0ctrl0_set); -	writel(CLKCTRL_PLL1CTRL0_EN_USB_CLKS | CLKCTRL_PLL1CTRL0_POWER, -			&clkctrl_regs->hw_clkctrl_pll1ctrl0_set); - -	writel(HW_DIGCTL_CTRL_USB0_CLKGATE | HW_DIGCTL_CTRL_USB1_CLKGATE, -		&digctl_ctrl->reg_clr); +	ret = ehci_mxs_toggle_clock(port, 1); +	if (ret) +		return ret;  	/* Start USB PHY */ -	writel(0, &ehci_mxs.phy_regs->hw_usbphy_pwd); +	writel(0, &port->phy_regs->hw_usbphy_pwd);  	/* Enable UTMI+ Level 2 and Level 3 compatibility */  	writel(USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2 | 1, -		&ehci_mxs.phy_regs->hw_usbphy_ctrl_set); +		&port->phy_regs->hw_usbphy_ctrl_set); -	usb_base = ((uint32_t)ehci_mxs.usb_regs) + 0x100; +	usb_base = port->usb_regs + 0x100;  	*hccr = (struct ehci_hccr *)usb_base;  	cap_base = ehci_readl(&(*hccr)->cr_capbase); @@ -114,19 +134,19 @@ int ehci_hcd_stop(int index)  {  	int ret;  	uint32_t usb_base, cap_base, tmp; -	struct mxs_register_32 *digctl_ctrl = -		(struct mxs_register_32 *)HW_DIGCTL_CTRL; -	struct mxs_clkctrl_regs *clkctrl_regs = -		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;  	struct ehci_hccr *hccr;  	struct ehci_hcor *hcor; +	const struct ehci_mxs_port *port; -	ret = mxs_ehci_get_port(&ehci_mxs, CONFIG_EHCI_MXS_PORT); -	if (ret) -		return ret; +	if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { +		printf("Invalid port index (index = %d)!\n", index); +		return -EINVAL; +	} + +	port = &mxs_port[index];  	/* Stop the USB port */ -	usb_base = ((uint32_t)ehci_mxs.usb_regs) + 0x100; +	usb_base = port->usb_regs + 0x100;  	hccr = (struct ehci_hccr *)usb_base;  	cap_base = ehci_readl(&hccr->cr_capbase);  	hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base)); @@ -140,17 +160,10 @@ int ehci_hcd_stop(int index)  		USBPHY_PWD_RXPWD1PT1 | USBPHY_PWD_RXPWDENV |  		USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS |  		USBPHY_PWD_TXPWDFS; -	writel(tmp, &ehci_mxs.phy_regs->hw_usbphy_pwd); +	writel(tmp, &port->phy_regs->hw_usbphy_pwd);  	/* Disable USB clock */ -	writel(CLKCTRL_PLL0CTRL0_EN_USB_CLKS, -			&clkctrl_regs->hw_clkctrl_pll0ctrl0_clr); -	writel(CLKCTRL_PLL1CTRL0_EN_USB_CLKS, -			&clkctrl_regs->hw_clkctrl_pll1ctrl0_clr); +	ret = ehci_mxs_toggle_clock(port, 0); -	/* Gate off the USB clock */ -	writel(HW_DIGCTL_CTRL_USB0_CLKGATE | HW_DIGCTL_CTRL_USB1_CLKGATE, -		&digctl_ctrl->reg_set); - -	return 0; +	return ret;  } diff --git a/include/configs/apx4devkit.h b/include/configs/apx4devkit.h index 73c66af06..18c424137 100644 --- a/include/configs/apx4devkit.h +++ b/include/configs/apx4devkit.h @@ -182,7 +182,8 @@  #ifdef CONFIG_CMD_USB  #define CONFIG_USB_EHCI  #define CONFIG_USB_EHCI_MXS -#define CONFIG_EHCI_MXS_PORT		1 +#define CONFIG_EHCI_MXS_PORT1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT	1  #define CONFIG_EHCI_IS_TDI  #define CONFIG_USB_STORAGE  #endif diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h index 59a7be931..f2725cc87 100644 --- a/include/configs/m28evk.h +++ b/include/configs/m28evk.h @@ -233,7 +233,9 @@  #ifdef	CONFIG_CMD_USB  #define	CONFIG_USB_EHCI  #define	CONFIG_USB_EHCI_MXS -#define	CONFIG_EHCI_MXS_PORT		1 +#define CONFIG_EHCI_MXS_PORT0 +#define CONFIG_EHCI_MXS_PORT1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT	2  #define	CONFIG_EHCI_IS_TDI  #define	CONFIG_USB_STORAGE  #endif diff --git a/include/configs/mx28evk.h b/include/configs/mx28evk.h index 6a46f3c08..0d918a153 100644 --- a/include/configs/mx28evk.h +++ b/include/configs/mx28evk.h @@ -181,7 +181,8 @@  #ifdef	CONFIG_CMD_USB  #define	CONFIG_USB_EHCI  #define	CONFIG_USB_EHCI_MXS -#define	CONFIG_EHCI_MXS_PORT 1 +#define CONFIG_EHCI_MXS_PORT1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT	1  #define	CONFIG_EHCI_IS_TDI  #define	CONFIG_USB_STORAGE  #define	CONFIG_USB_HOST_ETHER diff --git a/include/configs/sc_sps_1.h b/include/configs/sc_sps_1.h index decf8d9de..349497f67 100644 --- a/include/configs/sc_sps_1.h +++ b/include/configs/sc_sps_1.h @@ -170,7 +170,8 @@  #ifdef CONFIG_CMD_USB  #define CONFIG_USB_EHCI  #define CONFIG_USB_EHCI_MXS -#define CONFIG_EHCI_MXS_PORT		0 +#define CONFIG_EHCI_MXS_PORT0 +#define CONFIG_USB_MAX_CONTROLLER_COUNT	1  #define CONFIG_EHCI_IS_TDI  #define CONFIG_USB_STORAGE  #endif |