diff options
-rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/usb-imx6.c | 111 |
2 files changed, 112 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 2ff537ab89..7b872f6da3 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_ARCH_IMX31) += speed-imx31.o imx31.o iomux-v2.o obj-$(CONFIG_ARCH_IMX35) += speed-imx35.o imx35.o iomux-v3.o obj-$(CONFIG_ARCH_IMX51) += speed-imx51.o imx51.o iomux-v3.o imx5.o obj-$(CONFIG_ARCH_IMX53) += speed-imx53.o imx53.o iomux-v3.o imx5.o -obj-$(CONFIG_ARCH_IMX6) += speed-imx6.o imx6.o iomux-v3.o +obj-$(CONFIG_ARCH_IMX6) += speed-imx6.o imx6.o iomux-v3.o usb-imx6.o obj-$(CONFIG_IMX_CLKO) += clko.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_NAND_IMX) += nand.o diff --git a/arch/arm/mach-imx/usb-imx6.c b/arch/arm/mach-imx/usb-imx6.c new file mode 100644 index 0000000000..cd234d2084 --- /dev/null +++ b/arch/arm/mach-imx/usb-imx6.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Steffen Trumtrar, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation. + * + */ + +#include <common.h> +#include <io.h> +#include <mach/imx6-regs.h> + +#define SET 0x4 +#define CLR 0x8 + +#define USBPHY_CTRL 0x30 +#define USB_OTG_CTRL 0x800 +#define USB_UH1_CTRL 0x804 +#define USB_UH2_CTRL 0x808 +#define USB_UH3_CTRL 0x80c + +#define USB_UH1_USBCMD 0x340 + +#define USB_CMD_RUNSTOP (1 << 0) +#define USB_CMD_RESET (1 << 1) + +#define USB_OVER_CUR_DIS (1 << 7) +#define USBPHY_CTRL_SFTRST (1 << 31) +#define USBPHY_CTRL_CLKGATE (1 << 30) +#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) +#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) + +#define USBPHY1_PLL_480_CTRL_EN (1 << 13) +#define USBPHY1_PLL_480_CTRL_POWER (1 << 12) +#define USBPHY1_PLL_480_CTRL_EN_USB_CLK (1 << 6) +#define USBPHY1_PLL_480_CTRL_BYPASS (1 << 16) + +int imx6_usb_phy1_disable_oc(void) +{ + int val; + + /* disable over current detection */ + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL); + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL); + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL); + + return 0; +} + +int imx6_usb_phy1_enable(void) +{ + int val; + + /* disable external charger detector or DP will be poor */ + writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x1b0); + writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x210); + + /* enable usb pll */ + writel(USBPHY1_PLL_480_CTRL_EN | + USBPHY1_PLL_480_CTRL_POWER | + USBPHY1_PLL_480_CTRL_EN_USB_CLK, MX6_ANATOP_BASE_ADDR + 0x24); + + /* turn OFF clk bypass */ + /* at least on imx6 v1.0 this essential for usb to work */ + /* FIXME: test on v1.1. Datasheet declares bit as reserved */ + writel(USBPHY1_PLL_480_CTRL_BYPASS, MX6_ANATOP_BASE_ADDR + 0x28); + + /* stop then reset */ + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + val &= ~USB_CMD_RUNSTOP; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RUNSTOP); + + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + val |= USB_CMD_RESET; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RESET); + + /* reset usbphy */ + writel(USBPHY_CTRL_SFTRST, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + udelay(10); + /* clr reset and clkgate */ + writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + CLR); + + /* clr all pwd bits => power up phy */ + writel(0xffffffff, MX6_USBPHY1_BASE_ADDR + CLR); + + /* set utmilvl2/3 */ + val = readl(MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL); + val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2; + writel(val, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + + return 0; +} |