blob: 924bbb180b86e8f3bcf42426eb9b9f806ba3aabc [file] [log] [blame]
/*
* (C) Copyright 2010
* NVIDIA Corporation <www.nvidia.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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <nand.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-types.h>
#include <asm/arch/nvcommon.h>
#include <asm/arch/nv_hardware_access.h>
#include <asm/arch/nv_drf.h>
#include <asm/arch/tegra2.h>
#ifdef CONFIG_INIT_KERNEL_SHARED_DATA
#include <chromeos/kernel_shared_data.h>
#endif
#include "sdmmc/nvboot_clocks_int.h"
#include "board.h"
#include <asm/arch/gpio.h>
#include "lcd/gpinit/gp-util.h"
/******************************************************************************
* PLL CONFIGURATION & PARAMETERS for different clock generators:
*-----------------------------------------------------------------------------
* Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz
* ----------------------------------------------------------------------------
* PLLU_ENABLE_DLY_COUNT 02 (02h) 03 (03h) 02 (02h) 04 (04h)
* PLLU_STABLE_COUNT 51 (33h) 75 (4Bh) 47 (2Fh) 102 (66h)
* PLL_ACTIVE_DLY_COUNT 05 (05h) 06 (06h) 04 (04h) 09 (09h)
* XTAL_FREQ_COUNT 127 (7Fh) 187 (BBh) 118 (76h) 254 (FEh)
*****************************************************************************/
static const UsbPllDelayParams s_UsbPllDelayParams[NvBootClocksOscFreq_Num] =
{
/* ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT */
{0x02, 0x33, 0x05, 0x7F}, /* For ClocksOscFreq_13, */
{0x03, 0x4B, 0x06, 0xBB}, /* For ClocksOscFreq_19_2*/
{0x02, 0x2F, 0x04, 0x76}, /* For ClocksOscFreq_12 */
{0x04, 0x66, 0x09, 0xFE} /* For ClocksOscFreq_26 */
};
/******************************************************************************
* PLLU configuration information (reference clock is osc/clk_m and PLLU-FOs
* are fixed at 12MHz/60MHz/480MHz).
*
* reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz
* ----------------------------------------------------------------------
* DIVN 960 (3c0h) 200 (0c8h) 960 (3c0h) 960 (3c0h)
* DIVM 13 ( 0dh) 4 ( 04h) 12 ( 0ch) 26 ( 1ah)
* Filter frequency (MHz) 1 4.8 6 2
* CPCON 1100b 0011b 1100b 1100b
* LFCON0 0 0 0 0
*****************************************************************************/
static const UsbPllClockParams s_UsbPllBaseInfo[NvBootClocksOscFreq_Num] =
{
/* DivN, DivM, DivP, CPCON, LFCON */
{0x3C0, 0x0D, 0x00, 0xC, 0}, /* For NvBootClocksOscFreq_13, */
{0x0C8, 0x04, 0x00, 0x3, 0}, /* For NvBootClocksOscFreq_19_2 */
{0x3C0, 0x0C, 0x00, 0xC, 0}, /* For NvBootClocksOscFreq_12 */
{0x3C0, 0x1A, 0x00, 0xC, 0} /* For NvBootClocksOscFreq_26 */
};
/******************************************************************************
* Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and SessEnd.
* Each of these signals have their own debouncer and for each of those one out
* of 2 debouncing times can be chosen (BIAS_DEBOUNCE_A or BIAS_DEBOUNCE_B.)
*
* The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows:
* 0xffff -> No debouncing at all
* <n> ms = <n> *1000 / (1/19.2MHz) / 4
* So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have:
* BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0
* We need to use only DebounceA for BOOTROM. We don’t need the DebounceB
* values, so we can keep those to default.
*****************************************************************************/
static const NvU32 s_UsbBiasDebounceATime[NvBootClocksOscFreq_Num] =
{
/* Ten milli second delay for BIAS_DEBOUNCE_A */
0x7EF4, /* For NvBootClocksOscFreq_13, */
0xBB80, /* For NvBootClocksOscFreq_19_2 */
0x7530, /* For NvBootClocksOscFreq_12 */
0xFDE8 /* For NvBootClocksOscFreq_26 */
};
static const NvU32 s_UsbBiasTrkLengthTime[NvBootClocksOscFreq_Num] =
{
/* 20 micro seconds delay after bias cell operation */
5, /* For NvBootClocksOscFreq_13, */
7, /* For NvBootClocksOscFreq_19_2 */
5, /* For NvBootClocksOscFreq_12 */
9 /* For NvBootClocksOscFreq_26 */
};
/* UTMIP Idle Wait Delay */
static const NvU8 s_UtmipIdleWaitDelay = 17;
/* UTMIP Elastic limit */
static const NvU8 s_UtmipElasticLimit = 16;
/* UTMIP High Speed Sync Start Delay */
static const NvU8 s_UtmipHsSyncStartDelay = 9;
void board_usb_init(void);
void board_spi_init(void);
static void pinmux_init(void)
{
tegra_pinmux_config_table(tegra2_gp_pinmux, tegra2_gp_pinmux_tab_len);
}
/*
* Routine: board_init
* Description: Early hardware init.
*/
int board_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
/* boot param addr */
gd->bd->bi_boot_params = (NV_ADDRESS_MAP_SDRAM_BASE + 0x100);
/* board id for Linux */
gd->bd->bi_arch_number = LINUX_MACH_TYPE;
/*
* do pinmux_init early to make LCD power signals
* keep on low level before LCD power on
*/
pinmux_init();
#ifdef CONFIG_TEGRA2_LCD
gd->fb_base = LCD_FB_ADDR;
#endif
board_spi_init(); /* do this early so UART mux is OK */
board_usb_init();
/* turn off power detects */
writel(0, NV_ADDRESS_MAP_PMC_BASE + APBDEV_PMC_PWR_DET_LATCH_0);
writel(0, NV_ADDRESS_MAP_PMC_BASE + APBDEV_PMC_PWR_DET_0);
return 0;
}
/*
* Routine: misc_init_r
* Description: Configure board specific parts
*/
int misc_init_r(void)
{
#ifdef CONFIG_INIT_KERNEL_SHARED_DATA
initialize_kernel_shared_data();
#endif
return 0;
}
/*
* Routine: timer_init
*
* Description: init the timestamp and lastinc value
*
*/
int timer_init(void)
{
reset_timer();
return 0;
}
/*
* Routine: set_muxconf_regs
* Description: Setting up the configuration Mux registers specific to the
* hardware. Many pins need to be moved from protect to primary
* mode.
*/
void set_muxconf_regs(void)
{
}
/***************************************************************************
* Routines to be provided by corresponding device drivers.
***************************************************************************/
#ifndef CONFIG_TEGRA2_NAND
int board_nand_init(struct nand_chip *nand)
{
return -1;
}
#endif
/***************************************************************************
* Routines for UART initialization.
***************************************************************************/
void
NvBlAvpClockSetDivider(NvBool Enable, NvU32 Dividened, NvU32 Divisor)
{
NvU32 val;
if (Enable)
{
/* Set up divider for SCLK. */
/* SCLK is used for AVP, AHB, and APB. */
val = NV_DRF_DEF(CLK_RST_CONTROLLER, SUPER_SCLK_DIVIDER,
SUPER_SDIV_ENB, ENABLE)
| NV_DRF_NUM(CLK_RST_CONTROLLER, SUPER_SCLK_DIVIDER,
SUPER_SDIV_DIVIDEND, Dividened - 1)
| NV_DRF_NUM(CLK_RST_CONTROLLER, SUPER_SCLK_DIVIDER,
SUPER_SDIV_DIVISOR, Divisor - 1);
NV_CLK_RST_WRITE(SUPER_SCLK_DIVIDER, val);
}
else
{
/* Disable divider for SCLK. */
val = NV_DRF_DEF(CLK_RST_CONTROLLER, SUPER_SCLK_DIVIDER,
SUPER_SDIV_ENB, DISABLE);
NV_CLK_RST_WRITE(SUPER_SCLK_DIVIDER, val);
}
}
static char s_Hex2Char[] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
void NvBlUartClockInit(NvU32 reset_register,
NvU32 reset_mask,
NvU32 reset_enable,
NvU32 reset_disable,
NvU32 clock_register,
NvU32 clock_mask,
NvU32 clock_enable,
NvU32 clock_source_register,
NvU32 clock_source)
{
NvU32 Reg;
// 1. Assert Reset to UART D
Reg = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + reset_register);
Reg = (Reg & ~reset_mask) | reset_enable;
NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + reset_register, Reg);
// 2. Enable clk to UART D
Reg = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + clock_register);
Reg = (Reg & ~clock_mask) | clock_enable;
NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + clock_register, Reg);
// Override pllp setup for 216MHz operation.
Reg = NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_BYPASS, ENABLE)
| NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_ENABLE, DISABLE)
| NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_REF_DIS, REF_ENABLE)
| NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_BASE_OVRRIDE, ENABLE)
| NV_DRF_NUM(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_LOCK, 0x0)
| NV_DRF_NUM(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_DIVP, 0x1)
| NV_DRF_NUM(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_DIVN,
NVRM_PLLP_FIXED_FREQ_KHZ/500)
| NV_DRF_NUM(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_DIVM, 0x0C);
NV_CLK_RST_WRITE(PLLP_BASE, Reg);
Reg = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE,
PLLP_ENABLE, ENABLE, Reg);
NV_CLK_RST_WRITE(PLLP_BASE, Reg);
Reg = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE,
PLLP_BYPASS, DISABLE, Reg);
NV_CLK_RST_WRITE(PLLP_BASE, Reg);
// Enable pllp_out0 to UARTD.
NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + clock_source_register,
clock_source);
// wait for 2us
NvBlAvpStallUs(2);
// De-assert reset to UART D
Reg = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + reset_register);
Reg = (Reg & ~reset_mask) | reset_disable;
NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE + reset_register, Reg);
}
void NvBlUartInitBase(NvU8 * uart_base)
{
NvU32 divisor = (NVRM_PLLP_FIXED_FREQ_KHZ * 1000 /
NV_DEFAULT_DEBUG_BAUD / 16);
// Set up UART parameters.
NV_WRITE08(uart_base + UART_LCR_0, 0x80);
NV_WRITE08(uart_base + UART_THR_DLAB_0_0, divisor);
NV_WRITE08(uart_base + UART_IER_DLAB_0_0, 0x00);
NV_WRITE08(uart_base + UART_LCR_0, 0x00);
NV_WRITE08(uart_base + UART_IIR_FCR_0, 0x37);
NV_WRITE08(uart_base + UART_IER_DLAB_0_0, 0x00);
NV_WRITE08(uart_base + UART_LCR_0, 0x03); /* 8N1 */
NV_WRITE08(uart_base + UART_MCR_0, 0x02);
NV_WRITE08(uart_base + UART_MSR_0, 0x00);
NV_WRITE08(uart_base + UART_SPR_0, 0x00);
NV_WRITE08(uart_base + UART_IRDA_CSR_0, 0x00);
NV_WRITE08(uart_base + UART_ASR_0, 0x00);
NV_WRITE08(uart_base + UART_IIR_FCR_0, 0x31);
// Flush any old characters out of the RX FIFO.
while (NvBlUartRxReady(uart_base))
(void)NvBlUartRx(uart_base);
}
static NV_INLINE NvU32 NvBlUartTxReady(NvU8 const * uart_base)
{
return NV_READ8(uart_base + UART_LSR_0) & UART_LSR_0_THRE_FIELD;
}
NvU32 NvBlUartRxReady(NvU8 const * uart_base)
{
return NV_READ8(uart_base + UART_LSR_0) & UART_LSR_0_RDR_FIELD;
}
static NV_INLINE void NvBlUartTx(NvU8 * uart_base, NvU8 c)
{
NV_WRITE08(uart_base + UART_THR_DLAB_0_0, c);
}
NvU32 NvBlUartRx(NvU8 const * uart_base)
{
return NV_READ8(uart_base + UART_THR_DLAB_0_0);
}
int NvBlUartPoll(void)
{
if (NvBlUartRxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTA_BASE))
return NvBlUartRx((NvU8 *) NV_ADDRESS_MAP_APB_UARTA_BASE);
if (NvBlUartRxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTB_BASE))
return NvBlUartRx((NvU8 *)NV_ADDRESS_MAP_APB_UARTB_BASE);
if (NvBlUartRxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTD_BASE))
return NvBlUartRx((NvU8 *)NV_ADDRESS_MAP_APB_UARTD_BASE);
return -1;
}
int NvBlUartWrite(const void *ptr);
void NvBlPrintf(const char *format, ...);
void uart_post(char c);
static void
NvBlPrintU4(NvU8 byte)
{
uart_post(s_Hex2Char[byte & 0xF]);
}
void
NvBlPrintU8(NvU8 byte)
{
NvBlPrintU4((byte >> 4) & 0xF);
NvBlPrintU4((byte >> 0) & 0xF);
}
void
NvBlPrintU32(NvU32 word)
{
NvBlPrintU8((word >> 24) & 0xFF);
NvBlPrintU8((word >> 16) & 0xFF);
NvBlPrintU8((word >> 8) & 0xFF);
NvBlPrintU8((word >> 0) & 0xFF);
}
void
NvBlVprintf(const char *format, va_list ap)
{
char msg[256];
sprintf(msg, format, ap);
NvBlUartWrite(msg);
}
void
NvBlPrintf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
NvBlVprintf(format, ap);
va_end(ap);
}
void uart_post(char c)
{
#if defined(TEGRA2_TRACE)
#if (CONFIG_TEGRA2_ENABLE_UARTA)
while (!NvBlUartTxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTA_BASE))
;
NvBlUartTx((NvU8 *)NV_ADDRESS_MAP_APB_UARTA_BASE, c);
#endif
#if (CONFIG_TEGRA2_ENABLE_UARTB)
while (!NvBlUartTxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTB_BASE))
;
NvBlUartTx((NvU8 *)NV_ADDRESS_MAP_APB_UARTB_BASE, c);
#endif
#if (CONFIG_TEGRA2_ENABLE_UARTD)
while (!NvBlUartTxReady((NvU8 *)NV_ADDRESS_MAP_APB_UARTD_BASE))
;
NvBlUartTx((NvU8 *)NV_ADDRESS_MAP_APB_UARTD_BASE, c);
#endif
#endif
}
void PostZz(void)
{
uart_post(0x0d);
uart_post(0x0a);
uart_post('Z');
uart_post('z');
NvBlAvpStallUs(2000);
}
void PostYy(void)
{
NvBlAvpStallMs(20);
uart_post(0x0d);
uart_post(0x0a);
uart_post('Y');
uart_post('y');
}
void PostXx(void)
{
NvBlAvpStallMs(20);
uart_post(0x0d);
uart_post(0x0a);
uart_post('X');
uart_post('x');
uart_post(0x0d);
uart_post(0x0a);
}
int
NvBlUartWrite(const void *ptr)
{
const NvU8 *p = ptr;
while (*p)
{
if (*p == '\n') {
uart_post(0x0D);
}
uart_post(*p);
p++;
}
return 0;
}
void debug_trace(int i)
{
uart_post(i+'a');
uart_post('.');
uart_post('.');
}
void usbf_reset_controller(NvU32 UsbBase)
{
int RegVal = 0;
if (UsbBase == NV_ADDRESS_MAP_USB_BASE)
{
/* Enable clock to the USB controller */
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0);
RegVal |= Bit22;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0);
/* Reset the USB controller */
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0);
RegVal |= Bit22;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0);
udelay(2);
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0);
RegVal &= ~Bit22;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0);
udelay(2);
/* Set USB1_NO_LEGACY_MODE to 1, registers are accessible
* under base address
*/
RegVal= readl(UsbBase+USB1_LEGACY_CTRL);
RegVal |= Bit0;
writel(RegVal, UsbBase+USB1_LEGACY_CTRL);
}
else if(UsbBase == NV_ADDRESS_MAP_USB3_BASE)
{
/* Enable clock to the USB3 controller */
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0+4);
RegVal |= Bit27;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0+4);
/* Reset USB3 controller */
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0+4);
RegVal |= Bit27;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0+4);
udelay(2);
RegVal= readl(NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0+4);
RegVal &= ~Bit27;
writel(RegVal, NV_ADDRESS_MAP_CAR_BASE +
CLK_RST_CONTROLLER_RST_DEVICES_L_0+4);
udelay(2);
}
/*
* Assert UTMIP_RESET in USB1/3_IF_USB_SUSP_CTRL register to put
* UTMIP1/3 in reset.
*/
RegVal= readl(UsbBase+USB_SUSP_CTRL);
RegVal |= Bit11;
writel(RegVal, UsbBase+USB_SUSP_CTRL);
if(UsbBase == NV_ADDRESS_MAP_USB3_BASE)
{
/*
* Set USB3 to use UTMIP PHY by setting
* USB3_IF_USB_SUSP_CTRL.UTMIP_PHY_ENB register to 1.
*/
RegVal = readl(UsbBase+USB_SUSP_CTRL);
RegVal |= Bit12;
writel(RegVal, UsbBase+USB_SUSP_CTRL);
}
}
void usb1_set_host_mode(void)
{
int RegVal;
/* Check whether remote host from USB1 is driving VBus */
/* If not driving, we set GPIO USB1_VBus_En */
RegVal= readl(NV_ADDRESS_MAP_USB_BASE+USB_PHY_VBUS_SENSORS_0);
/* driven by remote host. do nothing here */
if (RegVal & Bit26)
return;
/* Seaboard platform uses PAD SLXK (GPIO D.00) as USB1_VBus_En */
/* Config as GPIO */
tg2_gpio_direction_output(3, 0, 1);
/* Z_SLXK = 0, normal, not tristate */
RegVal= readl(NV_ADDRESS_MAP_APB_MISC_BASE +
APB_MISC_PP_TRISTATE_REG_B_0);
RegVal &= ~Bit7;
writel(RegVal, NV_ADDRESS_MAP_APB_MISC_BASE +
APB_MISC_PP_TRISTATE_REG_B_0);
}
void board_usb_init(void)
{
int RegVal;
int i;
NvU32 PlluStableTime =0;
NvBootClocksOscFreq OscFreq;
int UsbBase;
int loop_count;
int PhyClkValid;
/* Get the Oscillator frequency */
OscFreq = NvBootClocksGetOscFreq();
/* Enable PLL U for USB */
NvBootClocksStartPll(NvBootClocksPllId_PllU,
s_UsbPllBaseInfo[OscFreq].M,
s_UsbPllBaseInfo[OscFreq].N,
s_UsbPllBaseInfo[OscFreq].P,
s_UsbPllBaseInfo[OscFreq].CPCON,
s_UsbPllBaseInfo[OscFreq].LFCON,
&PlluStableTime);
/* Initialize USB1 & USB3 controllers */
for (i = 0; i < 2; i++)
{
/* Select the correct base address for the ith controller. */
UsbBase = (i) ? NV_ADDRESS_MAP_USB3_BASE :
NV_ADDRESS_MAP_USB_BASE;
/* Reset the usb controller. */
usbf_reset_controller(UsbBase);
/* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */
RegVal= readl(UsbBase+UTMIP_MISC_CFG1);
RegVal &= ~Bit30;
writel(RegVal, UsbBase+UTMIP_MISC_CFG1);
/* Follow the crystal clock disable by >100ns delay. */
udelay(1);
/*
* To Use the A Session Valid for cable detection logic,
* VBUS_WAKEUP mux must be switched to actually use a_sess_vld
* threshold. This is done by setting VBUS_SENSE_CTL bit in
* USB_LEGACY_CTRL register.
*/
if (UsbBase == NV_ADDRESS_MAP_USB_BASE)
{
RegVal= readl(UsbBase+USB1_LEGACY_CTRL);
RegVal |= (Bit2+Bit1);
writel(RegVal, UsbBase+USB1_LEGACY_CTRL);
}
/* PLL Delay CONFIGURATION settings
* The following parameters control the bring up of the plls:
*/
RegVal= readl(UsbBase+UTMIP_MISC_CFG1);
RegVal &= 0xFFFC003F;
RegVal |= (s_UsbPllDelayParams[OscFreq].StableCount << 6);
RegVal &= 0xFF83FFFF;
RegVal |= (s_UsbPllDelayParams[OscFreq].ActiveDelayCount << 18);
writel(RegVal, UsbBase+UTMIP_MISC_CFG1);
/* Set PLL enable delay count and Crystal frequency count */
RegVal= readl(UsbBase+UTMIP_PLL_CFG1);
RegVal &= 0x08FFFFFF;
RegVal |= (s_UsbPllDelayParams[OscFreq].EnableDelayCount <<27);
RegVal &= 0xFFFFF000;
RegVal |= (s_UsbPllDelayParams[OscFreq].XtalFreqCount);
writel(RegVal, UsbBase+UTMIP_PLL_CFG1);
/* Setting the tracking length time. */
RegVal= readl(UsbBase+UTMIP_BIAS_CFG1);
RegVal &= 0xFFFFFF07;
RegVal |= (s_UsbBiasTrkLengthTime[OscFreq] <<3);
writel(RegVal, UsbBase+UTMIP_BIAS_CFG1);
/* Program Debounce time for VBUS to become valid. */
RegVal= readl(UsbBase+UTMIP_DEBOUNCE_CFG0);
RegVal &= 0xFFFF0000;
RegVal |= s_UsbBiasDebounceATime[OscFreq];
writel(RegVal, UsbBase+UTMIP_DEBOUNCE_CFG0);
/* Set UTMIP_FS_PREAMBLE_J to 1 */
RegVal= readl(UsbBase+UTMIP_TX_CFG0);
RegVal |= Bit19;
writel(RegVal, UsbBase+UTMIP_TX_CFG0);
/* Disable Battery charge enabling bit set to '1' for disable */
RegVal= readl(UsbBase+UTMIP_BAT_CHRG_CFG0);
RegVal |= Bit0;
writel(RegVal, UsbBase+UTMIP_BAT_CHRG_CFG0);
/* Set UTMIP_XCVR_LSBIAS_SEL to 0 */
RegVal= readl(UsbBase+UTMIP_XCVR_CFG0);
RegVal &= ~Bit21;
writel(RegVal, UsbBase+UTMIP_XCVR_CFG0);
/* Set bit 3 of UTMIP_SPARE_CFG0 to 1 */
RegVal= readl(UsbBase+UTMIP_SPARE_CFG0);
RegVal |= Bit3;
writel(RegVal, UsbBase+UTMIP_SPARE_CFG0);
/* Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
* Setting these fields, together with default values of the
* other fields, results in programming the registers below as
* follows:
* UTMIP_HSRX_CFG0 = 0x9168c000
* UTMIP_HSRX_CFG1 = 0x13
*/
/* Set PLL enable delay count and Crystal frequency count */
RegVal= readl(UsbBase+UTMIP_HSRX_CFG0);
RegVal &= 0xFFF07FFF;
RegVal |= s_UtmipIdleWaitDelay << 15;
RegVal &= 0xFFFF83FF;
RegVal |= s_UtmipElasticLimit << 10;
writel(RegVal, UsbBase+UTMIP_HSRX_CFG0);
/* Configure the UTMIP_HS_SYNC_START_DLY */
RegVal= readl(UsbBase+UTMIP_HSRX_CFG1);
RegVal &= 0xFFFFFFC1;
RegVal |= s_UtmipHsSyncStartDelay << 1;
writel(RegVal, UsbBase+UTMIP_HSRX_CFG1);
/* Preceed the crystal clock disable by >100ns delay. */
udelay(1);
/* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN
*/
RegVal= readl(UsbBase+UTMIP_MISC_CFG1);
RegVal |= Bit30;
writel(RegVal, UsbBase+UTMIP_MISC_CFG1);
/* Finished the per-controller init. */
/* De-assert UTMIP_RESET to bring out of reset. */
RegVal= readl(UsbBase+USB_SUSP_CTRL);
RegVal &= ~Bit11;
writel(RegVal, UsbBase+USB_SUSP_CTRL);
loop_count = 100000;
while (loop_count)
{
/* Wait for the phy clock to become valid in 100 ms */
PhyClkValid = readl(UsbBase+USB_SUSP_CTRL) & Bit7;
if (PhyClkValid)
break;
udelay(1);
loop_count--;
} /* while */
} /* for */
/* Disable by writing IC_ENB1 in USB2_CONTROLLER_2_USB2D_ICUSB_CTRL_0.*/
RegVal= readl(NV_ADDRESS_MAP_USB3_BASE+ICUSB_CTRL);
RegVal &= ~Bit3;
writel(RegVal, NV_ADDRESS_MAP_USB3_BASE+ICUSB_CTRL);
/* Setting STS field to 0 and PTS field to 0 */
RegVal= readl(NV_ADDRESS_MAP_USB3_BASE+PORTSC1);
RegVal &= ~(Bit31+Bit30+Bit29);
writel(RegVal, NV_ADDRESS_MAP_USB3_BASE+PORTSC1);
/* Deassert power down state for USB3 */
RegVal= readl(NV_ADDRESS_MAP_USB3_BASE+UTMIP_XCVR_CFG0);
RegVal &= ~(Bit18+Bit16+Bit14);
writel(RegVal, NV_ADDRESS_MAP_USB3_BASE+UTMIP_XCVR_CFG0);
RegVal= readl(NV_ADDRESS_MAP_USB3_BASE+UTMIP_XCVR_CFG1);
RegVal &= ~(Bit4+Bit2+Bit0);
writel(RegVal, NV_ADDRESS_MAP_USB3_BASE+UTMIP_XCVR_CFG1);
#if ((LINUX_MACH_TYPE == MACH_TYPE_SEABOARD) || \
(LINUX_MACH_TYPE == MACH_TYPE_KAEN) || \
(LINUX_MACH_TYPE == MACH_TYPE_AEBL) || \
(LINUX_MACH_TYPE == MACH_TYPE_ARTHUR))
usb1_set_host_mode();
#endif
}