1ef2ee5d0SMichal Meloun /*-
2ef2ee5d0SMichal Meloun  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
3ef2ee5d0SMichal Meloun  * All rights reserved.
4ef2ee5d0SMichal Meloun  *
5ef2ee5d0SMichal Meloun  * Redistribution and use in source and binary forms, with or without
6ef2ee5d0SMichal Meloun  * modification, are permitted provided that the following conditions
7ef2ee5d0SMichal Meloun  * are met:
8ef2ee5d0SMichal Meloun  * 1. Redistributions of source code must retain the above copyright
9ef2ee5d0SMichal Meloun  *    notice, this list of conditions and the following disclaimer.
10ef2ee5d0SMichal Meloun  * 2. Redistributions in binary form must reproduce the above copyright
11ef2ee5d0SMichal Meloun  *    notice, this list of conditions and the following disclaimer in the
12ef2ee5d0SMichal Meloun  *    documentation and/or other materials provided with the distribution.
13ef2ee5d0SMichal Meloun  *
14ef2ee5d0SMichal Meloun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ef2ee5d0SMichal Meloun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ef2ee5d0SMichal Meloun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ef2ee5d0SMichal Meloun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ef2ee5d0SMichal Meloun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ef2ee5d0SMichal Meloun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ef2ee5d0SMichal Meloun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ef2ee5d0SMichal Meloun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ef2ee5d0SMichal Meloun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ef2ee5d0SMichal Meloun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ef2ee5d0SMichal Meloun  * SUCH DAMAGE.
25ef2ee5d0SMichal Meloun  *
26ef2ee5d0SMichal Meloun  * $FreeBSD$
27ef2ee5d0SMichal Meloun  */
28ef2ee5d0SMichal Meloun 
29ef2ee5d0SMichal Meloun #include <sys/param.h>
30ef2ee5d0SMichal Meloun #include <sys/systm.h>
31ef2ee5d0SMichal Meloun #include <sys/bus.h>
32ef2ee5d0SMichal Meloun #include <sys/kernel.h>
33ef2ee5d0SMichal Meloun #include <sys/module.h>
34ef2ee5d0SMichal Meloun #include <sys/malloc.h>
35ef2ee5d0SMichal Meloun #include <sys/rman.h>
36ef2ee5d0SMichal Meloun 
37ef2ee5d0SMichal Meloun #include <machine/bus.h>
38ef2ee5d0SMichal Meloun #include <machine/fdt.h>
39ef2ee5d0SMichal Meloun 
40ef2ee5d0SMichal Meloun #include <dev/extres/hwreset/hwreset.h>
41ef2ee5d0SMichal Meloun #include <dev/extres/phy/phy.h>
42ef2ee5d0SMichal Meloun #include <dev/fdt/fdt_common.h>
43ef2ee5d0SMichal Meloun #include <dev/fdt/fdt_pinctrl.h>
44ef2ee5d0SMichal Meloun #include <dev/ofw/openfirm.h>
45ef2ee5d0SMichal Meloun #include <dev/ofw/ofw_bus.h>
46ef2ee5d0SMichal Meloun #include <dev/ofw/ofw_bus_subr.h>
47ef2ee5d0SMichal Meloun 
48ef2ee5d0SMichal Meloun #include <gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
49ef2ee5d0SMichal Meloun 
50ef2ee5d0SMichal Meloun #include "phy_if.h"
51ef2ee5d0SMichal Meloun 
52ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_USB2_PAD_MUX		0x004
53ef2ee5d0SMichal Meloun 
54ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_ELPG_PROGRAM		0x01C
55ef2ee5d0SMichal Meloun #define	 ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN		(1 << 26)
56ef2ee5d0SMichal Meloun #define	 ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY	(1 << 25)
57ef2ee5d0SMichal Meloun #define	 ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN		(1 << 24)
58ef2ee5d0SMichal Meloun 
59ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_P0_CTL1		0x040
60ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL1_PLL0_LOCKDET			(1 << 19)
61ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK		(0xf<< 12)
62ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL1_PLL_RST			(1 << 1)
63ef2ee5d0SMichal Meloun 
64ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_P0_CTL2		0x044
65ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL2_REFCLKBUF_EN			(1 << 6)
66ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL2_TXCLKREF_EN			(1 << 5)
67ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_P0_CTL2_TXCLKREF_SEL			(1 << 4)
68ef2ee5d0SMichal Meloun 
69ef2ee5d0SMichal Meloun 
70ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_USB3_PAD_MUX		0x134
71ef2ee5d0SMichal Meloun 
72ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_S0_CTL1		0x138
73ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_S0_CTL1_PLL1_LOCKDET			(1 << 27)
74ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_S0_CTL1_PLL1_MODE			(1 << 24)
75ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD			(1 << 3)
76ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_S0_CTL1_PLL_RST_L			(1 << 1)
77ef2ee5d0SMichal Meloun #define	 IOPHY_PLL_S0_CTL1_PLL_IDDQ			(1 << 0)
78ef2ee5d0SMichal Meloun 
79ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_S0_CTL2		0x13C
80ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_S0_CTL3		0x140
81ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_PLL_S0_CTL4		0x144
82ef2ee5d0SMichal Meloun 
83ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1	0x148
84ef2ee5d0SMichal Meloun #define	 IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD		(1 << 1)
85ef2ee5d0SMichal Meloun #define	 IOPHY_MISC_PAD_S0_CTL1_IDDQ			(1 << 0)
86ef2ee5d0SMichal Meloun 
87ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2	0x14C
88ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL3	0x150
89ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL4	0x154
90ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5	0x158
91ef2ee5d0SMichal Meloun #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6	0x15C
92ef2ee5d0SMichal Meloun 
93ef2ee5d0SMichal Meloun struct lane_cfg {
94ef2ee5d0SMichal Meloun 	char	*function;
95ef2ee5d0SMichal Meloun 	char 	**lanes;
96ef2ee5d0SMichal Meloun 	int 	iddq;
97ef2ee5d0SMichal Meloun };
98ef2ee5d0SMichal Meloun 
99ef2ee5d0SMichal Meloun struct xusbpadctl_softc {
100ef2ee5d0SMichal Meloun 	device_t	dev;
101ef2ee5d0SMichal Meloun 	struct resource	*mem_res;
102ef2ee5d0SMichal Meloun 	hwreset_t		rst;
103ef2ee5d0SMichal Meloun 	int		phy_ena_cnt;
104ef2ee5d0SMichal Meloun };
105ef2ee5d0SMichal Meloun 
106ef2ee5d0SMichal Meloun static struct ofw_compat_data compat_data[] = {
107ef2ee5d0SMichal Meloun 	{"nvidia,tegra124-xusb-padctl",	1},
108ef2ee5d0SMichal Meloun 	{NULL,				0},
109ef2ee5d0SMichal Meloun };
110ef2ee5d0SMichal Meloun 
111ef2ee5d0SMichal Meloun struct padctl_lane {
112ef2ee5d0SMichal Meloun 	const char *name;
113ef2ee5d0SMichal Meloun 	bus_size_t reg;
114ef2ee5d0SMichal Meloun 	uint32_t shift;
115ef2ee5d0SMichal Meloun 	uint32_t mask;
116ef2ee5d0SMichal Meloun 	int iddq;
117ef2ee5d0SMichal Meloun 	char **mux;
118ef2ee5d0SMichal Meloun 	int nmux;
119ef2ee5d0SMichal Meloun };
120ef2ee5d0SMichal Meloun 
121ef2ee5d0SMichal Meloun static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};
122ef2ee5d0SMichal Meloun static char *usb_mux[] = {"snps", "xusb"};
123ef2ee5d0SMichal Meloun static char *pci_mux[] = {"pcie", "usb3", "sata", "rsvd"};
124ef2ee5d0SMichal Meloun 
125ef2ee5d0SMichal Meloun #define	LANE(n, r, s, m, i, mx)					\
126ef2ee5d0SMichal Meloun {								\
127ef2ee5d0SMichal Meloun 	.name = n,						\
128ef2ee5d0SMichal Meloun 	.reg = r,						\
129ef2ee5d0SMichal Meloun 	.shift = s,						\
130ef2ee5d0SMichal Meloun 	.mask = m,						\
131ef2ee5d0SMichal Meloun 	.iddq = i,						\
132ef2ee5d0SMichal Meloun 	.mux = mx,						\
133ef2ee5d0SMichal Meloun 	.nmux = nitems(mx),					\
134ef2ee5d0SMichal Meloun }
135ef2ee5d0SMichal Meloun 
136ef2ee5d0SMichal Meloun static const struct padctl_lane lanes_tbl[] = {
137ef2ee5d0SMichal Meloun 	LANE("otg-0",  XUSB_PADCTL_USB2_PAD_MUX,  0, 0x3, -1, otg_mux),
138ef2ee5d0SMichal Meloun 	LANE("otg-1",  XUSB_PADCTL_USB2_PAD_MUX,  2, 0x3, -1, otg_mux),
139ef2ee5d0SMichal Meloun 	LANE("otg-2",  XUSB_PADCTL_USB2_PAD_MUX,  4, 0x3, -1, otg_mux),
140ef2ee5d0SMichal Meloun 	LANE("ulpi-0", XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, -1, usb_mux),
141ef2ee5d0SMichal Meloun 	LANE("hsic-0", XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, -1, usb_mux),
142ef2ee5d0SMichal Meloun 	LANE("hsic-1", XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, -1, usb_mux),
143ef2ee5d0SMichal Meloun 	LANE("pcie-0", XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3,  1, pci_mux),
144ef2ee5d0SMichal Meloun 	LANE("pcie-1", XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3,  2, pci_mux),
145ef2ee5d0SMichal Meloun 	LANE("pcie-2", XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3,  3, pci_mux),
146ef2ee5d0SMichal Meloun 	LANE("pcie-3", XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3,  4, pci_mux),
147ef2ee5d0SMichal Meloun 	LANE("pcie-4", XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3,  5, pci_mux),
148ef2ee5d0SMichal Meloun 	LANE("sata-0", XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3,  6, pci_mux),
149ef2ee5d0SMichal Meloun };
150ef2ee5d0SMichal Meloun 
151ef2ee5d0SMichal Meloun static int
152ef2ee5d0SMichal Meloun xusbpadctl_mux_function(const struct padctl_lane *lane, char *fnc_name)
153ef2ee5d0SMichal Meloun {
154ef2ee5d0SMichal Meloun 	int i;
155ef2ee5d0SMichal Meloun 
156ef2ee5d0SMichal Meloun 	for (i = 0; i < lane->nmux; i++) {
157ef2ee5d0SMichal Meloun 		if (strcmp(fnc_name, lane->mux[i]) == 0)
158ef2ee5d0SMichal Meloun 			return 	(i);
159ef2ee5d0SMichal Meloun 	}
160ef2ee5d0SMichal Meloun 
161ef2ee5d0SMichal Meloun 	return (-1);
162ef2ee5d0SMichal Meloun }
163ef2ee5d0SMichal Meloun 
164ef2ee5d0SMichal Meloun static int
165ef2ee5d0SMichal Meloun xusbpadctl_config_lane(struct xusbpadctl_softc *sc, char *lane_name,
166ef2ee5d0SMichal Meloun     const struct padctl_lane *lane, struct lane_cfg *cfg)
167ef2ee5d0SMichal Meloun {
168ef2ee5d0SMichal Meloun 
169ef2ee5d0SMichal Meloun 	int tmp;
170ef2ee5d0SMichal Meloun 	uint32_t reg;
171ef2ee5d0SMichal Meloun 
172ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, lane->reg);
173ef2ee5d0SMichal Meloun 	if (cfg->function != NULL) {
174ef2ee5d0SMichal Meloun 		tmp = xusbpadctl_mux_function(lane, cfg->function);
175ef2ee5d0SMichal Meloun 		if (tmp == -1) {
176ef2ee5d0SMichal Meloun 			device_printf(sc->dev,
177ef2ee5d0SMichal Meloun 			    "Unknown function %s for lane %s\n", cfg->function,
178ef2ee5d0SMichal Meloun 			    lane_name);
179ef2ee5d0SMichal Meloun 			return (EINVAL);
180ef2ee5d0SMichal Meloun 		}
181ef2ee5d0SMichal Meloun 		reg &= ~(lane->mask << lane->shift);
182ef2ee5d0SMichal Meloun 		reg |=  (tmp & lane->mask) << lane->shift;
183ef2ee5d0SMichal Meloun 	}
184ef2ee5d0SMichal Meloun 	if (cfg->iddq != -1) {
185ef2ee5d0SMichal Meloun 		if (lane->iddq == -1) {
186ef2ee5d0SMichal Meloun 			device_printf(sc->dev, "Invalid IDDQ for lane %s\n",
187ef2ee5d0SMichal Meloun 			lane_name);
188ef2ee5d0SMichal Meloun 			return (EINVAL);
189ef2ee5d0SMichal Meloun 		}
190ef2ee5d0SMichal Meloun 		if (cfg->iddq != 0)
191ef2ee5d0SMichal Meloun 			reg &= ~(1 << lane->iddq);
192ef2ee5d0SMichal Meloun 		else
193ef2ee5d0SMichal Meloun 			reg |= 1 << lane->iddq;
194ef2ee5d0SMichal Meloun 	}
195ef2ee5d0SMichal Meloun 
196ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, lane->reg, reg);
197ef2ee5d0SMichal Meloun 	return (0);
198ef2ee5d0SMichal Meloun }
199ef2ee5d0SMichal Meloun 
200ef2ee5d0SMichal Meloun static const struct padctl_lane *
201ef2ee5d0SMichal Meloun xusbpadctl_search_lane(char *lane_name)
202ef2ee5d0SMichal Meloun {
203ef2ee5d0SMichal Meloun 	int i;
204ef2ee5d0SMichal Meloun 
205ef2ee5d0SMichal Meloun 	for (i = 0; i < nitems(lanes_tbl); i++) {
206ef2ee5d0SMichal Meloun 		if (strcmp(lane_name, lanes_tbl[i].name) == 0)
207ef2ee5d0SMichal Meloun 			return 	(&lanes_tbl[i]);
208ef2ee5d0SMichal Meloun 	}
209ef2ee5d0SMichal Meloun 
210ef2ee5d0SMichal Meloun 	return (NULL);
211ef2ee5d0SMichal Meloun }
212ef2ee5d0SMichal Meloun 
213ef2ee5d0SMichal Meloun static int
214ef2ee5d0SMichal Meloun xusbpadctl_config_node(struct xusbpadctl_softc *sc, char *lane_name,
215ef2ee5d0SMichal Meloun     struct lane_cfg *cfg)
216ef2ee5d0SMichal Meloun {
217ef2ee5d0SMichal Meloun 	const struct padctl_lane *lane;
218ef2ee5d0SMichal Meloun 	int rv;
219ef2ee5d0SMichal Meloun 
220ef2ee5d0SMichal Meloun 	lane = xusbpadctl_search_lane(lane_name);
221ef2ee5d0SMichal Meloun 	if (lane == NULL) {
222ef2ee5d0SMichal Meloun 		device_printf(sc->dev, "Unknown lane: %s\n", lane_name);
223ef2ee5d0SMichal Meloun 		return (ENXIO);
224ef2ee5d0SMichal Meloun 	}
225ef2ee5d0SMichal Meloun 	rv = xusbpadctl_config_lane(sc, lane_name, lane, cfg);
226ef2ee5d0SMichal Meloun 	return (rv);
227ef2ee5d0SMichal Meloun }
228ef2ee5d0SMichal Meloun 
229ef2ee5d0SMichal Meloun static int
230ef2ee5d0SMichal Meloun xusbpadctl_read_node(struct xusbpadctl_softc *sc, phandle_t node,
231ef2ee5d0SMichal Meloun     struct lane_cfg *cfg, char **lanes, int *llanes)
232ef2ee5d0SMichal Meloun {
233ef2ee5d0SMichal Meloun 	int rv;
234ef2ee5d0SMichal Meloun 
235ef2ee5d0SMichal Meloun 	*llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes);
236ef2ee5d0SMichal Meloun 	if (*llanes <= 0)
237ef2ee5d0SMichal Meloun 		return (ENOENT);
238ef2ee5d0SMichal Meloun 
239ef2ee5d0SMichal Meloun 	/* Read function (mux) settings. */
240ef2ee5d0SMichal Meloun 	rv = OF_getprop_alloc(node, "nvidia,function", 1,
241ef2ee5d0SMichal Meloun 	    (void **)&cfg->function);
242ef2ee5d0SMichal Meloun 	if (rv <= 0)
243ef2ee5d0SMichal Meloun 		cfg->function = NULL;
244ef2ee5d0SMichal Meloun 	/* Read numeric properties. */
245ef2ee5d0SMichal Meloun 	rv = OF_getencprop(node, "nvidia,iddq", &cfg->iddq,
246ef2ee5d0SMichal Meloun 	    sizeof(cfg->iddq));
247ef2ee5d0SMichal Meloun 	if (rv <= 0)
248ef2ee5d0SMichal Meloun 		cfg->iddq = -1;
249ef2ee5d0SMichal Meloun 	return (0);
250ef2ee5d0SMichal Meloun }
251ef2ee5d0SMichal Meloun 
252ef2ee5d0SMichal Meloun static int
253ef2ee5d0SMichal Meloun xusbpadctl_process_node(struct xusbpadctl_softc *sc, phandle_t node)
254ef2ee5d0SMichal Meloun {
255ef2ee5d0SMichal Meloun 	struct lane_cfg cfg;
256ef2ee5d0SMichal Meloun 	char *lanes, *lname;
257ef2ee5d0SMichal Meloun 	int i, len, llanes, rv;
258ef2ee5d0SMichal Meloun 
259ef2ee5d0SMichal Meloun 	rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes);
260ef2ee5d0SMichal Meloun 	if (rv != 0)
261ef2ee5d0SMichal Meloun 		return (rv);
262ef2ee5d0SMichal Meloun 
263ef2ee5d0SMichal Meloun 	len = 0;
264ef2ee5d0SMichal Meloun 	lname = lanes;
265ef2ee5d0SMichal Meloun 	do {
266ef2ee5d0SMichal Meloun 		i = strlen(lname) + 1;
267ef2ee5d0SMichal Meloun 		rv = xusbpadctl_config_node(sc, lname, &cfg);
268ef2ee5d0SMichal Meloun 		if (rv != 0)
269ef2ee5d0SMichal Meloun 			device_printf(sc->dev,
270ef2ee5d0SMichal Meloun 			    "Cannot configure lane: %s: %d\n", lname, rv);
271ef2ee5d0SMichal Meloun 
272ef2ee5d0SMichal Meloun 		len += i;
273ef2ee5d0SMichal Meloun 		lname += i;
274ef2ee5d0SMichal Meloun 	} while (len < llanes);
275ef2ee5d0SMichal Meloun 
276ef2ee5d0SMichal Meloun 	if (lanes != NULL)
277bebd5269SOleksandr Tymoshenko 		OF_prop_free(lanes);
278ef2ee5d0SMichal Meloun 	if (cfg.function != NULL)
279bebd5269SOleksandr Tymoshenko 		OF_prop_free(cfg.function);
280ef2ee5d0SMichal Meloun 	return (rv);
281ef2ee5d0SMichal Meloun }
282ef2ee5d0SMichal Meloun 
283ef2ee5d0SMichal Meloun 
284ef2ee5d0SMichal Meloun static int
285ef2ee5d0SMichal Meloun xusbpadctl_pinctrl_cfg(device_t dev, phandle_t cfgxref)
286ef2ee5d0SMichal Meloun {
287ef2ee5d0SMichal Meloun 	struct xusbpadctl_softc *sc;
288ef2ee5d0SMichal Meloun 	phandle_t node, cfgnode;
289ef2ee5d0SMichal Meloun 	int rv;
290ef2ee5d0SMichal Meloun 
291ef2ee5d0SMichal Meloun 	sc = device_get_softc(dev);
292ef2ee5d0SMichal Meloun 	cfgnode = OF_node_from_xref(cfgxref);
293ef2ee5d0SMichal Meloun 
294ef2ee5d0SMichal Meloun 	rv = 0;
295ef2ee5d0SMichal Meloun 	for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
296ef2ee5d0SMichal Meloun 		if (!fdt_is_enabled(node))
297ef2ee5d0SMichal Meloun 			continue;
298ef2ee5d0SMichal Meloun 		rv = xusbpadctl_process_node(sc, node);
299ef2ee5d0SMichal Meloun 		if (rv != 0)
300ef2ee5d0SMichal Meloun 			return (rv);
301ef2ee5d0SMichal Meloun 	}
302ef2ee5d0SMichal Meloun 
303ef2ee5d0SMichal Meloun 	return (rv);
304ef2ee5d0SMichal Meloun }
305ef2ee5d0SMichal Meloun 
306ef2ee5d0SMichal Meloun static int
307ef2ee5d0SMichal Meloun xusbpadctl_phy_pcie_powerup(struct xusbpadctl_softc *sc)
308ef2ee5d0SMichal Meloun {
309ef2ee5d0SMichal Meloun 	uint32_t reg;
310ef2ee5d0SMichal Meloun 	int i;
311ef2ee5d0SMichal Meloun 
312ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
313ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
314ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
315ef2ee5d0SMichal Meloun 	DELAY(100);
316ef2ee5d0SMichal Meloun 
317ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
318ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN;
319ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN;
320ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
321ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
322ef2ee5d0SMichal Meloun 	DELAY(100);
323ef2ee5d0SMichal Meloun 
324ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
325ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_P0_CTL1_PLL_RST;
326ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
327ef2ee5d0SMichal Meloun 	DELAY(100);
328ef2ee5d0SMichal Meloun 
329ef2ee5d0SMichal Meloun 	for (i = 0; i < 100; i++) {
330ef2ee5d0SMichal Meloun 		reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
331ef2ee5d0SMichal Meloun 		if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET)
332ef2ee5d0SMichal Meloun 			return (0);
333ef2ee5d0SMichal Meloun 		DELAY(10);
334ef2ee5d0SMichal Meloun 	}
335ef2ee5d0SMichal Meloun 
336ef2ee5d0SMichal Meloun 	return (ETIMEDOUT);
337ef2ee5d0SMichal Meloun }
338ef2ee5d0SMichal Meloun 
339ef2ee5d0SMichal Meloun 
340ef2ee5d0SMichal Meloun static int
341ef2ee5d0SMichal Meloun xusbpadctl_phy_pcie_powerdown(struct xusbpadctl_softc *sc)
342ef2ee5d0SMichal Meloun {
343ef2ee5d0SMichal Meloun 	uint32_t reg;
344ef2ee5d0SMichal Meloun 
345ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
346ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST;
347ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
348ef2ee5d0SMichal Meloun 	DELAY(100);
349ef2ee5d0SMichal Meloun 	return (0);
350ef2ee5d0SMichal Meloun 
351ef2ee5d0SMichal Meloun }
352ef2ee5d0SMichal Meloun 
353ef2ee5d0SMichal Meloun static int
354ef2ee5d0SMichal Meloun xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc)
355ef2ee5d0SMichal Meloun {
356ef2ee5d0SMichal Meloun 	uint32_t reg;
357ef2ee5d0SMichal Meloun 	int i;
358ef2ee5d0SMichal Meloun 
359ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
360ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
361ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ;
362ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
363ef2ee5d0SMichal Meloun 
364ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
365ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
366ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ;
367ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
368ef2ee5d0SMichal Meloun 
369ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
370ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE;
371ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
372ef2ee5d0SMichal Meloun 
373ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
374ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
375ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
376ef2ee5d0SMichal Meloun 
377ef2ee5d0SMichal Meloun 	for (i = 100; i >= 0; i--) {
378ef2ee5d0SMichal Meloun 		reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
379ef2ee5d0SMichal Meloun 		if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
380ef2ee5d0SMichal Meloun 			break;
381ef2ee5d0SMichal Meloun 		DELAY(100);
382ef2ee5d0SMichal Meloun 	}
383ef2ee5d0SMichal Meloun 	if (i <= 0) {
384ef2ee5d0SMichal Meloun 		device_printf(sc->dev, "Failed to power up SATA phy\n");
385ef2ee5d0SMichal Meloun 		return (ETIMEDOUT);
386ef2ee5d0SMichal Meloun 	}
387ef2ee5d0SMichal Meloun 
388ef2ee5d0SMichal Meloun 	return (0);
389ef2ee5d0SMichal Meloun }
390ef2ee5d0SMichal Meloun 
391ef2ee5d0SMichal Meloun static int
392ef2ee5d0SMichal Meloun xusbpadctl_phy_sata_powerdown(struct xusbpadctl_softc *sc)
393ef2ee5d0SMichal Meloun {
394ef2ee5d0SMichal Meloun 	uint32_t reg;
395ef2ee5d0SMichal Meloun 
396ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
397ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L;
398ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
399ef2ee5d0SMichal Meloun 	DELAY(100);
400ef2ee5d0SMichal Meloun 
401ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
402ef2ee5d0SMichal Meloun 	reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE;
403ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
404ef2ee5d0SMichal Meloun 	DELAY(100);
405ef2ee5d0SMichal Meloun 
406ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
407ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
408ef2ee5d0SMichal Meloun 	reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ;
409ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
410ef2ee5d0SMichal Meloun 	DELAY(100);
411ef2ee5d0SMichal Meloun 
412ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
413ef2ee5d0SMichal Meloun 	reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
414ef2ee5d0SMichal Meloun 	reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ;
415ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
416ef2ee5d0SMichal Meloun 	DELAY(100);
417ef2ee5d0SMichal Meloun 
418ef2ee5d0SMichal Meloun 	return (0);
419ef2ee5d0SMichal Meloun }
420ef2ee5d0SMichal Meloun 
421ef2ee5d0SMichal Meloun static int
422ef2ee5d0SMichal Meloun xusbpadctl_phy_powerup(struct xusbpadctl_softc *sc)
423ef2ee5d0SMichal Meloun {
424ef2ee5d0SMichal Meloun 	uint32_t reg;
425ef2ee5d0SMichal Meloun 
426ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
427ef2ee5d0SMichal Meloun 	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
428ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
429ef2ee5d0SMichal Meloun 	DELAY(100);
430ef2ee5d0SMichal Meloun 
431ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
432ef2ee5d0SMichal Meloun 	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
433ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
434ef2ee5d0SMichal Meloun 	DELAY(100);
435ef2ee5d0SMichal Meloun 
436ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
437ef2ee5d0SMichal Meloun 	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
438ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
439ef2ee5d0SMichal Meloun 	DELAY(100);
440ef2ee5d0SMichal Meloun 
441ef2ee5d0SMichal Meloun 	return (0);
442ef2ee5d0SMichal Meloun }
443ef2ee5d0SMichal Meloun 
444ef2ee5d0SMichal Meloun static int
445ef2ee5d0SMichal Meloun xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc)
446ef2ee5d0SMichal Meloun {
447ef2ee5d0SMichal Meloun 	uint32_t reg;
448ef2ee5d0SMichal Meloun 
449ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
450ef2ee5d0SMichal Meloun 	reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
451ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
452ef2ee5d0SMichal Meloun 	DELAY(100);
453ef2ee5d0SMichal Meloun 
454ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
455ef2ee5d0SMichal Meloun 	reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
456ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
457ef2ee5d0SMichal Meloun 	DELAY(100);
458ef2ee5d0SMichal Meloun 
459ef2ee5d0SMichal Meloun 	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
460ef2ee5d0SMichal Meloun 	reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
461ef2ee5d0SMichal Meloun 	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
462ef2ee5d0SMichal Meloun 	DELAY(100);
463ef2ee5d0SMichal Meloun 
464ef2ee5d0SMichal Meloun 	return (0);
465ef2ee5d0SMichal Meloun }
466ef2ee5d0SMichal Meloun 
467ef2ee5d0SMichal Meloun static int
468ef2ee5d0SMichal Meloun xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable)
469ef2ee5d0SMichal Meloun {
470ef2ee5d0SMichal Meloun 	struct xusbpadctl_softc *sc;
471ef2ee5d0SMichal Meloun 	int rv;
472ef2ee5d0SMichal Meloun 
473ef2ee5d0SMichal Meloun 	sc = device_get_softc(dev);
474ef2ee5d0SMichal Meloun 
475ef2ee5d0SMichal Meloun 	if ((id != TEGRA_XUSB_PADCTL_PCIE) &&
476ef2ee5d0SMichal Meloun 	    (id != TEGRA_XUSB_PADCTL_SATA)) {
477ef2ee5d0SMichal Meloun 		device_printf(dev, "Unknown phy: %d\n", id);
478ef2ee5d0SMichal Meloun 		return (ENXIO);
479ef2ee5d0SMichal Meloun 	}
480ef2ee5d0SMichal Meloun 
481ef2ee5d0SMichal Meloun 	rv = 0;
482ef2ee5d0SMichal Meloun 	if (enable) {
483ef2ee5d0SMichal Meloun 		if (sc->phy_ena_cnt == 0) {
484ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_powerup(sc);
485ef2ee5d0SMichal Meloun 			if (rv != 0)
486ef2ee5d0SMichal Meloun 				return (rv);
487ef2ee5d0SMichal Meloun 		}
488ef2ee5d0SMichal Meloun 		sc->phy_ena_cnt++;
489ef2ee5d0SMichal Meloun 	}
490ef2ee5d0SMichal Meloun 
491ef2ee5d0SMichal Meloun 	if (id == TEGRA_XUSB_PADCTL_PCIE) {
492ef2ee5d0SMichal Meloun 		if (enable)
493ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_pcie_powerup(sc);
494ef2ee5d0SMichal Meloun 		else
495ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_pcie_powerdown(sc);
496ef2ee5d0SMichal Meloun 		if (rv != 0)
497ef2ee5d0SMichal Meloun 			return (rv);
498ef2ee5d0SMichal Meloun 	} else if (id == TEGRA_XUSB_PADCTL_SATA) {
499ef2ee5d0SMichal Meloun 		if (enable)
500ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_sata_powerup(sc);
501ef2ee5d0SMichal Meloun 		else
502ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_sata_powerdown(sc);
503ef2ee5d0SMichal Meloun 		if (rv != 0)
504ef2ee5d0SMichal Meloun 			return (rv);
505ef2ee5d0SMichal Meloun 	}
506ef2ee5d0SMichal Meloun 	if (!enable) {
507ef2ee5d0SMichal Meloun 		 if (sc->phy_ena_cnt == 1) {
508ef2ee5d0SMichal Meloun 			rv = xusbpadctl_phy_powerdown(sc);
509ef2ee5d0SMichal Meloun 			if (rv != 0)
510ef2ee5d0SMichal Meloun 				return (rv);
511ef2ee5d0SMichal Meloun 		}
512ef2ee5d0SMichal Meloun 		sc->phy_ena_cnt--;
513ef2ee5d0SMichal Meloun 	}
514ef2ee5d0SMichal Meloun 
515ef2ee5d0SMichal Meloun 	return (0);
516ef2ee5d0SMichal Meloun }
517ef2ee5d0SMichal Meloun 
518ef2ee5d0SMichal Meloun static int
519ef2ee5d0SMichal Meloun xusbpadctl_probe(device_t dev)
520ef2ee5d0SMichal Meloun {
521ef2ee5d0SMichal Meloun 
522ef2ee5d0SMichal Meloun 	if (!ofw_bus_status_okay(dev))
523ef2ee5d0SMichal Meloun 		return (ENXIO);
524ef2ee5d0SMichal Meloun 
525ef2ee5d0SMichal Meloun 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
526ef2ee5d0SMichal Meloun 		return (ENXIO);
527ef2ee5d0SMichal Meloun 
528ef2ee5d0SMichal Meloun 	device_set_desc(dev, "Tegra XUSB phy");
529ef2ee5d0SMichal Meloun 	return (BUS_PROBE_DEFAULT);
530ef2ee5d0SMichal Meloun }
531ef2ee5d0SMichal Meloun 
532ef2ee5d0SMichal Meloun static int
533ef2ee5d0SMichal Meloun xusbpadctl_detach(device_t dev)
534ef2ee5d0SMichal Meloun {
535ef2ee5d0SMichal Meloun 
536ef2ee5d0SMichal Meloun 	/* This device is always present. */
537ef2ee5d0SMichal Meloun 	return (EBUSY);
538ef2ee5d0SMichal Meloun }
539ef2ee5d0SMichal Meloun 
540ef2ee5d0SMichal Meloun static int
541ef2ee5d0SMichal Meloun xusbpadctl_attach(device_t dev)
542ef2ee5d0SMichal Meloun {
543ef2ee5d0SMichal Meloun 	struct xusbpadctl_softc * sc;
544ef2ee5d0SMichal Meloun 	int rid, rv;
545ef2ee5d0SMichal Meloun 	phandle_t node;
546ef2ee5d0SMichal Meloun 
547ef2ee5d0SMichal Meloun 	sc = device_get_softc(dev);
548ef2ee5d0SMichal Meloun 	sc->dev = dev;
549ef2ee5d0SMichal Meloun 
550ef2ee5d0SMichal Meloun 	rid = 0;
551ef2ee5d0SMichal Meloun 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
552ef2ee5d0SMichal Meloun 	    RF_ACTIVE);
553ef2ee5d0SMichal Meloun 	if (sc->mem_res == NULL) {
554ef2ee5d0SMichal Meloun 		device_printf(dev, "Cannot allocate memory resources\n");
555ef2ee5d0SMichal Meloun 		return (ENXIO);
556ef2ee5d0SMichal Meloun 	}
557ef2ee5d0SMichal Meloun 
558ef2ee5d0SMichal Meloun 	node = ofw_bus_get_node(dev);
559dac93553SMichal Meloun 	rv = hwreset_get_by_ofw_name(dev, 0, "padctl", &sc->rst);
560ef2ee5d0SMichal Meloun 	if (rv != 0) {
561ef2ee5d0SMichal Meloun 		device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv);
562ef2ee5d0SMichal Meloun 		return (rv);
563ef2ee5d0SMichal Meloun 	}
564ef2ee5d0SMichal Meloun 	rv = hwreset_deassert(sc->rst);
565ef2ee5d0SMichal Meloun 	if (rv != 0) {
566ef2ee5d0SMichal Meloun 		device_printf(dev, "Cannot unreset 'padctl' reset: %d\n", rv);
567ef2ee5d0SMichal Meloun 		return (rv);
568ef2ee5d0SMichal Meloun 	}
569ef2ee5d0SMichal Meloun 
570ef2ee5d0SMichal Meloun 	/* Register as a pinctrl device and use default configuration */
571ef2ee5d0SMichal Meloun 	fdt_pinctrl_register(dev, NULL);
572ef2ee5d0SMichal Meloun 	fdt_pinctrl_configure_by_name(dev, "default");
573ef2ee5d0SMichal Meloun 	phy_register_provider(dev);
574ef2ee5d0SMichal Meloun 
575ef2ee5d0SMichal Meloun 	return (0);
576ef2ee5d0SMichal Meloun }
577ef2ee5d0SMichal Meloun 
578ef2ee5d0SMichal Meloun 
579ef2ee5d0SMichal Meloun static device_method_t tegra_xusbpadctl_methods[] = {
580ef2ee5d0SMichal Meloun 	/* Device interface */
581ef2ee5d0SMichal Meloun 	DEVMETHOD(device_probe,         xusbpadctl_probe),
582ef2ee5d0SMichal Meloun 	DEVMETHOD(device_attach,        xusbpadctl_attach),
583ef2ee5d0SMichal Meloun 	DEVMETHOD(device_detach,        xusbpadctl_detach),
584ef2ee5d0SMichal Meloun 
585ef2ee5d0SMichal Meloun 	/* fdt_pinctrl interface */
586ef2ee5d0SMichal Meloun 	DEVMETHOD(fdt_pinctrl_configure, xusbpadctl_pinctrl_cfg),
587ef2ee5d0SMichal Meloun 
588ef2ee5d0SMichal Meloun 	/* phy interface */
589ef2ee5d0SMichal Meloun 	DEVMETHOD(phy_enable,		xusbpadctl_phy_enable),
590ef2ee5d0SMichal Meloun 
591ef2ee5d0SMichal Meloun 	DEVMETHOD_END
592ef2ee5d0SMichal Meloun };
593ef2ee5d0SMichal Meloun 
594ef2ee5d0SMichal Meloun static driver_t tegra_xusbpadctl_driver = {
595ef2ee5d0SMichal Meloun 	"tegra_xusbpadctl",
596ef2ee5d0SMichal Meloun 	tegra_xusbpadctl_methods,
597ef2ee5d0SMichal Meloun 	sizeof(struct xusbpadctl_softc),
598ef2ee5d0SMichal Meloun };
599ef2ee5d0SMichal Meloun 
600ef2ee5d0SMichal Meloun static devclass_t tegra_xusbpadctl_devclass;
601ef2ee5d0SMichal Meloun 
602ef2ee5d0SMichal Meloun EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver,
603ef2ee5d0SMichal Meloun     tegra_xusbpadctl_devclass, 0, 0, 73);
604