112 lines
3.4 KiB
C
112 lines
3.4 KiB
C
/*
|
|
* 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_phy2_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_phy2_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_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET);
|
|
udelay(10);
|
|
/* clr reset and clkgate */
|
|
writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + CLR);
|
|
|
|
/* clr all pwd bits => power up phy */
|
|
writel(0xffffffff, MX6_USBPHY2_BASE_ADDR + CLR);
|
|
|
|
/* set utmilvl2/3 */
|
|
val = readl(MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL);
|
|
val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2;
|
|
writel(val, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET);
|
|
|
|
return 0;
|
|
}
|