xref: /rk3399_rockchip-uboot/arch/arm/mach-tegra/tegra210/xusb-padctl.c (revision 6c43f6c8d920caa1db01f5d0571a4d9ba720be15)
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