| /* |
| * (C) Copyright 2010 |
| * Marvell Semiconductor <www.marvell.com> |
| * Written-by: Qingchao Qiu <qcqiu@marvell.com> |
| * |
| * See file CREDITS for list of people who contributed to this |
| * project. |
| * |
| * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, |
| * MA 02110-1301 USA |
| */ |
| #include <common.h> |
| #include "usb.h" |
| #include "ehci.h" |
| #include "ehci-core.h" |
| #include "apb_perf_base.h" |
| #include <io.h> |
| #include <global.h> |
| #include "gpio.h" |
| #include "bcm_primitive.h" |
| #include "timer.h" |
| #include "bcm_mailbox.h" |
| |
| #define USB_PHY_REG_BASE_USB0 0xF7B74000 |
| #define USB_PHY_REG_BASE_USB1 0xF7B78000 |
| #define USB_PHY_PLL_REG 0x04 |
| #define USB_PHY_PLL_CONTROL_REG 0x08 |
| #define USB_PHY_ANALOG_REG 0x34 |
| #define USB_PHY_RX_CTRL_REG 0x20 |
| #define USB_PLL_READY (1<<15) |
| #define USBMODE_OFFSET 0x1a8 |
| #define USBMODE_CM_HOST 3 |
| #define MV_SBUSCFG 0x90 |
| |
| #define USB2_OTG_REG0 52 |
| #define USB2_CHARGER_REG0 56 |
| #define USB2_PLL_REG0 0 |
| #define USB2_PLL_REG1 4 |
| #define USB2_CAL_CTRL 8 |
| #define USB2_DIG_REG0 28 |
| #define USB2_TX_CH_CTRL0 12 |
| |
| int berlin_cdp_reinit_phy(u32 base) |
| { |
| u32 data, timeout; |
| |
| /* powering up OTG */ |
| data = ehci_readl( base + USB2_OTG_REG0); |
| data |= 1<<4; |
| ehci_writel((base + USB2_OTG_REG0), data); |
| |
| /* powering Charger detector circuit */ |
| data = ehci_readl( base + USB2_CHARGER_REG0); |
| data |= 1<<5; |
| ehci_writel((base + USB2_CHARGER_REG0), data); |
| |
| /* Power up analog port */ |
| data = ehci_readl( base + USB2_TX_CH_CTRL0); |
| data |= 1<<24; |
| ehci_writel((base + USB2_TX_CH_CTRL0), 0x03BE7F6F); |
| |
| // Squelch setting |
| data = 0xC39F16CE; |
| ehci_writel((base + USB2_DIG_REG0), data); |
| |
| // Impedance calibration |
| data = 0xf5930488; |
| ehci_writel((base + USB2_CAL_CTRL), data); |
| |
| /* Configuring FBDIV for SOC Clk 25 Mhz */ |
| data = ehci_readl( base + USB2_PLL_REG0); |
| data &= 0xce00ff80; |
| data |= 5 | (0x60<<16) | (0<<28); |
| ehci_writel((base + USB2_PLL_REG0), data); |
| |
| /* Power up PLL, Reset, Suspen_en disable */ |
| ehci_writel((base + USB2_PLL_REG1), 0x407); |
| udelay(100); |
| |
| /* Deassert Reset */ |
| ehci_writel((base + USB2_PLL_REG1), 0x403); |
| |
| /* Wait for PLL Lock */ |
| timeout = 0x1000000; |
| do { |
| data = ehci_readl( base + USB2_PLL_REG0); |
| if (!--timeout) |
| break; |
| } while ( !(data&0x80000000)); |
| |
| if (!timeout) { |
| debug("ERROR: USB PHY PLL NOT LOCKED!\n"); |
| } |
| |
| return 0; |
| } |
| |
| |
| /* |
| * Create the appropriate control structures to manage |
| * a new EHCI host controller. |
| */ |
| int ehci_hcd_init(void) |
| { |
| u32 base_addr; |
| /* Deinit USB device inside BCM before using USB on ARM side */ |
| bcm_usb_console_func(EROM_TURN_OFF_USB_DEVICE); |
| berlin_cdp_reinit_phy(USB_PHY_REG_BASE_USB0); |
| base_addr = MEMMAP_USB0_REG_BASE; |
| /* set USBMODE to host mode */ |
| ehci_writel(base_addr + USBMODE_OFFSET, USBMODE_CM_HOST); |
| ehci_writel(base_addr + MV_SBUSCFG, 0x07); |
| |
| hccr = (struct ehci_hccr *)(base_addr + 0x100); |
| hcor = (struct ehci_hcor *)((u32) hccr |
| + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); |
| |
| debug("Berlin-ehci: init hccr %x and hcor %x hc_length %d\n", |
| (u32)hccr, (u32)hcor, |
| (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); |
| |
| return 0; |
| } |
| |
| /* |
| * Destroy the appropriate control structures corresponding |
| * the the EHCI host controller. |
| */ |
| int ehci_hcd_stop(void) |
| { |
| return 0; |
| } |