diff options
author | Ye Li <ye.li@nxp.com> | 2017-06-05 23:03:24 -0500 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2017-11-03 02:36:53 +0800 |
commit | cf0dd3af4c1d6d96e7394da46258e19cf281c6f0 (patch) | |
tree | 975982546ea47beadf589e1c1e181ae4dfe597a4 | |
parent | 657f18f11d6863a601892ec3573c70256ab64d60 (diff) |
MLK-15013-1 ehci-mx6: Add i.MX8 OTG controller support
The i.MX8 has two USB controllers: USBOH and USB3. The USBOH reuses
previous i.MX6/7. It has same PHY IP as i.MX7ULP but NC registers
are same as i.MX7D. So add its support in ehci-mx6 driver.
Also the driver is updated to remove build warning for 64 bits CPU.
Signed-off-by: Ye Li <ye.li@nxp.com>
-rw-r--r-- | arch/arm/include/asm/arch-imx8/imx-regs.h | 77 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mx6.c | 99 |
3 files changed, 160 insertions, 18 deletions
diff --git a/arch/arm/include/asm/arch-imx8/imx-regs.h b/arch/arm/include/asm/arch-imx8/imx-regs.h index c8c597724d1..78c44a4b6d1 100644 --- a/arch/arm/include/asm/arch-imx8/imx-regs.h +++ b/arch/arm/include/asm/arch-imx8/imx-regs.h @@ -34,14 +34,87 @@ #define ROM_SW_INFO_ADDR 0x00000890 -#define OTG_BASE_ADDR 0x5b0d0000 +#define USB_BASE_ADDR 0x5b0d0000 #define USB_PHY0_BASE_ADDR 0x5b100000 +#if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__)) +#include <asm/types.h> + /* * If ROM fail back to USB recover mode, USBPH0_PWD will be clear to use USB * If boot from the other mode, USB0_PWD will keep reset value */ #define is_boot_from_usb(void) (!(readl(USB_PHY0_BASE_ADDR) & (1<<20))) -#define disconnect_from_pc(void) writel(0x0, OTG_BASE_ADDR + 0x140) +#define disconnect_from_pc(void) writel(0x0, USB_BASE_ADDR + 0x140) + +struct usbphy_regs { + u32 usbphy_pwd; /* 0x000 */ + u32 usbphy_pwd_set; /* 0x004 */ + u32 usbphy_pwd_clr; /* 0x008 */ + u32 usbphy_pwd_tog; /* 0x00c */ + u32 usbphy_tx; /* 0x010 */ + u32 usbphy_tx_set; /* 0x014 */ + u32 usbphy_tx_clr; /* 0x018 */ + u32 usbphy_tx_tog; /* 0x01c */ + u32 usbphy_rx; /* 0x020 */ + u32 usbphy_rx_set; /* 0x024 */ + u32 usbphy_rx_clr; /* 0x028 */ + u32 usbphy_rx_tog; /* 0x02c */ + u32 usbphy_ctrl; /* 0x030 */ + u32 usbphy_ctrl_set; /* 0x034 */ + u32 usbphy_ctrl_clr; /* 0x038 */ + u32 usbphy_ctrl_tog; /* 0x03c */ + u32 usbphy_status; /* 0x040 */ + u32 reserved0[3]; + u32 usbphy_debug0; /* 0x050 */ + u32 usbphy_debug0_set; /* 0x054 */ + u32 usbphy_debug0_clr; /* 0x058 */ + u32 usbphy_debug0_tog; /* 0x05c */ + u32 reserved1[4]; + u32 usbphy_debug1; /* 0x070 */ + u32 usbphy_debug1_set; /* 0x074 */ + u32 usbphy_debug1_clr; /* 0x078 */ + u32 usbphy_debug1_tog; /* 0x07c */ + u32 usbphy_version; /* 0x080 */ + u32 reserved2[7]; + u32 usb1_pll_480_ctrl; /* 0x0a0 */ + u32 usb1_pll_480_ctrl_set; /* 0x0a4 */ + u32 usb1_pll_480_ctrl_clr; /* 0x0a8 */ + u32 usb1_pll_480_ctrl_tog; /* 0x0ac */ + u32 reserved3[4]; + u32 usb1_vbus_detect; /* 0xc0 */ + u32 usb1_vbus_detect_set; /* 0xc4 */ + u32 usb1_vbus_detect_clr; /* 0xc8 */ + u32 usb1_vbus_detect_tog; /* 0xcc */ + u32 usb1_vbus_det_stat; /* 0xd0 */ + u32 reserved4[3]; + u32 usb1_chrg_detect; /* 0xe0 */ + u32 usb1_chrg_detect_set; /* 0xe4 */ + u32 usb1_chrg_detect_clr; /* 0xe8 */ + u32 usb1_chrg_detect_tog; /* 0xec */ + u32 usb1_chrg_det_stat; /* 0xf0 */ + u32 reserved5[3]; + u32 usbphy_anactrl; /* 0x100 */ + u32 usbphy_anactrl_set; /* 0x104 */ + u32 usbphy_anactrl_clr; /* 0x108 */ + u32 usbphy_anactrl_tog; /* 0x10c */ + u32 usb1_loopback; /* 0x110 */ + u32 usb1_loopback_set; /* 0x114 */ + u32 usb1_loopback_clr; /* 0x118 */ + u32 usb1_loopback_tog; /* 0x11c */ + u32 usb1_loopback_hsfscnt; /* 0x120 */ + u32 usb1_loopback_hsfscnt_set; /* 0x124 */ + u32 usb1_loopback_hsfscnt_clr; /* 0x128 */ + u32 usb1_loopback_hsfscnt_tog; /* 0x12c */ + u32 usphy_trim_override_en; /* 0x130 */ + u32 usphy_trim_override_en_set; /* 0x134 */ + u32 usphy_trim_override_en_clr; /* 0x138 */ + u32 usphy_trim_override_en_tog; /* 0x13c */ + u32 usb1_pfda_ctrl1; /* 0x140 */ + u32 usb1_pfda_ctrl1_set; /* 0x144 */ + u32 usb1_pfda_ctrl1_clr; /* 0x148 */ + u32 usb1_pfda_ctrl1_tog; /* 0x14c */ +}; +#endif #endif /* __ASM_ARCH_IMX_REGS_H__ */ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 7e76f193210..765aba682fd 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -88,7 +88,7 @@ config USB_EHCI_MARVELL config USB_EHCI_MX6 bool "Support for i.MX6 on-chip EHCI USB controller" - depends on ARCH_MX6 || ARCH_MX7ULP + depends on ARCH_MX6 || ARCH_MX7ULP || ARCH_IMX8 default y ---help--- Enables support for the on-chip EHCI controller on i.MX6 SoCs. diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 9268e21dd45..e3c3060b078 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -60,12 +60,20 @@ DECLARE_GLOBAL_DATA_PTR; #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ +#define PLL_USB_EN_USB_CLKS_MASK (0x01 << 6) +#define PLL_USB_PWR_MASK (0x01 << 12) +#define PLL_USB_ENABLE_MASK (0x01 << 13) +#define PLL_USB_BYPASS_MASK (0x01 << 16) +#define PLL_USB_REG_ENABLE_MASK (0x01 << 21) +#define PLL_USB_DIV_SEL_MASK (0x07 << 22) +#define PLL_USB_LOCK_MASK (0x01 << 31) + /* USBCMD */ #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ #define UCMD_RESET (1 << 1) /* controller reset */ -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) -static const unsigned phy_bases[] = { +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) +static const ulong phy_bases[] = { USB_PHY0_BASE_ADDR, #if defined(USB_PHY1_BASE_ADDR) USB_PHY1_BASE_ADDR, @@ -99,6 +107,53 @@ static void usb_power_config(int index) scg_enable_usb_pll(true); +#elif defined(CONFIG_IMX8) + struct usbphy_regs __iomem *usbphy = + (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; + int timeout = 1000000; + + if (index > 0) + return; + + writel(ANADIG_USB2_CHRG_DETECT_EN_B | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, + &usbphy->usb1_chrg_detect); + + if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { + + /* Enable the regulator first */ + writel(PLL_USB_REG_ENABLE_MASK, + &usbphy->usb1_pll_480_ctrl_set); + + /* Wait at least 25us */ + udelay(25); + + /* Enable the power */ + writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); + + /* Wait lock */ + while (timeout--) { + if (readl(&usbphy->usb1_pll_480_ctrl) & + PLL_USB_LOCK_MASK) + break; + udelay(10); + } + + if (timeout <= 0) { + /* If timeout, we power down the pll */ + writel(PLL_USB_PWR_MASK, + &usbphy->usb1_pll_480_ctrl_clr); + return; + } + } + + /* Clear the bypass */ + writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); + + /* Enable the PLL clock out to USB */ + writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), + &usbphy->usb1_pll_480_ctrl_set); + #else struct anatop_regs __iomem *anatop = (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; @@ -211,6 +266,20 @@ struct usbnc_regs { u32 reserve0[2]; u32 hsic_ctrl; }; +#elif defined(CONFIG_IMX8) +struct usbnc_regs { + u32 ctrl1; + u32 ctrl2; + u32 reserve1[10]; + u32 phy_cfg1; + u32 phy_cfg2; + u32 reserve2; + u32 phy_status; + u32 reserve3[4]; + u32 adp_cfg1; + u32 adp_cfg2; + u32 adp_status; +}; #else /* Base address for this IP block is 0x02184800 */ struct usbnc_regs { @@ -239,7 +308,7 @@ struct usbnc_regs { static void usb_power_config(int index) { - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + (0x10000 * index) + USBNC_OFFSET); void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); @@ -252,7 +321,7 @@ static void usb_power_config(int index) int usb_phy_mode(int port) { - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + (0x10000 * port) + USBNC_OFFSET); void __iomem *status = (void __iomem *)(&usbnc->phy_status); u32 val; @@ -291,8 +360,8 @@ static void usb_oc_config(int index) struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET); void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); -#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + +#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + (0x10000 * index) + USBNC_OFFSET); void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); #endif @@ -375,7 +444,7 @@ int ehci_mx6_common_init(struct usb_ehci *ehci, int index) usb_power_config(index); usb_oc_config(index); -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) usb_internal_phy_clock_gate(index, 1); usb_phy_enable(index, ehci); #endif @@ -394,10 +463,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, enum usb_init_type type; #if defined(CONFIG_MX6) u32 controller_spacing = 0x200; -#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) +#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) u32 controller_spacing = 0x10000; #endif - struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR + + struct usb_ehci *ehci = (struct usb_ehci *)(ulong)(USB_BASE_ADDR + (controller_spacing * index)); int ret; @@ -420,8 +489,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, type = board_usb_phy_mode(index); if (hccr && hcor) { - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + + *hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); + *hcor = (struct ehci_hcor *)((ulong)*hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); } @@ -524,7 +593,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) * About fsl,usbphy, Refer to * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt. */ - if (is_mx6() || is_mx7ulp()) { + if (is_mx6() || is_mx7ulp() || is_imx8()) { phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy"); @@ -578,7 +647,7 @@ static int ehci_usb_ofdata_to_platdata(struct udevice *dev) return 0; } else { - extcon = fdt_get_property(gd->fdt_blob, dev_of_offset(dev), + extcon = fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "extcon", NULL); if (extcon) { plat->init_type = board_ehci_usb_phy_mode(dev); @@ -637,8 +706,8 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(10); - hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - hcor = (struct ehci_hcor *)((uint32_t)hccr + + hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); + hcor = (struct ehci_hcor *)((ulong)hccr + HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); |