Skip to content
Snippets Groups Projects
Commit a5f9bb4b authored by Ye Li's avatar Ye Li Committed by Troy Kisky
Browse files

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: default avatarYe Li <ye.li@nxp.com>
parent 087778bd
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*
*/
#ifndef __ASM_ARCH_IMX_REGS_H__
#define __ASM_ARCH_IMX_REGS_H__
#define MU_BASE_ADDR(id) ((0x5D1B0000UL + (id*0x10000)))
#define LPUART_BASE 0x5A060000
#define GPT1_BASE_ADDR 0x5D140000
#define SCU_LPUART_BASE 0x33220000
#define GPIO1_BASE_ADDR 0x5D080000
#define GPIO2_BASE_ADDR 0x5D090000
#define GPIO3_BASE_ADDR 0x5D0A0000
#define GPIO4_BASE_ADDR 0x5D0B0000
#define GPIO5_BASE_ADDR 0x5D0C0000
#define GPIO6_BASE_ADDR 0x5D0D0000
#define GPIO7_BASE_ADDR 0x5D0E0000
#define GPIO8_BASE_ADDR 0x5D0F0000
#define LPI2C1_BASE_ADDR 0x5A800000
#define LPI2C2_BASE_ADDR 0x5A810000
#define LPI2C3_BASE_ADDR 0x5A820000
#define LPI2C4_BASE_ADDR 0x5A830000
#define LPI2C5_BASE_ADDR 0x5A840000
#ifdef CONFIG_LPUART
#define LPUART_BASE SCU_LPUART_BASE
#endif
#define ROM_SW_INFO_ADDR 0x00000890
#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, 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__ */
......@@ -142,7 +142,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.
......
......@@ -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;
......@@ -210,6 +265,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 {
......@@ -238,7 +307,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);
......@@ -251,7 +320,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;
......@@ -290,8 +359,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
......@@ -374,7 +443,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
......@@ -393,10 +462,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;
......@@ -419,8 +488,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)));
}
......@@ -523,7 +592,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");
......@@ -577,7 +646,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);
......@@ -636,8 +705,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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment