Module Name: src Committed By: jmcneill Date: Sat Sep 23 23:21:35 UTC 2017
Modified Files: src/sys/arch/arm/nvidia: tegra210_car.c tegra210_carreg.h tegra210_xusbpad.c Log Message: More XUSB init stuff. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/nvidia/tegra210_car.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/nvidia/tegra210_carreg.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/nvidia/tegra210_xusbpad.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/nvidia/tegra210_car.c diff -u src/sys/arch/arm/nvidia/tegra210_car.c:1.6 src/sys/arch/arm/nvidia/tegra210_car.c:1.7 --- src/sys/arch/arm/nvidia/tegra210_car.c:1.6 Fri Sep 22 10:54:44 2017 +++ src/sys/arch/arm/nvidia/tegra210_car.c Sat Sep 23 23:21:35 2017 @@ -1,4 +1,5 @@ -/* $NetBSD: tegra210_car.c,v 1.6 2017/09/22 10:54:44 jmcneill Exp $ */ +/* $NetBSD: tegra210_car.c,v 1.7 2017/09/23 23:21:35 jmcneill Exp $ */ +#define TEGRA210_CAR_DEBUG /*- * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra210_car.c,v 1.6 2017/09/22 10:54:44 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra210_car.c,v 1.7 2017/09/23 23:21:35 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -738,31 +739,58 @@ tegra210_car_utmip_init(struct tegra210_ bus_space_tag_t bst = sc->sc_bst; bus_space_handle_t bsh = sc->sc_bsh; - const u_int enable_dly_count = 5; - const u_int stable_count = 150; - const u_int active_dly_count = 24; - const u_int xtal_freq_count = 385; + /* + * Set up the UTMI PLL. + */ + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG3_REG, + 0, CAR_UTMIP_PLL_CFG3_REF_SRC_SEL); + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG3_REG, + 0, CAR_UTMIP_PLL_CFG3_REF_DIS); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + 0, CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE); + delay(10); + /* TODO UTMIP_PLL_CFG0 */ + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, + CAR_UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN, 0); + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, + 0, CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT); /* Don't care */ + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, + 0, CAR_UTMIP_PLL_CFG2_STABLE_COUNT); + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, + 0, CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT); + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, + 0x3, CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT); + + bus_space_write_4(bst, bsh, CAR_RST_DEV_W_CLR_REG, CAR_DEV_W_XUSB); + bus_space_write_4(bst, bsh, CAR_RST_DEV_Y_CLR_REG, CAR_DEV_Y_PEX_USB_UPHY); + bus_space_write_4(bst, bsh, CAR_RST_DEV_Y_CLR_REG, CAR_DEV_Y_SATA_USB_UPHY); tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, - __SHIFTIN(stable_count, CAR_UTMIP_PLL_CFG2_STABLE_COUNT) | - __SHIFTIN(active_dly_count, CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT), + CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERUP | + CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERUP | + CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERUP, CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERDOWN | CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERDOWN | - CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN | - CAR_UTMIP_PLL_CFG2_STABLE_COUNT | - CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT); - - tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, - __SHIFTIN(enable_dly_count, CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT) | - __SHIFTIN(xtal_freq_count, CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT), - CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT | - CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT); - - tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, - 0, - CAR_UTMIP_PLL_CFG1_PLLU_POWERDOWN | - CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN); + CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN); + /* + * Set up UTMI PLL under hardware control + */ + tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, 0, + CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERUP | CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + 0, CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE, 0); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + 0, CAR_UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + CAR_UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET, 0); + tegra_reg_set_clear(bst, bsh, CLK_RST_CONTROLLER_XUSB_PLL_CFG0_REG, + 0, CLK_RST_CONTROLLER_XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY); + delay(1); + tegra_reg_set_clear(bst, bsh, CAR_UTMIPLL_HW_PWRDN_CFG0_REG, + CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE, 0); } static void @@ -781,6 +809,11 @@ tegra210_car_xusb_init(struct tegra210_c tegra_reg_set_clear(bst, bsh, CAR_PLLU_OUTA_REG, 0, CAR_PLLU_OUTA_OUT1_RSTN); tegra_reg_set_clear(bst, bsh, CAR_PLLU_OUTA_REG, 0, CAR_PLLU_OUTA_OUT2_RSTN); delay(5); + tegra_reg_set_clear(bst, bsh, CAR_PLLU_BASE_REG, + __SHIFTIN(0x19, CAR_PLLU_BASE_DIVN) | + __SHIFTIN(0x2, CAR_PLLU_BASE_DIVM) | + __SHIFTIN(0x1, CAR_PLLU_BASE_DIVP), + CAR_PLLU_BASE_DIVN | CAR_PLLU_BASE_DIVM | CAR_PLLU_BASE_DIVP); tegra_reg_set_clear(bst, bsh, CAR_PLLU_BASE_REG, CAR_PLLU_BASE_ENABLE, 0); do { delay(2); @@ -794,20 +827,60 @@ tegra210_car_xusb_init(struct tegra210_c delay(2); /* + * Set up PLLREFE + */ + tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_MISC_REG, + 0, CAR_PLLREFE_MISC_IDDQ); + delay(5); + tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_BASE_REG, + __SHIFTIN(0x4, CAR_PLLREFE_BASE_DIVM) | + __SHIFTIN(0x41, CAR_PLLREFE_BASE_DIVN) | + __SHIFTIN(0x0, CAR_PLLREFE_BASE_DIVP) | + __SHIFTIN(0x0, CAR_PLLREFE_BASE_KCP), + CAR_PLLREFE_BASE_DIVM | + CAR_PLLREFE_BASE_DIVN | + CAR_PLLREFE_BASE_DIVP | + CAR_PLLREFE_BASE_KCP); + tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_BASE_REG, + CAR_PLLREFE_BASE_ENABLE, 0); + do { + delay(2); + val = bus_space_read_4(bst, bsh, CAR_PLLREFE_MISC_REG); + } while ((val & CAR_PLLREFE_MISC_LOCK) == 0); + + /* * Set up the PLLE. */ tegra_reg_set_clear(bst, bsh, CAR_PLLE_AUX_REG, 0, CAR_PLLE_AUX_REF_SEL_PLLREFE); tegra_reg_set_clear(bst, bsh, CAR_PLLE_AUX_REG, 0, CAR_PLLE_AUX_REF_SRC); tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, 0, CAR_PLLE_MISC_IDDQ_OVERRIDE); delay(5); - tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, CAR_PLLE_MISC_PTS, 0); + tegra_reg_set_clear(bst, bsh, CAR_PLLE_BASE_REG, + __SHIFTIN(0xe, CAR_PLLE_BASE_DIVP_CML) | + __SHIFTIN(0x7d, CAR_PLLE_BASE_DIVN) | + __SHIFTIN(0x2, CAR_PLLE_BASE_DIVM), + CAR_PLLE_BASE_DIVP_CML | + CAR_PLLE_BASE_DIVN | + CAR_PLLE_BASE_DIVM); + tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, + CAR_PLLE_MISC_PTS, + CAR_PLLE_MISC_KCP | CAR_PLLE_MISC_VREG_CTRL | CAR_PLLE_MISC_KVCO); tegra_reg_set_clear(bst, bsh, CAR_PLLE_BASE_REG, CAR_PLLE_BASE_ENABLE, 0); do { delay(2); val = bus_space_read_4(bst, bsh, CAR_PLLE_MISC_REG); } while ((val & CAR_PLLE_MISC_LOCK) == 0); - tegra_reg_set_clear(bst, bsh, CAR_PLLE_SS_CNTL_REG, 0, CAR_PLLE_SS_CNTL_BYPASS_SS); - tegra_reg_set_clear(bst, bsh, CAR_PLLE_SS_CNTL_REG, 0, CAR_PLLE_SS_CNTL_SSCBYP); + tegra_reg_set_clear(bst, bsh, CAR_PLLE_SS_CNTL_REG, + __SHIFTIN(1, CAR_PLLE_SS_CNTL_SSCINC) | + __SHIFTIN(0x23, CAR_PLLE_SS_CNTL_SSCINCINTRV) | + __SHIFTIN(0x21, CAR_PLLE_SS_CNTL_SSCMAX), + CAR_PLLE_SS_CNTL_SSCINC | + CAR_PLLE_SS_CNTL_SSCINCINTRV | + CAR_PLLE_SS_CNTL_SSCMAX | + CAR_PLLE_SS_CNTL_SSCINVERT | + CAR_PLLE_SS_CNTL_SSCCENTER | + CAR_PLLE_SS_CNTL_BYPASS_SS | + CAR_PLLE_SS_CNTL_SSCBYP); delay(1); tegra_reg_set_clear(bst, bsh, CAR_PLLE_SS_CNTL_REG, 0, CAR_PLLE_SS_CNTL_INTERP_RESET); tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, 0, CAR_PLLE_MISC_IDDQ_SWCTL); @@ -819,39 +892,7 @@ tegra210_car_xusb_init(struct tegra210_c tegra_reg_set_clear(bst, bsh, CAR_PLLE_AUX_REG, CAR_PLLE_AUX_SEQ_ENABLE, 0); bus_space_write_4(bst, bsh, CAR_CLK_ENB_W_SET_REG, CAR_DEV_W_XUSB); - - tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_MISC_REG, - 0, CAR_PLLREFE_MISC_IDDQ); - val = __SHIFTIN(25, CAR_PLLREFE_BASE_DIVN) | - __SHIFTIN(1, CAR_PLLREFE_BASE_DIVM); - bus_space_write_4(bst, bsh, CAR_PLLREFE_BASE_REG, val); - - tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_MISC_REG, - 0, CAR_PLLREFE_MISC_LOCK_OVERRIDE); - tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_BASE_REG, - CAR_PLLREFE_BASE_ENABLE, 0); - tegra_reg_set_clear(bst, bsh, CAR_PLLREFE_MISC_REG, - CAR_PLLREFE_MISC_LOCK_ENABLE, 0); - - do { - delay(2); - val = bus_space_read_4(bst, bsh, CAR_PLLREFE_MISC_REG); - } while ((val & CAR_PLLREFE_MISC_LOCK) == 0); - - tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, - CAR_PLLE_MISC_IDDQ_SWCTL, CAR_PLLE_MISC_IDDQ_OVERRIDE); - tegra_reg_set_clear(bst, bsh, CAR_PLLE_BASE_REG, - CAR_PLLE_BASE_ENABLE, 0); - tegra_reg_set_clear(bst, bsh, CAR_PLLE_MISC_REG, - CAR_PLLE_MISC_LOCK_ENABLE, 0); - - do { - delay(2); - val = bus_space_read_4(bst, bsh, CAR_PLLE_MISC_REG); - } while ((val & CAR_PLLE_MISC_LOCK) == 0); - - tegra_reg_set_clear(bst, bsh, CAR_CLKSRC_XUSB_SS_REG, - CAR_CLKSRC_XUSB_SS_HS_CLK_BYPASS, 0); + bus_space_write_4(bst, bsh, CAR_CLK_ENB_W_SET_REG, CAR_DEV_W_XUSB_PADCTL); } static void @@ -964,6 +1005,9 @@ tegra210_car_clock_get_rate_pll(struct t } else if (tpll->base_reg == CAR_PLLP_BASE_REG) { /* XXX divp is not applied to PLLP's primary output */ divp = 0; + } else if (tpll->base_reg == CAR_PLLE_BASE_REG) { + divp = 0; + divm *= __SHIFTOUT(base, tpll->divp_mask); } else { divp = __SHIFTOUT(base, tpll->divp_mask); } Index: src/sys/arch/arm/nvidia/tegra210_carreg.h diff -u src/sys/arch/arm/nvidia/tegra210_carreg.h:1.5 src/sys/arch/arm/nvidia/tegra210_carreg.h:1.6 --- src/sys/arch/arm/nvidia/tegra210_carreg.h:1.5 Fri Sep 22 10:55:43 2017 +++ src/sys/arch/arm/nvidia/tegra210_carreg.h Sat Sep 23 23:21:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra210_carreg.h,v 1.5 2017/09/22 10:55:43 jmcneill Exp $ */ +/* $NetBSD: tegra210_carreg.h,v 1.6 2017/09/23 23:21:35 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -172,6 +172,10 @@ #define CAR_PLLE_MISC_LOCK __BIT(11) #define CAR_PLLE_MISC_LOCK_ENABLE __BIT(9) #define CAR_PLLE_MISC_PTS __BIT(8) +#define CAR_PLLE_MISC_KCP __BITS(7,6) +#define CAR_PLLE_MISC_VREG_BG_CTRL __BITS(5,4) +#define CAR_PLLE_MISC_VREG_CTRL __BITS(3,2) +#define CAR_PLLE_MISC_KVCO __BIT(0) #define CAR_PLLD2_BASE_REG 0x4b8 #define CAR_PLLD2_BASE_BYPASS __BIT(31) @@ -511,6 +515,9 @@ #define CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT __BITS(11,0) #define CAR_UTMIP_PLL_CFG2_REG 0x488 +#define CAR_UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN __BIT(30) +#define CAR_UTMIP_PLL_CFG2_PD_SAMP_D_POWERUP __BIT(25) +#define CAR_UTMIP_PLL_CFG2_PD_SAMP_D_POWERDOWN __BIT(24) #define CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT __BITS(23,18) #define CAR_UTMIP_PLL_CFG2_STABLE_COUNT __BITS(17,6) #define CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERUP __BIT(5) @@ -555,6 +562,12 @@ #define CAR_SATA_PLL_CFG1_PADPLL_PU_POST_DLY __BITS(15,8) #define CAR_SATA_PLL_CFG1_LANE_IDDQ2_PADPLL_IDDQ_DLY __BITS(7,0) +#define CAR_UTMIP_PLL_CFG3_REG 0x4c0 +#define CAR_UTMIP_PLL_CFG3_REF_SRC_SEL __BIT(26) +#define CAR_UTMIP_PLL_CFG3_REF_DIS __BIT(25) +#define CAR_UTMIP_PLL_CFG3_PTS __BIT(24) +#define CAR_UTMIP_PLL_CFG3_SETUP __BITS(23,0) + #define CAR_PLLREFE_BASE_REG 0x4c4 #define CAR_PLLREFE_BASE_BYPASS __BIT(31) #define CAR_PLLREFE_BASE_ENABLE __BIT(30) @@ -578,6 +591,7 @@ #define CAR_XUSBIO_PLL_CFG0_SEQ_STATE __BITS(27,26) #define CAR_XUSBIO_PLL_CFG0_SEQ_START_STATE __BIT(25) #define CAR_XUSBIO_PLL_CFG0_SEQ_ENABLE __BIT(24) +#define CAR_XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ __BIT(13) #define CAR_XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET __BIT(6) #define CAR_XUSBIO_PLL_CFG0_SEQ_RESET_INPUT_VALUE __BIT(5) #define CAR_XUSBIO_PLL_CFG0_SEQ_IN_SWCTL __BIT(4) @@ -586,6 +600,26 @@ #define CAR_XUSBIO_PLL_CFG0_PADPLL_RESET_OVERRIDE_VALUE __BIT(1) #define CAR_XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL __BIT(0) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_REG 0x52c +#define CAR_UTMIPLL_HW_PWRDN_CFG0_LOCK __BIT(31) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_STATE __BITS(27,26) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE __BIT(25) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE __BIT(24) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE __BIT(7) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET __BIT(6) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE __BIT(5) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL __BIT(4) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_OVERRIDE __BIT(3) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL __BIT(2) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE __BIT(1) +#define CAR_UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL __BIT(0) + +#define CLK_RST_CONTROLLER_XUSB_PLL_CFG0_REG 0x534 +#define CLK_RST_CONTROLLER_XUSB_PLL_CFG0_PLLU_CLK_SWITCH_DLY __BITS(31,24) +#define CLK_RST_CONTROLLER_XUSB_PLL_CFG0_PLLU_LOCK_DLY __BITS(23,14) +#define CLK_RST_CONTROLLER_XUSB_PLL_CFG0_UTMIPLL_IDDQ2_ENABLE_DLY __BITS(13,10) +#define CLK_RST_CONTROLLER_XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY __BITS(9,0) + #define CAR_CLKSRC_XUSB_HOST_REG 0x600 #define CAR_CLKSRC_XUSB_HOST_SRC __BITS(31,29) #define CAR_CLKSRC_XUSB_HOST_DIV __BITS(7,0) Index: src/sys/arch/arm/nvidia/tegra210_xusbpad.c diff -u src/sys/arch/arm/nvidia/tegra210_xusbpad.c:1.4 src/sys/arch/arm/nvidia/tegra210_xusbpad.c:1.5 --- src/sys/arch/arm/nvidia/tegra210_xusbpad.c:1.4 Fri Sep 22 11:01:24 2017 +++ src/sys/arch/arm/nvidia/tegra210_xusbpad.c Sat Sep 23 23:21:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra210_xusbpad.c,v 1.4 2017/09/22 11:01:24 jmcneill Exp $ */ +/* $NetBSD: tegra210_xusbpad.c,v 1.5 2017/09/23 23:21:35 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra210_xusbpad.c,v 1.4 2017/09/22 11:01:24 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra210_xusbpad.c,v 1.5 2017/09/23 23:21:35 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -46,6 +46,14 @@ __KERNEL_RCSID(0, "$NetBSD: tegra210_xus #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD __BITS(19,18) #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 1 +#define XUSB_PADCTL_VBUS_OC_MAP_REG 0x18 +#define XUSB_PADCTL_VBUS_OC_MAP_VBUS_ENABLE(n) __BIT((n) * 5) + +#define XUSB_PADCTL_OC_DET_REG 0x1c +#define XUSB_PADCTL_OC_DET_OC_DETECTED_VBUS_PAD(n) __BIT(12 + (n)) +#define XUSB_PADCTL_OC_DET_OC_DETECTED(n) __BIT(8 + (n)) +#define XUSB_PADCTL_OC_DET_SET_OC_DETECTED(n) __BIT(0 + (n)) + #define XUSB_PADCTL_ELPG_PROGRAM_1_REG 0x24 #define XUSB_PADCTL_ELPG_PROGRAM_1_AUX_MUX_LP0_VCORE_DOWN __BIT(31) #define XUSB_PADCTL_ELPG_PROGRAM_1_AUX_MUX_LP0_CLAMP_EN_EARLY __BIT(30) @@ -54,6 +62,39 @@ __KERNEL_RCSID(0, "$NetBSD: tegra210_xus #define XUSB_PADCTL_ELPG_PROGRAM_1_SSPn_ELPG_CLAMP_EN_EARLY(n) __BIT((n) * 3 + 1) #define XUSB_PADCTL_ELPG_PROGRAM_1_SSPn_ELPG_CLAMP_EN(n) __BIT((n) * 3 + 0) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG 0x360 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_PSDIV __BITS(29,28) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_NDIV __BITS(27,20) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_MDIV __BITS(17,16) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_LOCKDET_STATUS __BIT(15) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_PWR_OVRD __BIT(4) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_ENABLE __BIT(3) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_SLEEP __BITS(2,1) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_1_IDDQ __BIT(0) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG 0x364 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_CTRL __BITS(27,4) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_OVRD __BIT(2) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_DONE __BIT(1) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_EN __BIT(0) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_3_REG 0x368 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REG 0x36c +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_4_TXCLKREF_EN __BIT(15) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_4_TXCLKREF_SEL __BITS(13,12) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REFCLKBUF_EN __BIT(8) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REFCLK_SEL __BITS(7,4) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_5_REG 0x370 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_5_DCO_CTRL __BITS(23,16) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_6_REG 0x374 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_7_REG 0x378 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG 0x37c +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_DONE __BIT(31) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_OVRD __BIT(15) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_CLK_EN __BIT(13) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_EN __BIT(12) +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_9_REG 0x380 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_10_REG 0x384 +#define XUSB_PADCTL_UPHY_PLL_P0_CTL_11_REG 0x388 + #define XUSB_PADCTL_UPHY_USB3_PADn_ECTL_1_REG(n) (0xa60 + (n) * 0x40) #define XUSB_PADCTL_UPHY_USB3_PADn_ECTL_2_TX_TERM_CTRL __BITS(19,18) @@ -380,6 +421,9 @@ tegra210_xusbpad_configure_usb3_port(str delay(200); SETCLR4(sc, XUSB_PADCTL_ELPG_PROGRAM_1_REG, 0, XUSB_PADCTL_ELPG_PROGRAM_1_SSPn_ELPG_VCORE_DOWN(port->index)); + + SETCLR4(sc, XUSB_PADCTL_VBUS_OC_MAP_REG, + XUSB_PADCTL_VBUS_OC_MAP_VBUS_ENABLE(port->index), 0); } static void @@ -450,6 +494,8 @@ static void tegra210_xusbpad_xhci_enable(device_t dev) { struct tegra210_xusbpad_softc * const sc = device_private(dev); + uint32_t val; + int retry; SETCLR4(sc, XUSB_PADCTL_USB2_PAD_MUX_REG, __SHIFTIN(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB, @@ -457,6 +503,121 @@ tegra210_xusbpad_xhci_enable(device_t de XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD); tegra210_xusbpad_enable(sc); + + /* UPHY PLLs */ + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG, + __SHIFTIN(0x136, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_CTRL), + XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_CTRL); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_5_REG, + __SHIFTIN(0x2a, XUSB_PADCTL_UPHY_PLL_P0_CTL_5_DCO_CTRL), + XUSB_PADCTL_UPHY_PLL_P0_CTL_5_DCO_CTRL); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_1_PWR_OVRD, 0); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_OVRD, 0); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_OVRD, 0); + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REG, + __SHIFTIN(0, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REFCLK_SEL), + XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REFCLK_SEL); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REG, + __SHIFTIN(2, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_TXCLKREF_SEL), + XUSB_PADCTL_UPHY_PLL_P0_CTL_4_TXCLKREF_SEL); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_4_TXCLKREF_EN, 0); + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + __SHIFTIN(0, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_MDIV), + XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_MDIV); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + __SHIFTIN(0x19, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_NDIV), + XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_NDIV); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + __SHIFTIN(0, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_PSDIV), + XUSB_PADCTL_UPHY_PLL_P0_CTL_1_FREQ_PSDIV); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + 0, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_IDDQ); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + 0, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_SLEEP); + + delay(20); + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_4_REFCLKBUF_EN, 0); + + /* Calibration */ + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_EN, 0); + for (retry = 10000; retry > 0; retry--) { + delay(2); + val = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG); + if ((val & XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_DONE) != 0) + break; + } + if (retry == 0) { + aprint_error_dev(dev, "timeout calibrating UPHY PLL (1)\n"); + return; + } + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG, + 0, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_EN); + for (retry = 10000; retry > 0; retry--) { + delay(2); + val = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_2_REG); + if ((val & XUSB_PADCTL_UPHY_PLL_P0_CTL_2_CAL_DONE) == 0) + break; + } + if (retry == 0) { + aprint_error_dev(dev, "timeout calibrating UPHY PLL (2)\n"); + return; + } + + /* Enable the PLL */ + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_1_ENABLE, 0); + for (retry = 10000; retry > 0; retry--) { + delay(2); + val = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_1_REG); + if ((val & XUSB_PADCTL_UPHY_PLL_P0_CTL_1_LOCKDET_STATUS) != 0) + break; + } + if (retry == 0) { + aprint_error_dev(dev, "timeout enabling UPHY PLL\n"); + return; + } + + /* RCAL */ + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_EN, 0); + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG, + XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_CLK_EN, 0); + for (retry = 10000; retry > 0; retry--) { + delay(2); + val = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG); + if ((val & XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_DONE) != 0) + break; + } + if (retry == 0) { + aprint_error_dev(dev, "timeout calibrating UPHY PLL (3)\n"); + return; + } + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG, + 0, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_EN); + for (retry = 10000; retry > 0; retry--) { + delay(2); + val = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG); + if ((val & XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_DONE) == 0) + break; + } + if (retry == 0) { + aprint_error_dev(dev, "timeout calibrating UPHY PLL (4)\n"); + return; + } + + SETCLR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_REG, + 0, XUSB_PADCTL_UPHY_PLL_P0_CTL_8_RCAL_CLK_EN); } static const struct tegra_xusbpad_ops tegra210_xusbpad_ops = {