xref: /rk3399_rockchip-uboot/arch/arm/mach-tegra/tegra124/xusb-padctl.c (revision 09f455dca74973ef5e42311162c8dff7e83d44a2)
1*09f455dcSMasahiro Yamada /*
2*09f455dcSMasahiro Yamada  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
3*09f455dcSMasahiro Yamada  *
4*09f455dcSMasahiro Yamada  * SPDX-License-Identifier: GPL-2.0
5*09f455dcSMasahiro Yamada  */
6*09f455dcSMasahiro Yamada 
7*09f455dcSMasahiro Yamada #define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
8*09f455dcSMasahiro Yamada 
9*09f455dcSMasahiro Yamada #include <common.h>
10*09f455dcSMasahiro Yamada #include <errno.h>
11*09f455dcSMasahiro Yamada #include <fdtdec.h>
12*09f455dcSMasahiro Yamada #include <malloc.h>
13*09f455dcSMasahiro Yamada 
14*09f455dcSMasahiro Yamada #include <asm/io.h>
15*09f455dcSMasahiro Yamada 
16*09f455dcSMasahiro Yamada #include <asm/arch/clock.h>
17*09f455dcSMasahiro Yamada #include <asm/arch-tegra/xusb-padctl.h>
18*09f455dcSMasahiro Yamada 
19*09f455dcSMasahiro Yamada #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
20*09f455dcSMasahiro Yamada 
21*09f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
22*09f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
23*09f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
24*09f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
25*09f455dcSMasahiro Yamada 
26*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
27*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
28*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
29*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
30*09f455dcSMasahiro Yamada 
31*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
32*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
33*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
34*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
35*09f455dcSMasahiro Yamada 
36*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
37*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
38*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
39*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
40*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
41*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
42*09f455dcSMasahiro Yamada 
43*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
44*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
45*09f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
46*09f455dcSMasahiro Yamada 
47*09f455dcSMasahiro Yamada enum tegra124_function {
48*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
49*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
50*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_UART,
51*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_PCIE,
52*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_USB3,
53*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_SATA,
54*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
55*09f455dcSMasahiro Yamada };
56*09f455dcSMasahiro Yamada 
57*09f455dcSMasahiro Yamada static const char *const tegra124_functions[] = {
58*09f455dcSMasahiro Yamada 	"snps",
59*09f455dcSMasahiro Yamada 	"xusb",
60*09f455dcSMasahiro Yamada 	"uart",
61*09f455dcSMasahiro Yamada 	"pcie",
62*09f455dcSMasahiro Yamada 	"usb3",
63*09f455dcSMasahiro Yamada 	"sata",
64*09f455dcSMasahiro Yamada 	"rsvd",
65*09f455dcSMasahiro Yamada };
66*09f455dcSMasahiro Yamada 
67*09f455dcSMasahiro Yamada static const unsigned int tegra124_otg_functions[] = {
68*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
69*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
70*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_UART,
71*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
72*09f455dcSMasahiro Yamada };
73*09f455dcSMasahiro Yamada 
74*09f455dcSMasahiro Yamada static const unsigned int tegra124_usb_functions[] = {
75*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
76*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
77*09f455dcSMasahiro Yamada };
78*09f455dcSMasahiro Yamada 
79*09f455dcSMasahiro Yamada static const unsigned int tegra124_pci_functions[] = {
80*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_PCIE,
81*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_USB3,
82*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_SATA,
83*09f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
84*09f455dcSMasahiro Yamada };
85*09f455dcSMasahiro Yamada 
86*09f455dcSMasahiro Yamada struct tegra_xusb_padctl_lane {
87*09f455dcSMasahiro Yamada 	const char *name;
88*09f455dcSMasahiro Yamada 
89*09f455dcSMasahiro Yamada 	unsigned int offset;
90*09f455dcSMasahiro Yamada 	unsigned int shift;
91*09f455dcSMasahiro Yamada 	unsigned int mask;
92*09f455dcSMasahiro Yamada 	unsigned int iddq;
93*09f455dcSMasahiro Yamada 
94*09f455dcSMasahiro Yamada 	const unsigned int *funcs;
95*09f455dcSMasahiro Yamada 	unsigned int num_funcs;
96*09f455dcSMasahiro Yamada };
97*09f455dcSMasahiro Yamada 
98*09f455dcSMasahiro Yamada #define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
99*09f455dcSMasahiro Yamada 	{								\
100*09f455dcSMasahiro Yamada 		.name = _name,						\
101*09f455dcSMasahiro Yamada 		.offset = _offset,					\
102*09f455dcSMasahiro Yamada 		.shift = _shift,					\
103*09f455dcSMasahiro Yamada 		.mask = _mask,						\
104*09f455dcSMasahiro Yamada 		.iddq = _iddq,						\
105*09f455dcSMasahiro Yamada 		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
106*09f455dcSMasahiro Yamada 		.funcs = tegra124_##_funcs##_functions,			\
107*09f455dcSMasahiro Yamada 	}
108*09f455dcSMasahiro Yamada 
109*09f455dcSMasahiro Yamada static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
110*09f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
111*09f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
112*09f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
113*09f455dcSMasahiro Yamada 	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
114*09f455dcSMasahiro Yamada 	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
115*09f455dcSMasahiro Yamada 	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
116*09f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
117*09f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
118*09f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
119*09f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
120*09f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
121*09f455dcSMasahiro Yamada 	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
122*09f455dcSMasahiro Yamada };
123*09f455dcSMasahiro Yamada 
124*09f455dcSMasahiro Yamada struct tegra_xusb_phy_ops {
125*09f455dcSMasahiro Yamada 	int (*prepare)(struct tegra_xusb_phy *phy);
126*09f455dcSMasahiro Yamada 	int (*enable)(struct tegra_xusb_phy *phy);
127*09f455dcSMasahiro Yamada 	int (*disable)(struct tegra_xusb_phy *phy);
128*09f455dcSMasahiro Yamada 	int (*unprepare)(struct tegra_xusb_phy *phy);
129*09f455dcSMasahiro Yamada };
130*09f455dcSMasahiro Yamada 
131*09f455dcSMasahiro Yamada struct tegra_xusb_phy {
132*09f455dcSMasahiro Yamada 	const struct tegra_xusb_phy_ops *ops;
133*09f455dcSMasahiro Yamada 
134*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl;
135*09f455dcSMasahiro Yamada };
136*09f455dcSMasahiro Yamada 
137*09f455dcSMasahiro Yamada struct tegra_xusb_padctl_pin {
138*09f455dcSMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lane;
139*09f455dcSMasahiro Yamada 
140*09f455dcSMasahiro Yamada 	unsigned int func;
141*09f455dcSMasahiro Yamada 	int iddq;
142*09f455dcSMasahiro Yamada };
143*09f455dcSMasahiro Yamada 
144*09f455dcSMasahiro Yamada #define MAX_GROUPS 3
145*09f455dcSMasahiro Yamada #define MAX_PINS 6
146*09f455dcSMasahiro Yamada 
147*09f455dcSMasahiro Yamada struct tegra_xusb_padctl_group {
148*09f455dcSMasahiro Yamada 	const char *name;
149*09f455dcSMasahiro Yamada 
150*09f455dcSMasahiro Yamada 	const char *pins[MAX_PINS];
151*09f455dcSMasahiro Yamada 	unsigned int num_pins;
152*09f455dcSMasahiro Yamada 
153*09f455dcSMasahiro Yamada 	const char *func;
154*09f455dcSMasahiro Yamada 	int iddq;
155*09f455dcSMasahiro Yamada };
156*09f455dcSMasahiro Yamada 
157*09f455dcSMasahiro Yamada struct tegra_xusb_padctl_config {
158*09f455dcSMasahiro Yamada 	const char *name;
159*09f455dcSMasahiro Yamada 
160*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl_group groups[MAX_GROUPS];
161*09f455dcSMasahiro Yamada 	unsigned int num_groups;
162*09f455dcSMasahiro Yamada };
163*09f455dcSMasahiro Yamada 
164*09f455dcSMasahiro Yamada struct tegra_xusb_padctl {
165*09f455dcSMasahiro Yamada 	struct fdt_resource regs;
166*09f455dcSMasahiro Yamada 
167*09f455dcSMasahiro Yamada 	unsigned int enable;
168*09f455dcSMasahiro Yamada 
169*09f455dcSMasahiro Yamada 	struct tegra_xusb_phy phys[2];
170*09f455dcSMasahiro Yamada 
171*09f455dcSMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lanes;
172*09f455dcSMasahiro Yamada 	unsigned int num_lanes;
173*09f455dcSMasahiro Yamada 
174*09f455dcSMasahiro Yamada 	const char *const *functions;
175*09f455dcSMasahiro Yamada 	unsigned int num_functions;
176*09f455dcSMasahiro Yamada 
177*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl_config config;
178*09f455dcSMasahiro Yamada };
179*09f455dcSMasahiro Yamada 
180*09f455dcSMasahiro Yamada static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
181*09f455dcSMasahiro Yamada 			       unsigned long offset)
182*09f455dcSMasahiro Yamada {
183*09f455dcSMasahiro Yamada 	return readl(padctl->regs.start + offset);
184*09f455dcSMasahiro Yamada }
185*09f455dcSMasahiro Yamada 
186*09f455dcSMasahiro Yamada static inline void padctl_writel(struct tegra_xusb_padctl *padctl,
187*09f455dcSMasahiro Yamada 				 u32 value, unsigned long offset)
188*09f455dcSMasahiro Yamada {
189*09f455dcSMasahiro Yamada 	writel(value, padctl->regs.start + offset);
190*09f455dcSMasahiro Yamada }
191*09f455dcSMasahiro Yamada 
192*09f455dcSMasahiro Yamada static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
193*09f455dcSMasahiro Yamada {
194*09f455dcSMasahiro Yamada 	u32 value;
195*09f455dcSMasahiro Yamada 
196*09f455dcSMasahiro Yamada 	if (padctl->enable++ > 0)
197*09f455dcSMasahiro Yamada 		return 0;
198*09f455dcSMasahiro Yamada 
199*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
200*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
201*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
202*09f455dcSMasahiro Yamada 
203*09f455dcSMasahiro Yamada 	udelay(100);
204*09f455dcSMasahiro Yamada 
205*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
206*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
207*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
208*09f455dcSMasahiro Yamada 
209*09f455dcSMasahiro Yamada 	udelay(100);
210*09f455dcSMasahiro Yamada 
211*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
212*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
213*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
214*09f455dcSMasahiro Yamada 
215*09f455dcSMasahiro Yamada 	return 0;
216*09f455dcSMasahiro Yamada }
217*09f455dcSMasahiro Yamada 
218*09f455dcSMasahiro Yamada static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
219*09f455dcSMasahiro Yamada {
220*09f455dcSMasahiro Yamada 	u32 value;
221*09f455dcSMasahiro Yamada 
222*09f455dcSMasahiro Yamada 	if (padctl->enable == 0) {
223*09f455dcSMasahiro Yamada 		error("tegra-xusb-padctl: unbalanced enable/disable");
224*09f455dcSMasahiro Yamada 		return 0;
225*09f455dcSMasahiro Yamada 	}
226*09f455dcSMasahiro Yamada 
227*09f455dcSMasahiro Yamada 	if (--padctl->enable > 0)
228*09f455dcSMasahiro Yamada 		return 0;
229*09f455dcSMasahiro Yamada 
230*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
231*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
232*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
233*09f455dcSMasahiro Yamada 
234*09f455dcSMasahiro Yamada 	udelay(100);
235*09f455dcSMasahiro Yamada 
236*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
237*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
238*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
239*09f455dcSMasahiro Yamada 
240*09f455dcSMasahiro Yamada 	udelay(100);
241*09f455dcSMasahiro Yamada 
242*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
243*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
244*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
245*09f455dcSMasahiro Yamada 
246*09f455dcSMasahiro Yamada 	return 0;
247*09f455dcSMasahiro Yamada }
248*09f455dcSMasahiro Yamada 
249*09f455dcSMasahiro Yamada static int phy_prepare(struct tegra_xusb_phy *phy)
250*09f455dcSMasahiro Yamada {
251*09f455dcSMasahiro Yamada 	return tegra_xusb_padctl_enable(phy->padctl);
252*09f455dcSMasahiro Yamada }
253*09f455dcSMasahiro Yamada 
254*09f455dcSMasahiro Yamada static int phy_unprepare(struct tegra_xusb_phy *phy)
255*09f455dcSMasahiro Yamada {
256*09f455dcSMasahiro Yamada 	return tegra_xusb_padctl_disable(phy->padctl);
257*09f455dcSMasahiro Yamada }
258*09f455dcSMasahiro Yamada 
259*09f455dcSMasahiro Yamada static int pcie_phy_enable(struct tegra_xusb_phy *phy)
260*09f455dcSMasahiro Yamada {
261*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
262*09f455dcSMasahiro Yamada 	int err = -ETIMEDOUT;
263*09f455dcSMasahiro Yamada 	unsigned long start;
264*09f455dcSMasahiro Yamada 	u32 value;
265*09f455dcSMasahiro Yamada 
266*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
267*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
268*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
269*09f455dcSMasahiro Yamada 
270*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
271*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
272*09f455dcSMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
273*09f455dcSMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
274*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
275*09f455dcSMasahiro Yamada 
276*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
277*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
278*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
279*09f455dcSMasahiro Yamada 
280*09f455dcSMasahiro Yamada 	start = get_timer(0);
281*09f455dcSMasahiro Yamada 
282*09f455dcSMasahiro Yamada 	while (get_timer(start) < 50) {
283*09f455dcSMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
284*09f455dcSMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
285*09f455dcSMasahiro Yamada 			err = 0;
286*09f455dcSMasahiro Yamada 			break;
287*09f455dcSMasahiro Yamada 		}
288*09f455dcSMasahiro Yamada 	}
289*09f455dcSMasahiro Yamada 
290*09f455dcSMasahiro Yamada 	return err;
291*09f455dcSMasahiro Yamada }
292*09f455dcSMasahiro Yamada 
293*09f455dcSMasahiro Yamada static int pcie_phy_disable(struct tegra_xusb_phy *phy)
294*09f455dcSMasahiro Yamada {
295*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
296*09f455dcSMasahiro Yamada 	u32 value;
297*09f455dcSMasahiro Yamada 
298*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
299*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
300*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
301*09f455dcSMasahiro Yamada 
302*09f455dcSMasahiro Yamada 	return 0;
303*09f455dcSMasahiro Yamada }
304*09f455dcSMasahiro Yamada 
305*09f455dcSMasahiro Yamada static int sata_phy_enable(struct tegra_xusb_phy *phy)
306*09f455dcSMasahiro Yamada {
307*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
308*09f455dcSMasahiro Yamada 	int err = -ETIMEDOUT;
309*09f455dcSMasahiro Yamada 	unsigned long start;
310*09f455dcSMasahiro Yamada 	u32 value;
311*09f455dcSMasahiro Yamada 
312*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
313*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
314*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
315*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
316*09f455dcSMasahiro Yamada 
317*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
318*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
319*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
320*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
321*09f455dcSMasahiro Yamada 
322*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
323*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
324*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
325*09f455dcSMasahiro Yamada 
326*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
327*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
328*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
329*09f455dcSMasahiro Yamada 
330*09f455dcSMasahiro Yamada 	start = get_timer(0);
331*09f455dcSMasahiro Yamada 
332*09f455dcSMasahiro Yamada 	while (get_timer(start) < 50) {
333*09f455dcSMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
334*09f455dcSMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
335*09f455dcSMasahiro Yamada 			err = 0;
336*09f455dcSMasahiro Yamada 			break;
337*09f455dcSMasahiro Yamada 		}
338*09f455dcSMasahiro Yamada 	}
339*09f455dcSMasahiro Yamada 
340*09f455dcSMasahiro Yamada 	return err;
341*09f455dcSMasahiro Yamada }
342*09f455dcSMasahiro Yamada 
343*09f455dcSMasahiro Yamada static int sata_phy_disable(struct tegra_xusb_phy *phy)
344*09f455dcSMasahiro Yamada {
345*09f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
346*09f455dcSMasahiro Yamada 	u32 value;
347*09f455dcSMasahiro Yamada 
348*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
349*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
350*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
351*09f455dcSMasahiro Yamada 
352*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
353*09f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
354*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
355*09f455dcSMasahiro Yamada 
356*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
357*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
358*09f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
359*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
360*09f455dcSMasahiro Yamada 
361*09f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
362*09f455dcSMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
363*09f455dcSMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
364*09f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
365*09f455dcSMasahiro Yamada 
366*09f455dcSMasahiro Yamada 	return 0;
367*09f455dcSMasahiro Yamada }
368*09f455dcSMasahiro Yamada 
369*09f455dcSMasahiro Yamada static const struct tegra_xusb_phy_ops pcie_phy_ops = {
370*09f455dcSMasahiro Yamada 	.prepare = phy_prepare,
371*09f455dcSMasahiro Yamada 	.enable = pcie_phy_enable,
372*09f455dcSMasahiro Yamada 	.disable = pcie_phy_disable,
373*09f455dcSMasahiro Yamada 	.unprepare = phy_unprepare,
374*09f455dcSMasahiro Yamada };
375*09f455dcSMasahiro Yamada 
376*09f455dcSMasahiro Yamada static const struct tegra_xusb_phy_ops sata_phy_ops = {
377*09f455dcSMasahiro Yamada 	.prepare = phy_prepare,
378*09f455dcSMasahiro Yamada 	.enable = sata_phy_enable,
379*09f455dcSMasahiro Yamada 	.disable = sata_phy_disable,
380*09f455dcSMasahiro Yamada 	.unprepare = phy_unprepare,
381*09f455dcSMasahiro Yamada };
382*09f455dcSMasahiro Yamada 
383*09f455dcSMasahiro Yamada static struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) {
384*09f455dcSMasahiro Yamada 	.phys = {
385*09f455dcSMasahiro Yamada 		[0] = {
386*09f455dcSMasahiro Yamada 			.ops = &pcie_phy_ops,
387*09f455dcSMasahiro Yamada 		},
388*09f455dcSMasahiro Yamada 		[1] = {
389*09f455dcSMasahiro Yamada 			.ops = &sata_phy_ops,
390*09f455dcSMasahiro Yamada 		},
391*09f455dcSMasahiro Yamada 	},
392*09f455dcSMasahiro Yamada };
393*09f455dcSMasahiro Yamada 
394*09f455dcSMasahiro Yamada static const struct tegra_xusb_padctl_lane *
395*09f455dcSMasahiro Yamada tegra_xusb_padctl_find_lane(struct tegra_xusb_padctl *padctl, const char *name)
396*09f455dcSMasahiro Yamada {
397*09f455dcSMasahiro Yamada 	unsigned int i;
398*09f455dcSMasahiro Yamada 
399*09f455dcSMasahiro Yamada 	for (i = 0; i < padctl->num_lanes; i++)
400*09f455dcSMasahiro Yamada 		if (strcmp(name, padctl->lanes[i].name) == 0)
401*09f455dcSMasahiro Yamada 			return &padctl->lanes[i];
402*09f455dcSMasahiro Yamada 
403*09f455dcSMasahiro Yamada 	return NULL;
404*09f455dcSMasahiro Yamada }
405*09f455dcSMasahiro Yamada 
406*09f455dcSMasahiro Yamada static int
407*09f455dcSMasahiro Yamada tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
408*09f455dcSMasahiro Yamada 				 struct tegra_xusb_padctl_group *group,
409*09f455dcSMasahiro Yamada 				 const void *fdt, int node)
410*09f455dcSMasahiro Yamada {
411*09f455dcSMasahiro Yamada 	unsigned int i;
412*09f455dcSMasahiro Yamada 	int len, err;
413*09f455dcSMasahiro Yamada 
414*09f455dcSMasahiro Yamada 	group->name = fdt_get_name(fdt, node, &len);
415*09f455dcSMasahiro Yamada 
416*09f455dcSMasahiro Yamada 	len = fdt_count_strings(fdt, node, "nvidia,lanes");
417*09f455dcSMasahiro Yamada 	if (len < 0) {
418*09f455dcSMasahiro Yamada 		error("tegra-xusb-padctl: failed to parse \"nvidia,lanes\" property");
419*09f455dcSMasahiro Yamada 		return -EINVAL;
420*09f455dcSMasahiro Yamada 	}
421*09f455dcSMasahiro Yamada 
422*09f455dcSMasahiro Yamada 	group->num_pins = len;
423*09f455dcSMasahiro Yamada 
424*09f455dcSMasahiro Yamada 	for (i = 0; i < group->num_pins; i++) {
425*09f455dcSMasahiro Yamada 		err = fdt_get_string_index(fdt, node, "nvidia,lanes", i,
426*09f455dcSMasahiro Yamada 					   &group->pins[i]);
427*09f455dcSMasahiro Yamada 		if (err < 0) {
428*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to read string from \"nvidia,lanes\" property");
429*09f455dcSMasahiro Yamada 			return -EINVAL;
430*09f455dcSMasahiro Yamada 		}
431*09f455dcSMasahiro Yamada 	}
432*09f455dcSMasahiro Yamada 
433*09f455dcSMasahiro Yamada 	group->num_pins = len;
434*09f455dcSMasahiro Yamada 
435*09f455dcSMasahiro Yamada 	err = fdt_get_string(fdt, node, "nvidia,function", &group->func);
436*09f455dcSMasahiro Yamada 	if (err < 0) {
437*09f455dcSMasahiro Yamada 		error("tegra-xusb-padctl: failed to parse \"nvidia,func\" property");
438*09f455dcSMasahiro Yamada 		return -EINVAL;
439*09f455dcSMasahiro Yamada 	}
440*09f455dcSMasahiro Yamada 
441*09f455dcSMasahiro Yamada 	group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1);
442*09f455dcSMasahiro Yamada 
443*09f455dcSMasahiro Yamada 	return 0;
444*09f455dcSMasahiro Yamada }
445*09f455dcSMasahiro Yamada 
446*09f455dcSMasahiro Yamada static int tegra_xusb_padctl_find_function(struct tegra_xusb_padctl *padctl,
447*09f455dcSMasahiro Yamada 					   const char *name)
448*09f455dcSMasahiro Yamada {
449*09f455dcSMasahiro Yamada 	unsigned int i;
450*09f455dcSMasahiro Yamada 
451*09f455dcSMasahiro Yamada 	for (i = 0; i < padctl->num_functions; i++)
452*09f455dcSMasahiro Yamada 		if (strcmp(name, padctl->functions[i]) == 0)
453*09f455dcSMasahiro Yamada 			return i;
454*09f455dcSMasahiro Yamada 
455*09f455dcSMasahiro Yamada 	return -ENOENT;
456*09f455dcSMasahiro Yamada }
457*09f455dcSMasahiro Yamada 
458*09f455dcSMasahiro Yamada static int
459*09f455dcSMasahiro Yamada tegra_xusb_padctl_lane_find_function(struct tegra_xusb_padctl *padctl,
460*09f455dcSMasahiro Yamada 				     const struct tegra_xusb_padctl_lane *lane,
461*09f455dcSMasahiro Yamada 				     const char *name)
462*09f455dcSMasahiro Yamada {
463*09f455dcSMasahiro Yamada 	unsigned int i;
464*09f455dcSMasahiro Yamada 	int func;
465*09f455dcSMasahiro Yamada 
466*09f455dcSMasahiro Yamada 	func = tegra_xusb_padctl_find_function(padctl, name);
467*09f455dcSMasahiro Yamada 	if (func < 0)
468*09f455dcSMasahiro Yamada 		return func;
469*09f455dcSMasahiro Yamada 
470*09f455dcSMasahiro Yamada 	for (i = 0; i < lane->num_funcs; i++)
471*09f455dcSMasahiro Yamada 		if (lane->funcs[i] == func)
472*09f455dcSMasahiro Yamada 			return i;
473*09f455dcSMasahiro Yamada 
474*09f455dcSMasahiro Yamada 	return -ENOENT;
475*09f455dcSMasahiro Yamada }
476*09f455dcSMasahiro Yamada 
477*09f455dcSMasahiro Yamada static int
478*09f455dcSMasahiro Yamada tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl,
479*09f455dcSMasahiro Yamada 			      const struct tegra_xusb_padctl_group *group)
480*09f455dcSMasahiro Yamada {
481*09f455dcSMasahiro Yamada 	unsigned int i;
482*09f455dcSMasahiro Yamada 
483*09f455dcSMasahiro Yamada 	for (i = 0; i < group->num_pins; i++) {
484*09f455dcSMasahiro Yamada 		const struct tegra_xusb_padctl_lane *lane;
485*09f455dcSMasahiro Yamada 		unsigned int func;
486*09f455dcSMasahiro Yamada 		u32 value;
487*09f455dcSMasahiro Yamada 
488*09f455dcSMasahiro Yamada 		lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]);
489*09f455dcSMasahiro Yamada 		if (!lane) {
490*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: no lane for pin %s",
491*09f455dcSMasahiro Yamada 			      group->pins[i]);
492*09f455dcSMasahiro Yamada 			continue;
493*09f455dcSMasahiro Yamada 		}
494*09f455dcSMasahiro Yamada 
495*09f455dcSMasahiro Yamada 		func = tegra_xusb_padctl_lane_find_function(padctl, lane,
496*09f455dcSMasahiro Yamada 							    group->func);
497*09f455dcSMasahiro Yamada 		if (func < 0) {
498*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: function %s invalid for lane %s: %d",
499*09f455dcSMasahiro Yamada 			      group->func, lane->name, func);
500*09f455dcSMasahiro Yamada 			continue;
501*09f455dcSMasahiro Yamada 		}
502*09f455dcSMasahiro Yamada 
503*09f455dcSMasahiro Yamada 		value = padctl_readl(padctl, lane->offset);
504*09f455dcSMasahiro Yamada 
505*09f455dcSMasahiro Yamada 		/* set pin function */
506*09f455dcSMasahiro Yamada 		value &= ~(lane->mask << lane->shift);
507*09f455dcSMasahiro Yamada 		value |= func << lane->shift;
508*09f455dcSMasahiro Yamada 
509*09f455dcSMasahiro Yamada 		/*
510*09f455dcSMasahiro Yamada 		 * Set IDDQ if supported on the lane and specified in the
511*09f455dcSMasahiro Yamada 		 * configuration.
512*09f455dcSMasahiro Yamada 		 */
513*09f455dcSMasahiro Yamada 		if (lane->iddq > 0 && group->iddq >= 0) {
514*09f455dcSMasahiro Yamada 			if (group->iddq != 0)
515*09f455dcSMasahiro Yamada 				value &= ~(1 << lane->iddq);
516*09f455dcSMasahiro Yamada 			else
517*09f455dcSMasahiro Yamada 				value |= 1 << lane->iddq;
518*09f455dcSMasahiro Yamada 		}
519*09f455dcSMasahiro Yamada 
520*09f455dcSMasahiro Yamada 		padctl_writel(padctl, value, lane->offset);
521*09f455dcSMasahiro Yamada 	}
522*09f455dcSMasahiro Yamada 
523*09f455dcSMasahiro Yamada 	return 0;
524*09f455dcSMasahiro Yamada }
525*09f455dcSMasahiro Yamada 
526*09f455dcSMasahiro Yamada static int
527*09f455dcSMasahiro Yamada tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl,
528*09f455dcSMasahiro Yamada 			       struct tegra_xusb_padctl_config *config)
529*09f455dcSMasahiro Yamada {
530*09f455dcSMasahiro Yamada 	unsigned int i;
531*09f455dcSMasahiro Yamada 
532*09f455dcSMasahiro Yamada 	for (i = 0; i < config->num_groups; i++) {
533*09f455dcSMasahiro Yamada 		const struct tegra_xusb_padctl_group *group;
534*09f455dcSMasahiro Yamada 		int err;
535*09f455dcSMasahiro Yamada 
536*09f455dcSMasahiro Yamada 		group = &config->groups[i];
537*09f455dcSMasahiro Yamada 
538*09f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_group_apply(padctl, group);
539*09f455dcSMasahiro Yamada 		if (err < 0) {
540*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to apply group %s: %d",
541*09f455dcSMasahiro Yamada 			      group->name, err);
542*09f455dcSMasahiro Yamada 			continue;
543*09f455dcSMasahiro Yamada 		}
544*09f455dcSMasahiro Yamada 	}
545*09f455dcSMasahiro Yamada 
546*09f455dcSMasahiro Yamada 	return 0;
547*09f455dcSMasahiro Yamada }
548*09f455dcSMasahiro Yamada 
549*09f455dcSMasahiro Yamada static int
550*09f455dcSMasahiro Yamada tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
551*09f455dcSMasahiro Yamada 				  struct tegra_xusb_padctl_config *config,
552*09f455dcSMasahiro Yamada 				  const void *fdt, int node)
553*09f455dcSMasahiro Yamada {
554*09f455dcSMasahiro Yamada 	int subnode;
555*09f455dcSMasahiro Yamada 
556*09f455dcSMasahiro Yamada 	config->name = fdt_get_name(fdt, node, NULL);
557*09f455dcSMasahiro Yamada 
558*09f455dcSMasahiro Yamada 	fdt_for_each_subnode(fdt, subnode, node) {
559*09f455dcSMasahiro Yamada 		struct tegra_xusb_padctl_group *group;
560*09f455dcSMasahiro Yamada 		int err;
561*09f455dcSMasahiro Yamada 
562*09f455dcSMasahiro Yamada 		group = &config->groups[config->num_groups];
563*09f455dcSMasahiro Yamada 
564*09f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt,
565*09f455dcSMasahiro Yamada 						       subnode);
566*09f455dcSMasahiro Yamada 		if (err < 0) {
567*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to parse group %s",
568*09f455dcSMasahiro Yamada 			      group->name);
569*09f455dcSMasahiro Yamada 			return err;
570*09f455dcSMasahiro Yamada 		}
571*09f455dcSMasahiro Yamada 
572*09f455dcSMasahiro Yamada 		config->num_groups++;
573*09f455dcSMasahiro Yamada 	}
574*09f455dcSMasahiro Yamada 
575*09f455dcSMasahiro Yamada 	return 0;
576*09f455dcSMasahiro Yamada }
577*09f455dcSMasahiro Yamada 
578*09f455dcSMasahiro Yamada static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
579*09f455dcSMasahiro Yamada 				      const void *fdt, int node)
580*09f455dcSMasahiro Yamada {
581*09f455dcSMasahiro Yamada 	int subnode, err;
582*09f455dcSMasahiro Yamada 
583*09f455dcSMasahiro Yamada 	err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs);
584*09f455dcSMasahiro Yamada 	if (err < 0) {
585*09f455dcSMasahiro Yamada 		error("tegra-xusb-padctl: registers not found");
586*09f455dcSMasahiro Yamada 		return err;
587*09f455dcSMasahiro Yamada 	}
588*09f455dcSMasahiro Yamada 
589*09f455dcSMasahiro Yamada 	fdt_for_each_subnode(fdt, subnode, node) {
590*09f455dcSMasahiro Yamada 		struct tegra_xusb_padctl_config *config = &padctl->config;
591*09f455dcSMasahiro Yamada 
592*09f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt,
593*09f455dcSMasahiro Yamada 							subnode);
594*09f455dcSMasahiro Yamada 		if (err < 0) {
595*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to parse entry %s: %d",
596*09f455dcSMasahiro Yamada 			      config->name, err);
597*09f455dcSMasahiro Yamada 			continue;
598*09f455dcSMasahiro Yamada 		}
599*09f455dcSMasahiro Yamada 	}
600*09f455dcSMasahiro Yamada 
601*09f455dcSMasahiro Yamada 	return 0;
602*09f455dcSMasahiro Yamada }
603*09f455dcSMasahiro Yamada 
604*09f455dcSMasahiro Yamada static int process_nodes(const void *fdt, int nodes[], unsigned int count)
605*09f455dcSMasahiro Yamada {
606*09f455dcSMasahiro Yamada 	unsigned int i;
607*09f455dcSMasahiro Yamada 
608*09f455dcSMasahiro Yamada 	for (i = 0; i < count; i++) {
609*09f455dcSMasahiro Yamada 		enum fdt_compat_id id;
610*09f455dcSMasahiro Yamada 		int err;
611*09f455dcSMasahiro Yamada 
612*09f455dcSMasahiro Yamada 		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
613*09f455dcSMasahiro Yamada 			continue;
614*09f455dcSMasahiro Yamada 
615*09f455dcSMasahiro Yamada 		id = fdtdec_lookup(fdt, nodes[i]);
616*09f455dcSMasahiro Yamada 		switch (id) {
617*09f455dcSMasahiro Yamada 		case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL:
618*09f455dcSMasahiro Yamada 			break;
619*09f455dcSMasahiro Yamada 
620*09f455dcSMasahiro Yamada 		default:
621*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: unsupported compatible: %s",
622*09f455dcSMasahiro Yamada 			      fdtdec_get_compatible(id));
623*09f455dcSMasahiro Yamada 			continue;
624*09f455dcSMasahiro Yamada 		}
625*09f455dcSMasahiro Yamada 
626*09f455dcSMasahiro Yamada 		padctl->num_lanes = ARRAY_SIZE(tegra124_lanes);
627*09f455dcSMasahiro Yamada 		padctl->lanes = tegra124_lanes;
628*09f455dcSMasahiro Yamada 
629*09f455dcSMasahiro Yamada 		padctl->num_functions = ARRAY_SIZE(tegra124_functions);
630*09f455dcSMasahiro Yamada 		padctl->functions = tegra124_functions;
631*09f455dcSMasahiro Yamada 
632*09f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]);
633*09f455dcSMasahiro Yamada 		if (err < 0) {
634*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to parse DT: %d",
635*09f455dcSMasahiro Yamada 			      err);
636*09f455dcSMasahiro Yamada 			continue;
637*09f455dcSMasahiro Yamada 		}
638*09f455dcSMasahiro Yamada 
639*09f455dcSMasahiro Yamada 		/* deassert XUSB padctl reset */
640*09f455dcSMasahiro Yamada 		reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
641*09f455dcSMasahiro Yamada 
642*09f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_config_apply(padctl, &padctl->config);
643*09f455dcSMasahiro Yamada 		if (err < 0) {
644*09f455dcSMasahiro Yamada 			error("tegra-xusb-padctl: failed to apply pinmux: %d",
645*09f455dcSMasahiro Yamada 			      err);
646*09f455dcSMasahiro Yamada 			continue;
647*09f455dcSMasahiro Yamada 		}
648*09f455dcSMasahiro Yamada 
649*09f455dcSMasahiro Yamada 		/* only a single instance is supported */
650*09f455dcSMasahiro Yamada 		break;
651*09f455dcSMasahiro Yamada 	}
652*09f455dcSMasahiro Yamada 
653*09f455dcSMasahiro Yamada 	return 0;
654*09f455dcSMasahiro Yamada }
655*09f455dcSMasahiro Yamada 
656*09f455dcSMasahiro Yamada struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type)
657*09f455dcSMasahiro Yamada {
658*09f455dcSMasahiro Yamada 	struct tegra_xusb_phy *phy = NULL;
659*09f455dcSMasahiro Yamada 
660*09f455dcSMasahiro Yamada 	switch (type) {
661*09f455dcSMasahiro Yamada 	case TEGRA_XUSB_PADCTL_PCIE:
662*09f455dcSMasahiro Yamada 		phy = &padctl->phys[0];
663*09f455dcSMasahiro Yamada 		phy->padctl = padctl;
664*09f455dcSMasahiro Yamada 		break;
665*09f455dcSMasahiro Yamada 
666*09f455dcSMasahiro Yamada 	case TEGRA_XUSB_PADCTL_SATA:
667*09f455dcSMasahiro Yamada 		phy = &padctl->phys[1];
668*09f455dcSMasahiro Yamada 		phy->padctl = padctl;
669*09f455dcSMasahiro Yamada 		break;
670*09f455dcSMasahiro Yamada 	}
671*09f455dcSMasahiro Yamada 
672*09f455dcSMasahiro Yamada 	return phy;
673*09f455dcSMasahiro Yamada }
674*09f455dcSMasahiro Yamada 
675*09f455dcSMasahiro Yamada int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
676*09f455dcSMasahiro Yamada {
677*09f455dcSMasahiro Yamada 	if (phy && phy->ops && phy->ops->prepare)
678*09f455dcSMasahiro Yamada 		return phy->ops->prepare(phy);
679*09f455dcSMasahiro Yamada 
680*09f455dcSMasahiro Yamada 	return phy ? -ENOSYS : -EINVAL;
681*09f455dcSMasahiro Yamada }
682*09f455dcSMasahiro Yamada 
683*09f455dcSMasahiro Yamada int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
684*09f455dcSMasahiro Yamada {
685*09f455dcSMasahiro Yamada 	if (phy && phy->ops && phy->ops->enable)
686*09f455dcSMasahiro Yamada 		return phy->ops->enable(phy);
687*09f455dcSMasahiro Yamada 
688*09f455dcSMasahiro Yamada 	return phy ? -ENOSYS : -EINVAL;
689*09f455dcSMasahiro Yamada }
690*09f455dcSMasahiro Yamada 
691*09f455dcSMasahiro Yamada int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
692*09f455dcSMasahiro Yamada {
693*09f455dcSMasahiro Yamada 	if (phy && phy->ops && phy->ops->disable)
694*09f455dcSMasahiro Yamada 		return phy->ops->disable(phy);
695*09f455dcSMasahiro Yamada 
696*09f455dcSMasahiro Yamada 	return phy ? -ENOSYS : -EINVAL;
697*09f455dcSMasahiro Yamada }
698*09f455dcSMasahiro Yamada 
699*09f455dcSMasahiro Yamada int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
700*09f455dcSMasahiro Yamada {
701*09f455dcSMasahiro Yamada 	if (phy && phy->ops && phy->ops->unprepare)
702*09f455dcSMasahiro Yamada 		return phy->ops->unprepare(phy);
703*09f455dcSMasahiro Yamada 
704*09f455dcSMasahiro Yamada 	return phy ? -ENOSYS : -EINVAL;
705*09f455dcSMasahiro Yamada }
706*09f455dcSMasahiro Yamada 
707*09f455dcSMasahiro Yamada void tegra_xusb_padctl_init(const void *fdt)
708*09f455dcSMasahiro Yamada {
709*09f455dcSMasahiro Yamada 	int count, nodes[1];
710*09f455dcSMasahiro Yamada 
711*09f455dcSMasahiro Yamada 	count = fdtdec_find_aliases_for_id(fdt, "padctl",
712*09f455dcSMasahiro Yamada 					   COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
713*09f455dcSMasahiro Yamada 					   nodes, ARRAY_SIZE(nodes));
714*09f455dcSMasahiro Yamada 	if (process_nodes(fdt, nodes, count))
715*09f455dcSMasahiro Yamada 		return;
716*09f455dcSMasahiro Yamada }
717