Tegra30 and Tegra114 are compatible except 1. T30 takes 55 ms to finish Port Reset. T114 takes 50 ms. 2. PLL parameters
Tested on Tegra20 Harmony/Seaboard, Tegra30 Cardhu, and Tegra114 Dalmore platforms. All works well. Signed-off-by: Jim Lin <ji...@nvidia.com> --- arch/arm/include/asm/arch-tegra/clk_rst.h | 10 + arch/arm/include/asm/arch-tegra/usb.h | 249 ------------------ arch/arm/include/asm/arch-tegra114/tegra.h | 1 + arch/arm/include/asm/arch-tegra114/usb.h | 287 +++++++++++++++++++++ arch/arm/include/asm/arch-tegra20/usb.h | 279 +++++++++++++++++++++ arch/arm/include/asm/arch-tegra30/usb.h | 294 ++++++++++++++++++++++ board/nvidia/common/board.c | 2 +- drivers/usb/host/ehci-hcd.c | 40 ++- drivers/usb/host/ehci-tegra.c | 376 ++++++++++++++++++++------- 9 files changed, 1178 insertions(+), 360 deletions(-) delete mode 100644 arch/arm/include/asm/arch-tegra/usb.h create mode 100644 arch/arm/include/asm/arch-tegra114/usb.h create mode 100644 arch/arm/include/asm/arch-tegra20/usb.h create mode 100644 arch/arm/include/asm/arch-tegra30/usb.h diff --git a/arch/arm/include/asm/arch-tegra/clk_rst.h b/arch/arm/include/asm/arch-tegra/clk_rst.h index c754ec7..9b8de9c 100644 --- a/arch/arm/include/asm/arch-tegra/clk_rst.h +++ b/arch/arm/include/asm/arch-tegra/clk_rst.h @@ -225,6 +225,16 @@ enum { IN_408_OUT_9_6_DIVISOR = 83, }; +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 */ +#define PLLU_POWERDOWN (1 << 16) +#define PLL_ENABLE_POWERDOWN (1 << 14) +#define PLL_ACTIVE_POWERDOWN (1 << 12) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG2_0 */ +#define UTMIP_FORCE_PD_SAMP_C_POWERDOWN (1 << 4) +#define UTMIP_FORCE_PD_SAMP_B_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PD_SAMP_A_POWERDOWN (1 << 0) + /* CLK_RST_CONTROLLER_OSC_CTRL_0 */ #define OSC_XOBP_SHIFT 1 #define OSC_XOBP_MASK (1U << OSC_XOBP_SHIFT) diff --git a/arch/arm/include/asm/arch-tegra/usb.h b/arch/arm/include/asm/arch-tegra/usb.h deleted file mode 100644 index ef6c089..0000000 --- a/arch/arm/include/asm/arch-tegra/usb.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * 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 - */ - -#ifndef _TEGRA_USB_H_ -#define _TEGRA_USB_H_ - - -/* USB Controller (USBx_CONTROLLER_) regs */ -struct usb_ctlr { - /* 0x000 */ - uint id; - uint reserved0; - uint host; - uint device; - - /* 0x010 */ - uint txbuf; - uint rxbuf; - uint reserved1[2]; - - /* 0x020 */ - uint reserved2[56]; - - /* 0x100 */ - u16 cap_length; - u16 hci_version; - uint hcs_params; - uint hcc_params; - uint reserved3[5]; - - /* 0x120 */ - uint dci_version; - uint dcc_params; - uint reserved4[6]; - - /* 0x140 */ - uint usb_cmd; - uint usb_sts; - uint usb_intr; - uint frindex; - - /* 0x150 */ - uint reserved5; - uint periodic_list_base; - uint async_list_addr; - uint async_tt_sts; - - /* 0x160 */ - uint burst_size; - uint tx_fill_tuning; - uint reserved6; /* is this port_sc1 on some controllers? */ - uint icusb_ctrl; - - /* 0x170 */ - uint ulpi_viewport; - uint reserved7; - uint endpt_nak; - uint endpt_nak_enable; - - /* 0x180 */ - uint reserved; - uint port_sc1; - uint reserved8[6]; - - /* 0x1a0 */ - uint reserved9; - uint otgsc; - uint usb_mode; - uint endpt_setup_stat; - - /* 0x1b0 */ - uint reserved10[20]; - - /* 0x200 */ - uint reserved11[0x80]; - - /* 0x400 */ - uint susp_ctrl; - uint phy_vbus_sensors; - uint phy_vbus_wakeup_id; - uint phy_alt_vbus_sys; - - /* 0x410 */ - uint usb1_legacy_ctrl; - uint reserved12[4]; - - /* 0x424 */ - uint ulpi_timing_ctrl_0; - uint ulpi_timing_ctrl_1; - uint reserved13[53]; - - /* 0x500 */ - uint reserved14[64 * 3]; - - /* 0x800 */ - uint utmip_pll_cfg0; - uint utmip_pll_cfg1; - uint utmip_xcvr_cfg0; - uint utmip_bias_cfg0; - - /* 0x810 */ - uint utmip_hsrx_cfg0; - uint utmip_hsrx_cfg1; - uint utmip_fslsrx_cfg0; - uint utmip_fslsrx_cfg1; - - /* 0x820 */ - uint utmip_tx_cfg0; - uint utmip_misc_cfg0; - uint utmip_misc_cfg1; - uint utmip_debounce_cfg0; - - /* 0x830 */ - uint utmip_bat_chrg_cfg0; - uint utmip_spare_cfg0; - uint utmip_xcvr_cfg1; - uint utmip_bias_cfg1; -}; - - -/* USB1_LEGACY_CTRL */ -#define USB1_NO_LEGACY_MODE 1 - -#define VBUS_SENSE_CTL_SHIFT 1 -#define VBUS_SENSE_CTL_MASK (3 << VBUS_SENSE_CTL_SHIFT) -#define VBUS_SENSE_CTL_VBUS_WAKEUP 0 -#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP 1 -#define VBUS_SENSE_CTL_AB_SESS_VLD 2 -#define VBUS_SENSE_CTL_A_SESS_VLD 3 - -/* USB2_IF_ULPI_TIMING_CTRL_0 */ -#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) -#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) - -/* USB2_IF_ULPI_TIMING_CTRL_1 */ -#define ULPI_DATA_TRIMMER_LOAD (1 << 0) -#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) -#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) -#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) -#define ULPI_DIR_TRIMMER_LOAD (1 << 24) -#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) - -/* USBx_IF_USB_SUSP_CTRL_0 */ -#define ULPI_PHY_ENB (1 << 13) -#define UTMIP_PHY_ENB (1 << 12) -#define UTMIP_RESET (1 << 11) -#define USB_PHY_CLK_VALID (1 << 7) -#define USB_SUSP_CLR (1 << 5) - -/* USBx_UTMIP_MISC_CFG1 */ -#define UTMIP_PLLU_STABLE_COUNT_SHIFT 6 -#define UTMIP_PLLU_STABLE_COUNT_MASK \ - (0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT) -#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT 18 -#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK \ - (0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT) -#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30) - -/* USBx_UTMIP_PLL_CFG1_0 */ -#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT 27 -#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK \ - (0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT) -#define UTMIP_XTAL_FREQ_COUNT_SHIFT 0 -#define UTMIP_XTAL_FREQ_COUNT_MASK 0xfff - -/* USBx_UTMIP_BIAS_CFG1_0 */ -#define UTMIP_BIAS_PDTRK_COUNT_SHIFT 3 -#define UTMIP_BIAS_PDTRK_COUNT_MASK \ - (0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT) - -#define UTMIP_DEBOUNCE_CFG0_SHIFT 0 -#define UTMIP_DEBOUNCE_CFG0_MASK 0xffff - -/* USBx_UTMIP_TX_CFG0_0 */ -#define UTMIP_FS_PREAMBLE_J (1 << 19) - -/* USBx_UTMIP_BAT_CHRG_CFG0_0 */ -#define UTMIP_PD_CHRG 1 - -/* USBx_UTMIP_XCVR_CFG0_0 */ -#define UTMIP_XCVR_LSBIAS_SE (1 << 21) - -/* USBx_UTMIP_SPARE_CFG0_0 */ -#define FUSE_SETUP_SEL (1 << 3) - -/* USBx_UTMIP_HSRX_CFG0_0 */ -#define UTMIP_IDLE_WAIT_SHIFT 15 -#define UTMIP_IDLE_WAIT_MASK (0x1f << UTMIP_IDLE_WAIT_SHIFT) -#define UTMIP_ELASTIC_LIMIT_SHIFT 10 -#define UTMIP_ELASTIC_LIMIT_MASK \ - (0x1f << UTMIP_ELASTIC_LIMIT_SHIFT) - -/* USBx_UTMIP_HSRX_CFG0_1 */ -#define UTMIP_HS_SYNC_START_DLY_SHIFT 1 -#define UTMIP_HS_SYNC_START_DLY_MASK \ - (0xf << UTMIP_HS_SYNC_START_DLY_SHIFT) - -/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */ -#define IC_ENB1 (1 << 3) - -/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */ -#define PTS_SHIFT 30 -#define PTS_MASK (3U << PTS_SHIFT) -#define PTS_UTMI 0 -#define PTS_RESERVED 1 -#define PTS_ULPI 2 -#define PTS_ICUSB_SER 3 - -#define STS (1 << 29) -#define WKOC (1 << 22) -#define WKDS (1 << 21) -#define WKCN (1 << 20) - -/* USBx_UTMIP_XCVR_CFG0_0 */ -#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) -#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) -#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) - -/* USBx_UTMIP_XCVR_CFG1_0 */ -#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) -#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) -#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) - -/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */ -#define VBUS_VLD_STS (1 << 26) - - -/* Setup USB on the board */ -int board_usb_init(const void *blob); - -#endif /* _TEGRA_USB_H_ */ diff --git a/arch/arm/include/asm/arch-tegra114/tegra.h b/arch/arm/include/asm/arch-tegra114/tegra.h index 5d426b5..893d229 100644 --- a/arch/arm/include/asm/arch-tegra114/tegra.h +++ b/arch/arm/include/asm/arch-tegra114/tegra.h @@ -30,5 +30,6 @@ #define NVBOOTINFOTABLE_BCTPTR 0x4C /* BCT pointer in BIT in IRAM */ #define MAX_NUM_CPU 4 +#define TEGRA_USB1_BASE 0x7D000000 #endif /* TEGRA114_H */ diff --git a/arch/arm/include/asm/arch-tegra114/usb.h b/arch/arm/include/asm/arch-tegra114/usb.h new file mode 100644 index 0000000..c3ca5fa --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/usb.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2013 NVIDIA Corporation + * 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 + */ + +#ifndef _TEGRA_USB_H_ +#define _TEGRA_USB_H_ + + +/* USB Controller (USBx_CONTROLLER_) regs */ +struct usb_ctlr { + /* 0x000 */ + uint id; + uint reserved0; + uint host; + uint device; + + /* 0x010 */ + uint txbuf; + uint rxbuf; + uint reserved1[2]; + + /* 0x020 */ + uint reserved2[56]; + + /* 0x100 */ + u16 cap_length; + u16 hci_version; + uint hcs_params; + uint hcc_params; + uint reserved3[5]; + + /* 0x120 */ + uint dci_version; + uint dcc_params; + uint reserved4[2]; + + /* 0x130 */ + uint usb_cmd; + uint usb_sts; + uint usb_intr; + uint frindex; + + /* 0x140 */ + uint reserved5; + uint periodic_list_base; + uint async_list_addr; + uint reserved5_1; + + /* 0x150 */ + uint burst_size; + uint tx_fill_tuning; + uint reserved6; + uint icusb_ctrl; + + /* 0x160 */ + uint ulpi_viewport; + uint reserved7; + uint reserved7_0; + uint reserved7_1; + + /* 0x170 */ + uint reserved; + uint port_sc1; + uint reserved8[6]; + + /* 0x190 */ + uint reserved9[8]; + + /* 0x1b0 */ + uint reserved10; + uint hostpc1_devlc; + uint reserved10_1[2]; + + /* 0x1c0 */ + uint reserved10_2[4]; + + /* 0x1d0 */ + uint reserved10_3[4]; + + /* 0x1e0 */ + uint reserved10_4[4]; + + /* 0x1f0 */ + uint reserved10_5; + uint otgsc; + uint usb_mode; + uint reserved10_6; + + /* 0x200 */ + uint endpt_nak; + uint endpt_nak_enable; + uint endpt_setup_stat; + uint reserved11_1[0x7D]; + + /* 0x400 */ + uint susp_ctrl; + uint phy_vbus_sensors; + uint phy_vbus_wakeup_id; + uint phy_alt_vbus_sys; + + /* 0x410 */ + uint usb1_legacy_ctrl; + uint reserved12[3]; + + /* 0x420 */ + uint reserved13[56]; + + /* 0x500 */ + uint reserved14[64 * 3]; + + /* 0x800 */ + uint utmip_pll_cfg0; + uint utmip_pll_cfg1; + uint utmip_xcvr_cfg0; + uint utmip_bias_cfg0; + + /* 0x810 */ + uint utmip_hsrx_cfg0; + uint utmip_hsrx_cfg1; + uint utmip_fslsrx_cfg0; + uint utmip_fslsrx_cfg1; + + /* 0x820 */ + uint utmip_tx_cfg0; + uint utmip_misc_cfg0; + uint utmip_misc_cfg1; + uint utmip_debounce_cfg0; + + /* 0x830 */ + uint utmip_bat_chrg_cfg0; + uint utmip_spare_cfg0; + uint utmip_xcvr_cfg1; + uint utmip_bias_cfg1; +}; + +/* USB1_LEGACY_CTRL */ +#define USB1_NO_LEGACY_MODE 1 + +#define VBUS_SENSE_CTL_SHIFT 1 +#define VBUS_SENSE_CTL_MASK (3 << VBUS_SENSE_CTL_SHIFT) +#define VBUS_SENSE_CTL_VBUS_WAKEUP 0 +#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP 1 +#define VBUS_SENSE_CTL_AB_SESS_VLD 2 +#define VBUS_SENSE_CTL_A_SESS_VLD 3 + +/* USBx_IF_USB_SUSP_CTRL_0 */ +#define UTMIP_PHY_ENB (1 << 12) +#define UTMIP_RESET (1 << 11) +#define USB_PHY_CLK_VALID (1 << 7) +#define USB_SUSP_CLR (1 << 5) + +/* USBx_UTMIP_MISC_CFG0 */ +#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) + +/* USBx_UTMIP_MISC_CFG1 */ +#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30) + +/* Moved to Clock and Reset register space */ +#define UTMIP_PLLU_STABLE_COUNT_SHIFT 6 +#define UTMIP_PLLU_STABLE_COUNT_MASK \ + (0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT) +/* Moved to Clock and Reset register space */ +#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT 18 +#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK \ + (0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT) + +/* USBx_UTMIP_PLL_CFG1_0 */ +/* Moved to Clock and Reset register space */ +#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT 27 +#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK \ + (0x1f << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT) +#define UTMIP_XTAL_FREQ_COUNT_SHIFT 0 +#define UTMIP_XTAL_FREQ_COUNT_MASK 0xfff + +/* USBx_UTMIP_BIAS_CFG0_0 */ +#define UTMIP_HSDISCON_LEVEL_MSB (1 << 24) +#define UTMIP_OTGPD (1 << 11) +#define UTMIP_BIASPD (1 << 10) +#define UTMIP_HSDISCON_LEVEL_SHIFT 2 +#define UTMIP_HSDISCON_LEVEL_MASK \ + (0x3 << UTMIP_HSDISCON_LEVEL_SHIFT) +#define UTMIP_HSSQUELCH_LEVEL_SHIFT 0 +#define UTMIP_HSSQUELCH_LEVEL_MASK \ + (0x3 << UTMIP_HSSQUELCH_LEVEL_SHIFT) + +/* USBx_UTMIP_BIAS_CFG1_0 */ +#define UTMIP_FORCE_PDTRK_POWERDOWN 1 +#define UTMIP_BIAS_PDTRK_COUNT_SHIFT 3 +#define UTMIP_BIAS_PDTRK_COUNT_MASK \ + (0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT) + +/* USBx_UTMIP_DEBOUNCE_CFG0_0 */ +#define UTMIP_DEBOUNCE_CFG0_SHIFT 0 +#define UTMIP_DEBOUNCE_CFG0_MASK 0xffff + +/* USBx_UTMIP_TX_CFG0_0 */ +#define UTMIP_FS_PREAMBLE_J (1 << 19) + +/* USBx_UTMIP_BAT_CHRG_CFG0_0 */ +#define UTMIP_PD_CHRG 1 + +/* USBx_UTMIP_SPARE_CFG0_0 */ +#define FUSE_SETUP_SEL (1 << 3) + +/* USBx_UTMIP_HSRX_CFG0_0 */ +#define UTMIP_IDLE_WAIT_SHIFT 15 +#define UTMIP_IDLE_WAIT_MASK (0x1f << UTMIP_IDLE_WAIT_SHIFT) +#define UTMIP_ELASTIC_LIMIT_SHIFT 10 +#define UTMIP_ELASTIC_LIMIT_MASK \ + (0x1f << UTMIP_ELASTIC_LIMIT_SHIFT) + +/* USBx_UTMIP_HSRX_CFG0_1 */ +#define UTMIP_HS_SYNC_START_DLY_SHIFT 1 +#define UTMIP_HS_SYNC_START_DLY_MASK \ + (0x1f << UTMIP_HS_SYNC_START_DLY_SHIFT) + +/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */ +#define IC_ENB1 (1 << 3) + +/* PORTSC1, USB1, defined for Tegra20 to avoid compiling error */ +#define PTS1_SHIFT 31 +#define PTS1_MASK (1 << PTS1_SHIFT) +#define STS1 (1 << 30) + +/* USB2D_HOSTPC1_DEVLC_0 */ +#define PTS_SHIFT 29 +#define PTS_MASK (0x7U << PTS_SHIFT) +#define PTS_UTMI 0 +#define PTS_RESERVED 1 +#define PTS_ULPI 2 +#define PTS_ICUSB_SER 3 +#define PTS_HSIC 4 + +#define STS (1 << 28) + +/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */ +#define WKOC (1 << 22) +#define WKDS (1 << 21) +#define WKCN (1 << 20) + +/* USBx_UTMIP_XCVR_CFG0_0 */ +#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) +#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) +#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) +#define UTMIP_XCVR_LSBIAS_SE (1 << 21) +#define UTMIP_XCVR_HSSLEW_MSB_SHIFT 25 +#define UTMIP_XCVR_HSSLEW_MSB_MASK \ + (0x7f << UTMIP_XCVR_HSSLEW_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_MSB_SHIFT 22 +#define UTMIP_XCVR_SETUP_MSB_MASK (0x7 << UTMIP_XCVR_SETUP_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_SHIFT 0 +#define UTMIP_XCVR_SETUP_MASK (0xf << UTMIP_XCVR_SETUP_SHIFT) + +/* USBx_UTMIP_XCVR_CFG1_0 */ +#define UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT 18 +#define UTMIP_XCVR_TERM_RANGE_ADJ_MASK \ + (0xf << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT) +#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) +#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) + +/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */ +#define VBUS_VLD_STS (1 << 26) + + +/* Setup USB on the board */ +int board_usb_init(const void *blob); + +#endif /* _TEGRA_USB_H_ */ diff --git a/arch/arm/include/asm/arch-tegra20/usb.h b/arch/arm/include/asm/arch-tegra20/usb.h new file mode 100644 index 0000000..415c0f6 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra20/usb.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2013 NVIDIA Corporation + * 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 + */ + +#ifndef _TEGRA_USB_H_ +#define _TEGRA_USB_H_ + + +/* USB Controller (USBx_CONTROLLER_) regs */ +struct usb_ctlr { + /* 0x000 */ + uint id; + uint reserved0; + uint host; + uint device; + + /* 0x010 */ + uint txbuf; + uint rxbuf; + uint reserved1[2]; + + /* 0x020 */ + uint reserved2[56]; + + /* 0x100 */ + u16 cap_length; + u16 hci_version; + uint hcs_params; + uint hcc_params; + uint reserved3[5]; + + /* 0x120 */ + uint dci_version; + uint dcc_params; + uint reserved4[6]; + + /* 0x140 */ + uint usb_cmd; + uint usb_sts; + uint usb_intr; + uint frindex; + + /* 0x150 */ + uint reserved5; + uint periodic_list_base; + uint async_list_addr; + uint async_tt_sts; + + /* 0x160 */ + uint burst_size; + uint tx_fill_tuning; + uint reserved6; /* is this port_sc1 on some controllers? */ + uint icusb_ctrl; + + /* 0x170 */ + uint ulpi_viewport; + uint reserved7; + uint endpt_nak; + uint endpt_nak_enable; + + /* 0x180 */ + uint reserved; + uint port_sc1; + uint reserved8[6]; + + /* 0x1a0 */ + uint reserved9; + uint otgsc; + uint usb_mode; + uint endpt_setup_stat; + + /* 0x1b0 */ + uint reserved10[20]; + + /* 0x200 */ + uint reserved11[0x80]; + + /* 0x400 */ + uint susp_ctrl; + uint phy_vbus_sensors; + uint phy_vbus_wakeup_id; + uint phy_alt_vbus_sys; + + /* 0x410 */ + uint usb1_legacy_ctrl; + uint reserved12[4]; + + /* 0x424 */ + uint ulpi_timing_ctrl_0; + uint ulpi_timing_ctrl_1; + uint reserved13[53]; + + /* 0x500 */ + uint reserved14[64 * 3]; + + /* 0x800 */ + uint utmip_pll_cfg0; + uint utmip_pll_cfg1; + uint utmip_xcvr_cfg0; + uint utmip_bias_cfg0; + + /* 0x810 */ + uint utmip_hsrx_cfg0; + uint utmip_hsrx_cfg1; + uint utmip_fslsrx_cfg0; + uint utmip_fslsrx_cfg1; + + /* 0x820 */ + uint utmip_tx_cfg0; + uint utmip_misc_cfg0; + uint utmip_misc_cfg1; + uint utmip_debounce_cfg0; + + /* 0x830 */ + uint utmip_bat_chrg_cfg0; + uint utmip_spare_cfg0; + uint utmip_xcvr_cfg1; + uint utmip_bias_cfg1; +}; + + +/* USB1_LEGACY_CTRL */ +#define USB1_NO_LEGACY_MODE 1 + +#define VBUS_SENSE_CTL_SHIFT 1 +#define VBUS_SENSE_CTL_MASK (3 << VBUS_SENSE_CTL_SHIFT) +#define VBUS_SENSE_CTL_VBUS_WAKEUP 0 +#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP 1 +#define VBUS_SENSE_CTL_AB_SESS_VLD 2 +#define VBUS_SENSE_CTL_A_SESS_VLD 3 + +/* USB2_IF_ULPI_TIMING_CTRL_0 */ +#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) +#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) + +/* USB2_IF_ULPI_TIMING_CTRL_1 */ +#define ULPI_DATA_TRIMMER_LOAD (1 << 0) +#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) +#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) +#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) +#define ULPI_DIR_TRIMMER_LOAD (1 << 24) +#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) + +/* USBx_IF_USB_SUSP_CTRL_0 */ +#define ULPI_PHY_ENB (1 << 13) +#define UTMIP_PHY_ENB (1 << 12) +#define UTMIP_RESET (1 << 11) +#define USB_PHY_CLK_VALID (1 << 7) +#define USB_SUSP_CLR (1 << 5) + +/* USBx_UTMIP_MISC_CFG0 */ +#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) + +/* USBx_UTMIP_MISC_CFG1 */ +#define UTMIP_PLLU_STABLE_COUNT_SHIFT 6 +#define UTMIP_PLLU_STABLE_COUNT_MASK \ + (0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT) +#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT 18 +#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK \ + (0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT) +#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30) + +/* USBx_UTMIP_PLL_CFG1_0 */ +#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT 27 +#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK \ + (0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT) +#define UTMIP_XTAL_FREQ_COUNT_SHIFT 0 +#define UTMIP_XTAL_FREQ_COUNT_MASK 0xfff + +/* USBx_UTMIP_BIAS_CFG0_0 */ +#define UTMIP_HSDISCON_LEVEL_MSB (1 << 24) +#define UTMIP_OTGPD (1 << 11) +#define UTMIP_BIASPD (1 << 10) +#define UTMIP_HSDISCON_LEVEL_SHIFT 2 +#define UTMIP_HSDISCON_LEVEL_MASK \ + (0x3 << UTMIP_HSDISCON_LEVEL_SHIFT) +#define UTMIP_HSSQUELCH_LEVEL_SHIFT 0 +#define UTMIP_HSSQUELCH_LEVEL_MASK \ + (0x3 << UTMIP_HSSQUELCH_LEVEL_SHIFT) + +/* USBx_UTMIP_BIAS_CFG1_0 */ +#define UTMIP_FORCE_PDTRK_POWERDOWN 1 +#define UTMIP_BIAS_PDTRK_COUNT_SHIFT 3 +#define UTMIP_BIAS_PDTRK_COUNT_MASK \ + (0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT) + +#define UTMIP_DEBOUNCE_CFG0_SHIFT 0 +#define UTMIP_DEBOUNCE_CFG0_MASK 0xffff + +/* USBx_UTMIP_TX_CFG0_0 */ +#define UTMIP_FS_PREAMBLE_J (1 << 19) + +/* USBx_UTMIP_BAT_CHRG_CFG0_0 */ +#define UTMIP_PD_CHRG 1 + +/* USBx_UTMIP_SPARE_CFG0_0 */ +#define FUSE_SETUP_SEL (1 << 3) + +/* USBx_UTMIP_HSRX_CFG0_0 */ +#define UTMIP_IDLE_WAIT_SHIFT 15 +#define UTMIP_IDLE_WAIT_MASK (0x1f << UTMIP_IDLE_WAIT_SHIFT) +#define UTMIP_ELASTIC_LIMIT_SHIFT 10 +#define UTMIP_ELASTIC_LIMIT_MASK \ + (0x1f << UTMIP_ELASTIC_LIMIT_SHIFT) + +/* USBx_UTMIP_HSRX_CFG0_1 */ +#define UTMIP_HS_SYNC_START_DLY_SHIFT 1 +#define UTMIP_HS_SYNC_START_DLY_MASK \ + (0xf << UTMIP_HS_SYNC_START_DLY_SHIFT) + +/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */ +#define IC_ENB1 (1 << 3) + +/* PORTSC1, USB1 */ +#define PTS1_SHIFT 31 +#define PTS1_MASK (1 << PTS1_SHIFT) +#define STS1 (1 << 30) + +/* PORTSC, USB2, USB3 */ +#define PTS_SHIFT 30 +#define PTS_MASK (3U << PTS_SHIFT) +#define PTS_UTMI 0 +#define PTS_RESERVED 1 +#define PTS_ULPI 2 +#define PTS_ICUSB_SER 3 + +#define STS (1 << 29) +#define WKOC (1 << 22) +#define WKDS (1 << 21) +#define WKCN (1 << 20) + +/* USBx_UTMIP_XCVR_CFG0_0 */ +#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) +#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) +#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) +#define UTMIP_XCVR_LSBIAS_SE (1 << 21) +#define UTMIP_XCVR_HSSLEW_MSB_SHIFT 25 +#define UTMIP_XCVR_HSSLEW_MSB_MASK \ + (0x7f << UTMIP_XCVR_HSSLEW_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_MSB_SHIFT 22 +#define UTMIP_XCVR_SETUP_MSB_MASK (0x7 << UTMIP_XCVR_SETUP_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_SHIFT 0 +#define UTMIP_XCVR_SETUP_MASK (0xf << UTMIP_XCVR_SETUP_SHIFT) + + +/* USBx_UTMIP_XCVR_CFG1_0 */ +#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) +#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) +#define UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT 18 +#define UTMIP_XCVR_TERM_RANGE_ADJ_MASK \ + (0xf << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT) + +/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */ +#define VBUS_VLD_STS (1 << 26) + + +/* Setup USB on the board */ +int board_usb_init(const void *blob); + +#endif /* _TEGRA_USB_H_ */ diff --git a/arch/arm/include/asm/arch-tegra30/usb.h b/arch/arm/include/asm/arch-tegra30/usb.h new file mode 100644 index 0000000..84049b7 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra30/usb.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2013 NVIDIA Corporation + * 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 + */ + +#ifndef _TEGRA_USB_H_ +#define _TEGRA_USB_H_ + + +/* USB Controller (USBx_CONTROLLER_) regs */ +struct usb_ctlr { + /* 0x000 */ + uint id; + uint reserved0; + uint host; + uint device; + + /* 0x010 */ + uint txbuf; + uint rxbuf; + uint reserved1[2]; + + /* 0x020 */ + uint reserved2[56]; + + /* 0x100 */ + u16 cap_length; + u16 hci_version; + uint hcs_params; + uint hcc_params; + uint reserved3[5]; + + /* 0x120 */ + uint dci_version; + uint dcc_params; + uint reserved4[2]; + + /* 0x130 */ + uint usb_cmd; + uint usb_sts; + uint usb_intr; + uint frindex; + + /* 0x140 */ + uint reserved5; + uint periodic_list_base; + uint async_list_addr; + uint reserved5_1; + + /* 0x150 */ + uint burst_size; + uint tx_fill_tuning; + uint reserved6; /* is this port_sc1 on some controllers? */ + uint icusb_ctrl; + + /* 0x160 */ + uint ulpi_viewport; + uint reserved7; + uint endpt_nak; + uint endpt_nak_enable; + + /* 0x170 */ + uint reserved; + uint port_sc1; + uint reserved8[6]; + + /* 0x190 */ + uint reserved9[8]; + + /* 0x1b0 */ + uint reserved10; + uint hostpc1_devlc; + uint reserved10_1[2]; + + /* 0x1c0 */ + uint reserved10_2[4]; + + /* 0x1d0 */ + uint reserved10_3[4]; + + /* 0x1e0 */ + uint reserved10_4[4]; + + /* 0x1f0 */ + uint reserved10_5; + uint otgsc; + uint usb_mode; + uint reserved10_6; + + /* 0x200 */ + uint reserved11[2]; + uint endpt_setup_stat; + uint reserved11_1[0x7D]; + + /* 0x400 */ + uint susp_ctrl; + uint phy_vbus_sensors; + uint phy_vbus_wakeup_id; + uint phy_alt_vbus_sys; + + /* 0x410 */ + uint usb1_legacy_ctrl; + uint reserved12[3]; + + /* 0x420 */ + uint reserved13[56]; + + /* 0x500 */ + uint reserved14[64 * 3]; + + /* 0x800 */ + uint utmip_pll_cfg0; + uint utmip_pll_cfg1; + uint utmip_xcvr_cfg0; + uint utmip_bias_cfg0; + + /* 0x810 */ + uint utmip_hsrx_cfg0; + uint utmip_hsrx_cfg1; + uint utmip_fslsrx_cfg0; + uint utmip_fslsrx_cfg1; + + /* 0x820 */ + uint utmip_tx_cfg0; + uint utmip_misc_cfg0; + uint utmip_misc_cfg1; + uint utmip_debounce_cfg0; + + /* 0x830 */ + uint utmip_bat_chrg_cfg0; + uint utmip_spare_cfg0; + uint utmip_xcvr_cfg1; + uint utmip_bias_cfg1; +}; + +/* USB1_LEGACY_CTRL */ +#define USB1_NO_LEGACY_MODE 1 + +#define VBUS_SENSE_CTL_SHIFT 1 +#define VBUS_SENSE_CTL_MASK (3 << VBUS_SENSE_CTL_SHIFT) +#define VBUS_SENSE_CTL_VBUS_WAKEUP 0 +#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP 1 +#define VBUS_SENSE_CTL_AB_SESS_VLD 2 +#define VBUS_SENSE_CTL_A_SESS_VLD 3 + +/* USB2_IF_ULPI_TIMING_CTRL_0 */ +#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) +#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) + +/* USB2_IF_ULPI_TIMING_CTRL_1 */ +#define ULPI_DATA_TRIMMER_LOAD (1 << 0) +#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) +#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) +#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) +#define ULPI_DIR_TRIMMER_LOAD (1 << 24) +#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) + +/* USBx_IF_USB_SUSP_CTRL_0 */ +#define ULPI_PHY_ENB (1 << 13) +#define UTMIP_PHY_ENB (1 << 12) +#define UTMIP_RESET (1 << 11) +#define USB_PHY_CLK_VALID (1 << 7) +#define USB_SUSP_CLR (1 << 5) + +/* USBx_UTMIP_MISC_CFG0 */ +#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) + +/* USBx_UTMIP_MISC_CFG1 */ +#define UTMIP_PLLU_STABLE_COUNT_SHIFT 6 +#define UTMIP_PLLU_STABLE_COUNT_MASK \ + (0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT) +#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT 18 +#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK \ + (0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT) +#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30) + +/* USBx_UTMIP_PLL_CFG1_0 */ +#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT 27 +#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK \ + (0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT) +#define UTMIP_XTAL_FREQ_COUNT_SHIFT 0 +#define UTMIP_XTAL_FREQ_COUNT_MASK 0xfff + +/* USBx_UTMIP_BIAS_CFG0_0 */ +#define UTMIP_HSDISCON_LEVEL_MSB (1 << 24) +#define UTMIP_OTGPD (1 << 11) +#define UTMIP_BIASPD (1 << 10) +#define UTMIP_HSDISCON_LEVEL_SHIFT 2 +#define UTMIP_HSDISCON_LEVEL_MASK \ + (0x3 << UTMIP_HSDISCON_LEVEL_SHIFT) +#define UTMIP_HSSQUELCH_LEVEL_SHIFT 0 +#define UTMIP_HSSQUELCH_LEVEL_MASK \ + (0x3 << UTMIP_HSSQUELCH_LEVEL_SHIFT) + +/* USBx_UTMIP_BIAS_CFG1_0 */ +#define UTMIP_FORCE_PDTRK_POWERDOWN 1 +#define UTMIP_BIAS_PDTRK_COUNT_SHIFT 3 +#define UTMIP_BIAS_PDTRK_COUNT_MASK \ + (0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT) + +#define UTMIP_DEBOUNCE_CFG0_SHIFT 0 +#define UTMIP_DEBOUNCE_CFG0_MASK 0xffff + +/* USBx_UTMIP_TX_CFG0_0 */ +#define UTMIP_FS_PREAMBLE_J (1 << 19) + +/* USBx_UTMIP_BAT_CHRG_CFG0_0 */ +#define UTMIP_PD_CHRG 1 + +/* USBx_UTMIP_SPARE_CFG0_0 */ +#define FUSE_SETUP_SEL (1 << 3) + +/* USBx_UTMIP_HSRX_CFG0_0 */ +#define UTMIP_IDLE_WAIT_SHIFT 15 +#define UTMIP_IDLE_WAIT_MASK (0x1f << UTMIP_IDLE_WAIT_SHIFT) +#define UTMIP_ELASTIC_LIMIT_SHIFT 10 +#define UTMIP_ELASTIC_LIMIT_MASK \ + (0x1f << UTMIP_ELASTIC_LIMIT_SHIFT) + +/* USBx_UTMIP_HSRX_CFG0_1 */ +#define UTMIP_HS_SYNC_START_DLY_SHIFT 1 +#define UTMIP_HS_SYNC_START_DLY_MASK \ + (0xf << UTMIP_HS_SYNC_START_DLY_SHIFT) + +/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */ +#define IC_ENB1 (1 << 3) + +/* PORTSC1, USB1, defined for Tegra20 to avoid compiling error */ +#define PTS1_SHIFT 31 +#define PTS1_MASK (1 << PTS1_SHIFT) +#define STS1 (1 << 30) + +/* USB2D_HOSTPC1_DEVLC_0 */ +#define PTS_SHIFT 29 +#define PTS_MASK (0x7U << PTS_SHIFT) +#define PTS_UTMI 0 +#define PTS_RESERVED 1 +#define PTS_ULPI 2 +#define PTS_ICUSB_SER 3 +#define PTS_HSIC 4 + +#define STS (1 << 28) + +/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */ +#define WKOC (1 << 22) +#define WKDS (1 << 21) +#define WKCN (1 << 20) + +/* USBx_UTMIP_XCVR_CFG0_0 */ +#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) +#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) +#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) +#define UTMIP_XCVR_LSBIAS_SE (1 << 21) +#define UTMIP_XCVR_HSSLEW_MSB_SHIFT 25 +#define UTMIP_XCVR_HSSLEW_MSB_MASK \ + (0x7f << UTMIP_XCVR_HSSLEW_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_MSB_SHIFT 22 +#define UTMIP_XCVR_SETUP_MSB_MASK (0x7 << UTMIP_XCVR_SETUP_MSB_SHIFT) +#define UTMIP_XCVR_SETUP_SHIFT 0 +#define UTMIP_XCVR_SETUP_MASK (0xf << UTMIP_XCVR_SETUP_SHIFT) + +/* USBx_UTMIP_XCVR_CFG1_0 */ +#define UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT 18 +#define UTMIP_XCVR_TERM_RANGE_ADJ_MASK \ + (0xf << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT) +#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) +#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) + +/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */ +#define VBUS_VLD_STS (1 << 26) + + +/* Setup USB on the board */ +int board_usb_init(const void *blob); + +#endif /* _TEGRA_USB_H_ */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 8d7a227..f0f81c9 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -46,7 +46,7 @@ #include <asm/arch/emc.h> #endif #ifdef CONFIG_USB_EHCI_TEGRA -#include <asm/arch-tegra/usb.h> +#include <asm/arch/usb.h> #endif #ifdef CONFIG_TEGRA_MMC #include <asm/arch-tegra/tegra_mmc.h> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c816878..6a55cd2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -122,6 +122,31 @@ static struct descriptor { #define ehci_is_TDI() (0) #endif +int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) +{ + return PORTSC_PSPD(reg); +} + +int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) + __attribute__((weak, alias("__ehci_get_port_speed"))); + +void __ehci_set_usbmode(int index) +{ + uint32_t tmp; + uint32_t *reg_ptr; + + reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE); + tmp = ehci_readl(reg_ptr); + tmp |= USBMODE_CM_HC; +#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) + tmp |= USBMODE_BE; +#endif + ehci_writel(reg_ptr, tmp); +} + +void ehci_set_usbmode(int index) + __attribute__((weak, alias("__ehci_set_usbmode"))); + void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) { mdelay(50); @@ -149,8 +174,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) static int ehci_reset(int index) { uint32_t cmd; - uint32_t tmp; - uint32_t *reg_ptr; int ret = 0; cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); @@ -163,15 +186,8 @@ static int ehci_reset(int index) goto out; } - if (ehci_is_TDI()) { - reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE); - tmp = ehci_readl(reg_ptr); - tmp |= USBMODE_CM_HC; -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) - tmp |= USBMODE_BE; -#endif - ehci_writel(reg_ptr, tmp); - } + if (ehci_is_TDI()) + ehci_set_usbmode(index); #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); @@ -711,7 +727,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; if (ehci_is_TDI()) { - switch (PORTSC_PSPD(reg)) { + switch (ehci_get_port_speed(ctrl->hcor, reg)) { case PORTSC_PSPD_FS: break; case PORTSC_PSPD_LS: diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 554145a..6b53659 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (c) 2009-2012 NVIDIA Corporation + * Copyright (c) 2009-2013 NVIDIA Corporation * Copyright (c) 2013 Lucas Stach * * See file CREDITS for list of people who contributed to this @@ -27,7 +27,8 @@ #include <asm/io.h> #include <asm-generic/gpio.h> #include <asm/arch/clock.h> -#include <asm/arch-tegra/usb.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch/usb.h> #include <usb.h> #include <usb/ulpi.h> #include <libfdt.h> @@ -35,6 +36,9 @@ #include "ehci.h" +#define HOSTPC1_DEVLC 0x84 +#define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) + #ifdef CONFIG_USB_ULPI #ifndef CONFIG_USB_ULPI_VIEWPORT #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ @@ -74,6 +78,7 @@ enum dr_mode { /* Information about a USB port */ struct fdt_usb { struct usb_ctlr *reg; /* address of registers in physical memory */ + int params[PARAM_COUNT]; /* timing parameters */ unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ unsigned enabled:1; /* 1 to enable, 0 to disable */ @@ -87,55 +92,8 @@ struct fdt_usb { static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ static unsigned port_count; /* Number of available ports */ - -/* - * This table has USB timing parameters for each Oscillator frequency we - * support. There are four sets of values: - * - * 1. 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 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) - * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) - * Filter frequency (MHz) 1 4.8 6 2 - * CPCON 1100b 0011b 1100b 1100b - * LFCON0 0 0 0 0 - * - * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * --------------------------------------------------------------------------- - * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) - * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) - * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) - * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) - * - * 3. 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 two 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. - * - * 4. The 20 microsecond delay after bias cell operation. - */ -static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; +static unsigned is_T30_compatible; +static unsigned is_T114_compatible; /* UTMIP Idle Wait Delay */ static const u8 utmip_idle_wait_delay = 17; @@ -155,14 +113,62 @@ static const u8 utmip_hs_sync_start_delay = 9; */ void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) { - mdelay(50); - if (((u32) status_reg & TEGRA_USB_ADDR_MASK) != TEGRA_USB1_BASE) + udelay(49990); + if (is_T30_compatible) { + /* + * Tegra 114 takes 50 ms to assert Port Enable bit. + * We have to exit earlier. Otherwise ehci-hcd.c will clear + * our Port Enable bit. + */ + if (is_T114_compatible) + return; + /* Tegra 3 takes about 55 ms to assert Port Enable bit. */ + udelay(5010); + return; + } + udelay(10); + if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != TEGRA_USB1_BASE) return; /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ if (ehci_readl(status_reg) & EHCI_PS_CSC) *reg |= EHCI_PS_CSC; } +/* + * This ehci_set_usbmode overrides the weak function ehci_set_usbmode + * in "ehci-hcd.c". + */ +void ehci_set_usbmode(int index) +{ + struct fdt_usb *config; + struct usb_ctlr *usbctlr; + uint32_t tmp; + + config = &port[index]; + usbctlr = config->reg; + + tmp = ehci_readl(&usbctlr->usb_mode); + tmp |= USBMODE_CM_HC; + ehci_writel(&usbctlr->usb_mode, tmp); +} + +/* + * This ehci_get_port_speed overrides the weak function ehci_get_port_speed + * in "ehci-hcd.c". + */ +int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) +{ + uint32_t tmp; + uint32_t *reg_ptr; + + if (is_T30_compatible) { + reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); + tmp = ehci_readl(reg_ptr); + return HOSTPC1_PSPD(tmp); + } else + return PORTSC_PSPD(reg); +} + /* Put the port into host mode */ static void set_host_mode(struct fdt_usb *config) { @@ -171,7 +177,7 @@ static void set_host_mode(struct fdt_usb *config) * bail out in this case. */ if (config->dr_mode == DR_MODE_OTG && - (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) + (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) return; /* @@ -214,8 +220,10 @@ static int init_utmi_usb_controller(struct fdt_usb *config) { u32 val; int loop_count; - const unsigned *timing; + const u32 *timing; struct usb_ctlr *usbctlr = config->reg; + struct clk_rst_ctlr *clkrst; + struct usb_ctlr *usb1ctlr; clock_enable(config->periph_id); @@ -232,45 +240,112 @@ static int init_utmi_usb_controller(struct fdt_usb *config) * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP * mux must be switched to actually use a_sess_vld threshold. */ - if (fdt_gpio_isvalid(&config->vbus_gpio)) { + if (config->dr_mode == DR_MODE_OTG && + fdt_gpio_isvalid(&config->vbus_gpio)) clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, - VBUS_SENSE_CTL_MASK, - VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); - } + VBUS_SENSE_CTL_MASK, + VBUS_SENSE_CTL_A_SESS_VLD << + VBUS_SENSE_CTL_SHIFT); /* * PLL Delay CONFIGURATION settings. The following parameters control * the bring up of the plls. */ - timing = usb_pll[clock_get_osc_freq()]; + timing = (u32 *)config->params; + if (is_T30_compatible) + goto pll_T30_init; val = readl(&usbctlr->utmip_misc_cfg1); clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); + timing[PARAM_STABLE_COUNT] << + UTMIP_PLLU_STABLE_COUNT_SHIFT); clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << + timing[PARAM_ACTIVE_DELAY_COUNT] << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); writel(val, &usbctlr->utmip_misc_cfg1); /* Set PLL enable delay count and crystal frequency count */ val = readl(&usbctlr->utmip_pll_cfg1); clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << + timing[PARAM_ENABLE_DELAY_COUNT] << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << + timing[PARAM_XTAL_FREQ_COUNT] << UTMIP_XTAL_FREQ_COUNT_SHIFT); writel(val, &usbctlr->utmip_pll_cfg1); + goto pll_init_done; + +pll_T30_init: + clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + val = readl(&clkrst->crc_utmip_pll_cfg2); + clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, + timing[PARAM_STABLE_COUNT] << + UTMIP_PLLU_STABLE_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, + timing[PARAM_ACTIVE_DELAY_COUNT] << + UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); + writel(val, &clkrst->crc_utmip_pll_cfg2); + + /* Set PLL enable delay count and crystal frequency count */ + val = readl(&clkrst->crc_utmip_pll_cfg1); + clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, + timing[PARAM_ENABLE_DELAY_COUNT] << + UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, + timing[PARAM_XTAL_FREQ_COUNT] << + UTMIP_XTAL_FREQ_COUNT_SHIFT); + writel(val, &clkrst->crc_utmip_pll_cfg1); + + /* Disable Power Down state for PLL */ + clrbits_le32(&clkrst->crc_utmip_pll_cfg1, + PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | + PLL_ACTIVE_POWERDOWN); + + /* Recommended PHY settings for EYE diagram */ + val = readl(&usbctlr->utmip_xcvr_cfg0); + clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, + 0x4 << UTMIP_XCVR_SETUP_SHIFT); + clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, + 0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); + clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, + 0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); + writel(val, &usbctlr->utmip_xcvr_cfg0); + + clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, + UTMIP_XCVR_TERM_RANGE_ADJ_MASK, + 0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); + + /* Some registers can be controlled from USB1 only. */ + if (config->periph_id != PERIPH_ID_USBD) { + clock_enable(PERIPH_ID_USBD); + /* Disable Reset if in Reset state */ + reset_set_enable(PERIPH_ID_USBD, 0); + } + usb1ctlr = (struct usb_ctlr *)TEGRA_USB1_BASE; + val = readl(&usb1ctlr->utmip_bias_cfg0); + setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); + clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, + 0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); + clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, + 0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); + writel(val, &usb1ctlr->utmip_bias_cfg0); + + /* Miscellaneous setting mentioned in Programming Guide */ + clrbits_le32(&usbctlr->utmip_misc_cfg0, UTMIP_SUSPEND_EXIT_ON_EDGE); +pll_init_done: /* Setting the tracking length time */ clrsetbits_le32(&usbctlr->utmip_bias_cfg1, - UTMIP_BIAS_PDTRK_COUNT_MASK, - timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); + UTMIP_BIAS_PDTRK_COUNT_MASK, + timing[PARAM_BIAS_TIME] << + UTMIP_BIAS_PDTRK_COUNT_SHIFT); /* Program debounce time for VBUS to become valid */ clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, - UTMIP_DEBOUNCE_CFG0_MASK, - timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); + UTMIP_DEBOUNCE_CFG0_MASK, + timing[PARAM_DEBOUNCE_A_TIME] << + UTMIP_DEBOUNCE_CFG0_SHIFT); setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); @@ -292,15 +367,16 @@ static int init_utmi_usb_controller(struct fdt_usb *config) /* Set PLL enable delay count and Crystal frequency count */ val = readl(&usbctlr->utmip_hsrx_cfg0); clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, - utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); + utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, - utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); + utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); writel(val, &usbctlr->utmip_hsrx_cfg0); /* Configure the UTMIP_HS_SYNC_START_DLY */ clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, - UTMIP_HS_SYNC_START_DLY_MASK, - utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); + UTMIP_HS_SYNC_START_DLY_MASK, + utmip_hs_sync_start_delay << + UTMIP_HS_SYNC_START_DLY_SHIFT); /* Preceed the crystal clock disable by >100ns delay. */ udelay(1); @@ -308,6 +384,14 @@ static int init_utmi_usb_controller(struct fdt_usb *config) /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); + if (is_T30_compatible) { + if (config->periph_id == PERIPH_ID_USBD) + clrbits_le32(&clkrst->crc_utmip_pll_cfg2, + UTMIP_FORCE_PD_SAMP_A_POWERDOWN); + if (config->periph_id == PERIPH_ID_USB3) + clrbits_le32(&clkrst->crc_utmip_pll_cfg2, + UTMIP_FORCE_PD_SAMP_C_POWERDOWN); + } /* Finished the per-controller init. */ /* De-assert UTMIP_RESET to bring out of reset. */ @@ -325,17 +409,37 @@ static int init_utmi_usb_controller(struct fdt_usb *config) /* Disable ICUSB FS/LS transceiver */ clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); - /* Select UTMI parallel interface */ - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS); + if (!is_T30_compatible) { + /* Select UTMI parallel interface */ + if (config->periph_id == PERIPH_ID_USBD) { + clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK, + PTS_UTMI << PTS1_SHIFT); + clrbits_le32(&usbctlr->port_sc1, STS1); + } else { + clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, + PTS_UTMI << PTS_SHIFT); + clrbits_le32(&usbctlr->port_sc1, STS); + } + } /* Deassert power down state */ clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | - UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); + UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | - UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); + UTMIP_FORCE_PDCHRP_POWERDOWN | + UTMIP_FORCE_PDDR_POWERDOWN); + if (is_T30_compatible) { + /* + * BIAS Pad Power Down is common among all 3 USB + * controllers and can be controlled from USB1 only. + */ + usb1ctlr = (struct usb_ctlr *)TEGRA_USB1_BASE; + clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); + udelay(25); + clrbits_le32(&usb1ctlr->utmip_bias_cfg1, + UTMIP_FORCE_PDTRK_POWERDOWN); + } return 0; } @@ -371,7 +475,7 @@ static int init_ulpi_usb_controller(struct fdt_usb *config) /* enable pinmux bypass */ setbits_le32(&usbctlr->ulpi_timing_ctrl_0, - ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); + ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); /* Select ULPI parallel interface */ clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT); @@ -431,16 +535,28 @@ static int init_ulpi_usb_controller(struct fdt_usb *config) } #endif -static void config_clock(const u32 timing[]) +static void config_clock(const u32 *timing) { clock_start_pll(CLOCK_ID_USB, - timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], - timing[PARAM_CPCON], timing[PARAM_LFCON]); + timing[PARAM_DIVM], timing[PARAM_DIVN], + timing[PARAM_DIVP], timing[PARAM_CPCON], + timing[PARAM_LFCON]); } -int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) +int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_hz, + struct fdt_usb *config) { const char *phy, *mode; + int clk_node = 0, rate; + + /* Find the parameters for our oscillator frequency */ + do { + clk_node = fdt_node_offset_by_compatible(blob, + clk_node, "nvidia,usbparams"); + if (clk_node < 0) + return -FDT_ERR_NOTFOUND; + rate = fdtdec_get_int(blob, clk_node, "osc-frequency", 0); + } while (rate != osc_frequency_hz); config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); mode = fdt_getprop(blob, node, "dr_mode", NULL); @@ -480,27 +596,30 @@ int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) config->ulpi, config->periph_id, config->vbus_gpio.gpio, config->phy_reset_gpio.gpio, config->dr_mode); - return 0; + return fdtdec_get_int_array(blob, clk_node, "params", + (u32 *)&config->params, PARAM_COUNT); } -int board_usb_init(const void *blob) +/* + * Process a list of nodes, adding them to our list of SDMMC ports. + * + * @param blob fdt blob + * @param node_list list of nodes to process (any <=0 are ignored) + * @param count number of nodes to process + * @return 0 if ok, -1 on error + */ +static int process_nodes(const void *blob, int node_list[], int count) { struct fdt_usb config; - enum clock_osc_freq freq; - int node_list[USB_PORTS_MAX]; - int node, count, i; + int node, i; + int clk_done = 0; + unsigned osc_freq = clock_get_rate(CLOCK_ID_OSC); - /* Set up the USB clocks correctly based on our oscillator frequency */ - freq = clock_get_osc_freq(); - config_clock(usb_pll[freq]); - - /* count may return <0 on error */ - count = fdtdec_find_aliases_for_id(blob, "usb", - COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); + port_count = 0; for (i = 0; i < count; i++) { if (port_count == USB_PORTS_MAX) { - printf("tegrausb: Cannot register more than %d ports\n", - USB_PORTS_MAX); + printf("tegrausb: Cannot register more than %d ports\n" + , USB_PORTS_MAX); return -1; } @@ -508,11 +627,15 @@ int board_usb_init(const void *blob) node = node_list[i]; if (!node) continue; - if (fdt_decode_usb(blob, node, &config)) { + if (fdt_decode_usb(blob, node, osc_freq, &config)) { debug("Cannot decode USB node %s\n", fdt_get_name(blob, node, NULL)); return -1; } + if (!clk_done) { + config_clock((u32 *)&config.params); + clk_done = 1; + } config.initialized = 0; /* add new USB port to the list of available ports */ @@ -522,6 +645,49 @@ int board_usb_init(const void *blob) return 0; } +int board_usb_init(const void *blob) +{ + int node_list[USB_PORTS_MAX]; + int count, err; + + is_T30_compatible = 0; + is_T114_compatible = 0; + + /* count may return <0 on error */ + count = fdtdec_find_aliases_for_id(blob, "usb", + COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); + if (!count) + goto skip_T20_process; + err = process_nodes(blob, node_list, count); + if (err) { + printf("%s: Error processing T20 compatible USB node(s)!\n", + __func__); + return err; + } +skip_T20_process: + + count = fdtdec_find_aliases_for_id(blob, "usb", + COMPAT_NVIDIA_TEGRA114_USB, node_list, USB_PORTS_MAX); + if (count) + is_T114_compatible = 1; + + count = fdtdec_find_aliases_for_id(blob, "usb", + COMPAT_NVIDIA_TEGRA30_USB, node_list, USB_PORTS_MAX); + if (count) + is_T30_compatible = 1; + else + goto skip_T30_process; + err = process_nodes(blob, node_list, count); + if (count && err) { + printf("%s: Error processing T30 compatible USB node(s)!\n", + __func__); + return err; + } +skip_T30_process: + + return 0; +} + /** * Start up the given port number (ports are numbered from 0 on each board). * This returns values for the appropriate hccr and hcor addresses to use for @@ -564,6 +730,20 @@ success: usbctlr = config->reg; *hccr = (struct ehci_hccr *)&usbctlr->cap_length; *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; + + if (is_T30_compatible) { + /* Set to Host mode after Controller Reset was done */ + clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, + USBMODE_CM_HC); + /* Select UTMI parallel interface after setting host mode */ + if (config->utmi) { + clrsetbits_le32((char *)&usbctlr->usb_cmd + + HOSTPC1_DEVLC, PTS_MASK, + PTS_UTMI << PTS_SHIFT); + clrbits_le32((char *)&usbctlr->usb_cmd + + HOSTPC1_DEVLC, STS); + } + } return 0; } -- 1.7.7 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot