1*6c43f6c8STom Warren /* 2*6c43f6c8STom Warren * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. 3*6c43f6c8STom Warren * 4*6c43f6c8STom Warren * SPDX-License-Identifier: GPL-2.0 5*6c43f6c8STom Warren */ 6*6c43f6c8STom Warren 7*6c43f6c8STom Warren #define pr_fmt(fmt) "tegra-xusb-padctl: " fmt 8*6c43f6c8STom Warren 9*6c43f6c8STom Warren #include <common.h> 10*6c43f6c8STom Warren #include <errno.h> 11*6c43f6c8STom Warren #include <fdtdec.h> 12*6c43f6c8STom Warren #include <malloc.h> 13*6c43f6c8STom Warren 14*6c43f6c8STom Warren #include <asm/io.h> 15*6c43f6c8STom Warren 16*6c43f6c8STom Warren #include <asm/arch/clock.h> 17*6c43f6c8STom Warren #include <asm/arch-tegra/xusb-padctl.h> 18*6c43f6c8STom Warren 19*6c43f6c8STom Warren #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> 20*6c43f6c8STom Warren 21*6c43f6c8STom Warren struct tegra_xusb_phy_ops { 22*6c43f6c8STom Warren int (*prepare)(struct tegra_xusb_phy *phy); 23*6c43f6c8STom Warren int (*enable)(struct tegra_xusb_phy *phy); 24*6c43f6c8STom Warren int (*disable)(struct tegra_xusb_phy *phy); 25*6c43f6c8STom Warren int (*unprepare)(struct tegra_xusb_phy *phy); 26*6c43f6c8STom Warren }; 27*6c43f6c8STom Warren 28*6c43f6c8STom Warren struct tegra_xusb_phy { 29*6c43f6c8STom Warren const struct tegra_xusb_phy_ops *ops; 30*6c43f6c8STom Warren 31*6c43f6c8STom Warren struct tegra_xusb_padctl *padctl; 32*6c43f6c8STom Warren }; 33*6c43f6c8STom Warren 34*6c43f6c8STom Warren struct tegra_xusb_padctl { 35*6c43f6c8STom Warren struct fdt_resource regs; 36*6c43f6c8STom Warren 37*6c43f6c8STom Warren unsigned int enable; 38*6c43f6c8STom Warren 39*6c43f6c8STom Warren struct tegra_xusb_phy phys[2]; 40*6c43f6c8STom Warren }; 41*6c43f6c8STom Warren 42*6c43f6c8STom Warren static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, 43*6c43f6c8STom Warren unsigned long offset) 44*6c43f6c8STom Warren { 45*6c43f6c8STom Warren u32 value = readl(padctl->regs.start + offset); 46*6c43f6c8STom Warren debug("padctl: %08lx > %08x\n", offset, value); 47*6c43f6c8STom Warren return value; 48*6c43f6c8STom Warren } 49*6c43f6c8STom Warren 50*6c43f6c8STom Warren static inline void padctl_writel(struct tegra_xusb_padctl *padctl, 51*6c43f6c8STom Warren u32 value, unsigned long offset) 52*6c43f6c8STom Warren { 53*6c43f6c8STom Warren debug("padctl: %08lx < %08x\n", offset, value); 54*6c43f6c8STom Warren writel(value, padctl->regs.start + offset); 55*6c43f6c8STom Warren } 56*6c43f6c8STom Warren 57*6c43f6c8STom Warren #define XUSB_PADCTL_ELPG_PROGRAM 0x024 58*6c43f6c8STom Warren #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 31) 59*6c43f6c8STom Warren #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30) 60*6c43f6c8STom Warren #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 29) 61*6c43f6c8STom Warren 62*6c43f6c8STom Warren static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) 63*6c43f6c8STom Warren { 64*6c43f6c8STom Warren u32 value; 65*6c43f6c8STom Warren 66*6c43f6c8STom Warren if (padctl->enable++ > 0) 67*6c43f6c8STom Warren return 0; 68*6c43f6c8STom Warren 69*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 70*6c43f6c8STom Warren value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 71*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 72*6c43f6c8STom Warren 73*6c43f6c8STom Warren udelay(100); 74*6c43f6c8STom Warren 75*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 76*6c43f6c8STom Warren value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 77*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 78*6c43f6c8STom Warren 79*6c43f6c8STom Warren udelay(100); 80*6c43f6c8STom Warren 81*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 82*6c43f6c8STom Warren value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 83*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 84*6c43f6c8STom Warren 85*6c43f6c8STom Warren return 0; 86*6c43f6c8STom Warren } 87*6c43f6c8STom Warren 88*6c43f6c8STom Warren static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) 89*6c43f6c8STom Warren { 90*6c43f6c8STom Warren u32 value; 91*6c43f6c8STom Warren 92*6c43f6c8STom Warren if (padctl->enable == 0) { 93*6c43f6c8STom Warren error("unbalanced enable/disable"); 94*6c43f6c8STom Warren return 0; 95*6c43f6c8STom Warren } 96*6c43f6c8STom Warren 97*6c43f6c8STom Warren if (--padctl->enable > 0) 98*6c43f6c8STom Warren return 0; 99*6c43f6c8STom Warren 100*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 101*6c43f6c8STom Warren value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 102*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 103*6c43f6c8STom Warren 104*6c43f6c8STom Warren udelay(100); 105*6c43f6c8STom Warren 106*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 107*6c43f6c8STom Warren value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 108*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 109*6c43f6c8STom Warren 110*6c43f6c8STom Warren udelay(100); 111*6c43f6c8STom Warren 112*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 113*6c43f6c8STom Warren value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 114*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 115*6c43f6c8STom Warren 116*6c43f6c8STom Warren return 0; 117*6c43f6c8STom Warren } 118*6c43f6c8STom Warren 119*6c43f6c8STom Warren static int phy_prepare(struct tegra_xusb_phy *phy) 120*6c43f6c8STom Warren { 121*6c43f6c8STom Warren int err; 122*6c43f6c8STom Warren 123*6c43f6c8STom Warren err = tegra_xusb_padctl_enable(phy->padctl); 124*6c43f6c8STom Warren if (err < 0) 125*6c43f6c8STom Warren return err; 126*6c43f6c8STom Warren 127*6c43f6c8STom Warren reset_set_enable(PERIPH_ID_PEX_USB_UPHY, 0); 128*6c43f6c8STom Warren 129*6c43f6c8STom Warren return 0; 130*6c43f6c8STom Warren } 131*6c43f6c8STom Warren 132*6c43f6c8STom Warren static int phy_unprepare(struct tegra_xusb_phy *phy) 133*6c43f6c8STom Warren { 134*6c43f6c8STom Warren reset_set_enable(PERIPH_ID_PEX_USB_UPHY, 1); 135*6c43f6c8STom Warren 136*6c43f6c8STom Warren return tegra_xusb_padctl_disable(phy->padctl); 137*6c43f6c8STom Warren } 138*6c43f6c8STom Warren 139*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360 140*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV_MASK (0xff << 20) 141*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV(x) (((x) & 0xff) << 20) 142*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_MDIV_MASK (0x3 << 16) 143*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_LOCKDET_STATUS (1 << 15) 144*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_PWR_OVRD (1 << 4) 145*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_ENABLE (1 << 3) 146*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_SLEEP_MASK (0x3 << 1) 147*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_SLEEP(x) (((x) & 0x3) << 1) 148*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL1_IDDQ (1 << 0) 149*6c43f6c8STom Warren 150*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364 151*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_CTRL_MASK (0xffffff << 4) 152*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_CTRL(x) (((x) & 0xffffff) << 4) 153*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_OVRD (1 << 2) 154*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE (1 << 1) 155*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_EN (1 << 0) 156*6c43f6c8STom Warren 157*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c 158*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_EN (1 << 15) 159*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_SEL_MASK (0x3 << 12) 160*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_SEL(x) (((x) & 0x3) << 12) 161*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4_REFCLKBUF_EN (1 << 8) 162*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL4_REFCLK_SEL_MASK (0xf << 4) 163*6c43f6c8STom Warren 164*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370 165*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL5_DCO_CTRL_MASK (0xff << 16) 166*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL5_DCO_CTRL(x) (((x) & 0xff) << 16) 167*6c43f6c8STom Warren 168*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c 169*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE (1 << 31) 170*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_OVRD (1 << 15) 171*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_CLK_EN (1 << 13) 172*6c43f6c8STom Warren #define XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_EN (1 << 12) 173*6c43f6c8STom Warren 174*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0 0x51c 175*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0_SEQ_ENABLE (1 << 24) 176*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ (1 << 13) 177*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET (1 << 6) 178*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL (1 << 2) 179*6c43f6c8STom Warren #define CLK_RST_XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL (1 << 0) 180*6c43f6c8STom Warren 181*6c43f6c8STom Warren static int pcie_phy_enable(struct tegra_xusb_phy *phy) 182*6c43f6c8STom Warren { 183*6c43f6c8STom Warren struct tegra_xusb_padctl *padctl = phy->padctl; 184*6c43f6c8STom Warren unsigned long start; 185*6c43f6c8STom Warren u32 value; 186*6c43f6c8STom Warren 187*6c43f6c8STom Warren debug("> %s(phy=%p)\n", __func__, phy); 188*6c43f6c8STom Warren 189*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 190*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_CTRL_MASK; 191*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_CTRL(0x136); 192*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 193*6c43f6c8STom Warren 194*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 195*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL5_DCO_CTRL_MASK; 196*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL5_DCO_CTRL(0x2a); 197*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 198*6c43f6c8STom Warren 199*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 200*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL1_PWR_OVRD; 201*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 202*6c43f6c8STom Warren 203*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 204*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_OVRD; 205*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 206*6c43f6c8STom Warren 207*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 208*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_OVRD; 209*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 210*6c43f6c8STom Warren 211*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 212*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_SEL_MASK; 213*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL4_REFCLK_SEL_MASK; 214*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_SEL(2); 215*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL4_TXCLKREF_EN; 216*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 217*6c43f6c8STom Warren 218*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 219*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_MDIV_MASK; 220*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV_MASK; 221*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV(25); 222*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 223*6c43f6c8STom Warren 224*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 225*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_IDDQ; 226*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 227*6c43f6c8STom Warren 228*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 229*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_SLEEP_MASK; 230*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 231*6c43f6c8STom Warren 232*6c43f6c8STom Warren udelay(1); 233*6c43f6c8STom Warren 234*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 235*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL4_REFCLKBUF_EN; 236*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 237*6c43f6c8STom Warren 238*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 239*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_EN; 240*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 241*6c43f6c8STom Warren 242*6c43f6c8STom Warren debug(" waiting for calibration\n"); 243*6c43f6c8STom Warren 244*6c43f6c8STom Warren start = get_timer(0); 245*6c43f6c8STom Warren 246*6c43f6c8STom Warren while (get_timer(start) < 250) { 247*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 248*6c43f6c8STom Warren if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE) 249*6c43f6c8STom Warren break; 250*6c43f6c8STom Warren } 251*6c43f6c8STom Warren 252*6c43f6c8STom Warren debug(" done\n"); 253*6c43f6c8STom Warren 254*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 255*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_EN; 256*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 257*6c43f6c8STom Warren 258*6c43f6c8STom Warren debug(" waiting for calibration to stop\n"); 259*6c43f6c8STom Warren 260*6c43f6c8STom Warren start = get_timer(0); 261*6c43f6c8STom Warren 262*6c43f6c8STom Warren while (get_timer(start) < 250) { 263*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 264*6c43f6c8STom Warren if ((value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE) == 0) 265*6c43f6c8STom Warren break; 266*6c43f6c8STom Warren } 267*6c43f6c8STom Warren 268*6c43f6c8STom Warren debug(" done\n"); 269*6c43f6c8STom Warren 270*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 271*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL1_ENABLE; 272*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 273*6c43f6c8STom Warren 274*6c43f6c8STom Warren debug(" waiting for PLL to lock...\n"); 275*6c43f6c8STom Warren start = get_timer(0); 276*6c43f6c8STom Warren 277*6c43f6c8STom Warren while (get_timer(start) < 250) { 278*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 279*6c43f6c8STom Warren if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL1_LOCKDET_STATUS) 280*6c43f6c8STom Warren break; 281*6c43f6c8STom Warren } 282*6c43f6c8STom Warren 283*6c43f6c8STom Warren debug(" done\n"); 284*6c43f6c8STom Warren 285*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 286*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_CLK_EN; 287*6c43f6c8STom Warren value |= XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_EN; 288*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 289*6c43f6c8STom Warren 290*6c43f6c8STom Warren debug(" waiting for register calibration...\n"); 291*6c43f6c8STom Warren start = get_timer(0); 292*6c43f6c8STom Warren 293*6c43f6c8STom Warren while (get_timer(start) < 250) { 294*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 295*6c43f6c8STom Warren if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE) 296*6c43f6c8STom Warren break; 297*6c43f6c8STom Warren } 298*6c43f6c8STom Warren 299*6c43f6c8STom Warren debug(" done\n"); 300*6c43f6c8STom Warren 301*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 302*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_EN; 303*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 304*6c43f6c8STom Warren 305*6c43f6c8STom Warren debug(" waiting for register calibration to stop...\n"); 306*6c43f6c8STom Warren start = get_timer(0); 307*6c43f6c8STom Warren 308*6c43f6c8STom Warren while (get_timer(start) < 250) { 309*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 310*6c43f6c8STom Warren if ((value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE) == 0) 311*6c43f6c8STom Warren break; 312*6c43f6c8STom Warren } 313*6c43f6c8STom Warren 314*6c43f6c8STom Warren debug(" done\n"); 315*6c43f6c8STom Warren 316*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 317*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_CLK_EN; 318*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 319*6c43f6c8STom Warren 320*6c43f6c8STom Warren value = readl(NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0); 321*6c43f6c8STom Warren value &= ~CLK_RST_XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL; 322*6c43f6c8STom Warren value &= ~CLK_RST_XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL; 323*6c43f6c8STom Warren value |= CLK_RST_XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET; 324*6c43f6c8STom Warren value |= CLK_RST_XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ; 325*6c43f6c8STom Warren writel(value, NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0); 326*6c43f6c8STom Warren 327*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 328*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_PWR_OVRD; 329*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 330*6c43f6c8STom Warren 331*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 332*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_OVRD; 333*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 334*6c43f6c8STom Warren 335*6c43f6c8STom Warren value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 336*6c43f6c8STom Warren value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_OVRD; 337*6c43f6c8STom Warren padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 338*6c43f6c8STom Warren 339*6c43f6c8STom Warren udelay(1); 340*6c43f6c8STom Warren 341*6c43f6c8STom Warren value = readl(NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0); 342*6c43f6c8STom Warren value |= CLK_RST_XUSBIO_PLL_CFG0_SEQ_ENABLE; 343*6c43f6c8STom Warren writel(value, NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0); 344*6c43f6c8STom Warren 345*6c43f6c8STom Warren debug("< %s()\n", __func__); 346*6c43f6c8STom Warren return 0; 347*6c43f6c8STom Warren } 348*6c43f6c8STom Warren 349*6c43f6c8STom Warren static int pcie_phy_disable(struct tegra_xusb_phy *phy) 350*6c43f6c8STom Warren { 351*6c43f6c8STom Warren return 0; 352*6c43f6c8STom Warren } 353*6c43f6c8STom Warren 354*6c43f6c8STom Warren static const struct tegra_xusb_phy_ops pcie_phy_ops = { 355*6c43f6c8STom Warren .prepare = phy_prepare, 356*6c43f6c8STom Warren .enable = pcie_phy_enable, 357*6c43f6c8STom Warren .disable = pcie_phy_disable, 358*6c43f6c8STom Warren .unprepare = phy_unprepare, 359*6c43f6c8STom Warren }; 360*6c43f6c8STom Warren 361*6c43f6c8STom Warren static struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) { 362*6c43f6c8STom Warren .phys = { 363*6c43f6c8STom Warren [0] = { 364*6c43f6c8STom Warren .ops = &pcie_phy_ops, 365*6c43f6c8STom Warren }, 366*6c43f6c8STom Warren }, 367*6c43f6c8STom Warren }; 368*6c43f6c8STom Warren 369*6c43f6c8STom Warren static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl, 370*6c43f6c8STom Warren const void *fdt, int node) 371*6c43f6c8STom Warren { 372*6c43f6c8STom Warren int err; 373*6c43f6c8STom Warren 374*6c43f6c8STom Warren err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs); 375*6c43f6c8STom Warren if (err < 0) { 376*6c43f6c8STom Warren error("registers not found"); 377*6c43f6c8STom Warren return err; 378*6c43f6c8STom Warren } 379*6c43f6c8STom Warren 380*6c43f6c8STom Warren debug("regs: %pa-%pa\n", &padctl->regs.start, 381*6c43f6c8STom Warren &padctl->regs.end); 382*6c43f6c8STom Warren 383*6c43f6c8STom Warren return 0; 384*6c43f6c8STom Warren } 385*6c43f6c8STom Warren 386*6c43f6c8STom Warren static int process_nodes(const void *fdt, int nodes[], unsigned int count) 387*6c43f6c8STom Warren { 388*6c43f6c8STom Warren unsigned int i; 389*6c43f6c8STom Warren int err; 390*6c43f6c8STom Warren 391*6c43f6c8STom Warren debug("> %s(fdt=%p, nodes=%p, count=%u)\n", __func__, fdt, nodes, 392*6c43f6c8STom Warren count); 393*6c43f6c8STom Warren 394*6c43f6c8STom Warren for (i = 0; i < count; i++) { 395*6c43f6c8STom Warren enum fdt_compat_id id; 396*6c43f6c8STom Warren 397*6c43f6c8STom Warren if (!fdtdec_get_is_enabled(fdt, nodes[i])) 398*6c43f6c8STom Warren continue; 399*6c43f6c8STom Warren 400*6c43f6c8STom Warren id = fdtdec_lookup(fdt, nodes[i]); 401*6c43f6c8STom Warren switch (id) { 402*6c43f6c8STom Warren case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL: 403*6c43f6c8STom Warren case COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL: 404*6c43f6c8STom Warren break; 405*6c43f6c8STom Warren 406*6c43f6c8STom Warren default: 407*6c43f6c8STom Warren error("unsupported compatible: %s", 408*6c43f6c8STom Warren fdtdec_get_compatible(id)); 409*6c43f6c8STom Warren continue; 410*6c43f6c8STom Warren } 411*6c43f6c8STom Warren 412*6c43f6c8STom Warren err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]); 413*6c43f6c8STom Warren if (err < 0) { 414*6c43f6c8STom Warren error("failed to parse DT: %d", 415*6c43f6c8STom Warren err); 416*6c43f6c8STom Warren continue; 417*6c43f6c8STom Warren } 418*6c43f6c8STom Warren 419*6c43f6c8STom Warren /* deassert XUSB padctl reset */ 420*6c43f6c8STom Warren reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0); 421*6c43f6c8STom Warren 422*6c43f6c8STom Warren /* only a single instance is supported */ 423*6c43f6c8STom Warren break; 424*6c43f6c8STom Warren } 425*6c43f6c8STom Warren 426*6c43f6c8STom Warren debug("< %s()\n", __func__); 427*6c43f6c8STom Warren return 0; 428*6c43f6c8STom Warren } 429*6c43f6c8STom Warren 430*6c43f6c8STom Warren struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type) 431*6c43f6c8STom Warren { 432*6c43f6c8STom Warren struct tegra_xusb_phy *phy = NULL; 433*6c43f6c8STom Warren 434*6c43f6c8STom Warren switch (type) { 435*6c43f6c8STom Warren case TEGRA_XUSB_PADCTL_PCIE: 436*6c43f6c8STom Warren phy = &padctl->phys[0]; 437*6c43f6c8STom Warren phy->padctl = padctl; 438*6c43f6c8STom Warren break; 439*6c43f6c8STom Warren } 440*6c43f6c8STom Warren 441*6c43f6c8STom Warren return phy; 442*6c43f6c8STom Warren } 443*6c43f6c8STom Warren 444*6c43f6c8STom Warren int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy) 445*6c43f6c8STom Warren { 446*6c43f6c8STom Warren if (phy && phy->ops && phy->ops->prepare) 447*6c43f6c8STom Warren return phy->ops->prepare(phy); 448*6c43f6c8STom Warren 449*6c43f6c8STom Warren return phy ? -ENOSYS : -EINVAL; 450*6c43f6c8STom Warren } 451*6c43f6c8STom Warren 452*6c43f6c8STom Warren int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy) 453*6c43f6c8STom Warren { 454*6c43f6c8STom Warren if (phy && phy->ops && phy->ops->enable) 455*6c43f6c8STom Warren return phy->ops->enable(phy); 456*6c43f6c8STom Warren 457*6c43f6c8STom Warren return phy ? -ENOSYS : -EINVAL; 458*6c43f6c8STom Warren } 459*6c43f6c8STom Warren 460*6c43f6c8STom Warren int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy) 461*6c43f6c8STom Warren { 462*6c43f6c8STom Warren if (phy && phy->ops && phy->ops->disable) 463*6c43f6c8STom Warren return phy->ops->disable(phy); 464*6c43f6c8STom Warren 465*6c43f6c8STom Warren return phy ? -ENOSYS : -EINVAL; 466*6c43f6c8STom Warren } 467*6c43f6c8STom Warren 468*6c43f6c8STom Warren int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy) 469*6c43f6c8STom Warren { 470*6c43f6c8STom Warren if (phy && phy->ops && phy->ops->unprepare) 471*6c43f6c8STom Warren return phy->ops->unprepare(phy); 472*6c43f6c8STom Warren 473*6c43f6c8STom Warren return phy ? -ENOSYS : -EINVAL; 474*6c43f6c8STom Warren } 475*6c43f6c8STom Warren 476*6c43f6c8STom Warren void tegra_xusb_padctl_init(const void *fdt) 477*6c43f6c8STom Warren { 478*6c43f6c8STom Warren int count, nodes[1]; 479*6c43f6c8STom Warren 480*6c43f6c8STom Warren debug("> %s(fdt=%p)\n", __func__, fdt); 481*6c43f6c8STom Warren 482*6c43f6c8STom Warren count = fdtdec_find_aliases_for_id(fdt, "padctl", 483*6c43f6c8STom Warren COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL, 484*6c43f6c8STom Warren nodes, ARRAY_SIZE(nodes)); 485*6c43f6c8STom Warren if (process_nodes(fdt, nodes, count)) 486*6c43f6c8STom Warren return; 487*6c43f6c8STom Warren 488*6c43f6c8STom Warren count = fdtdec_find_aliases_for_id(fdt, "padctl", 489*6c43f6c8STom Warren COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, 490*6c43f6c8STom Warren nodes, ARRAY_SIZE(nodes)); 491*6c43f6c8STom Warren if (process_nodes(fdt, nodes, count)) 492*6c43f6c8STom Warren return; 493*6c43f6c8STom Warren 494*6c43f6c8STom Warren debug("< %s()\n", __func__); 495*6c43f6c8STom Warren } 496