summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/usb-imx6.c111
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;
+}