1e9034789SMichal Meloun /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3e9034789SMichal Meloun  *
4e9034789SMichal Meloun  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
5e9034789SMichal Meloun  *
6e9034789SMichal Meloun  * Redistribution and use in source and binary forms, with or without
7e9034789SMichal Meloun  * modification, are permitted provided that the following conditions
8e9034789SMichal Meloun  * are met:
9e9034789SMichal Meloun  * 1. Redistributions of source code must retain the above copyright
10e9034789SMichal Meloun  *    notice, this list of conditions and the following disclaimer.
11e9034789SMichal Meloun  * 2. Redistributions in binary form must reproduce the above copyright
12e9034789SMichal Meloun  *    notice, this list of conditions and the following disclaimer in the
13e9034789SMichal Meloun  *    documentation and/or other materials provided with the distribution.
14e9034789SMichal Meloun  *
15e9034789SMichal Meloun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e9034789SMichal Meloun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e9034789SMichal Meloun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e9034789SMichal Meloun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e9034789SMichal Meloun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e9034789SMichal Meloun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e9034789SMichal Meloun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e9034789SMichal Meloun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e9034789SMichal Meloun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e9034789SMichal Meloun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e9034789SMichal Meloun  * SUCH DAMAGE.
26e9034789SMichal Meloun  */
27e9034789SMichal Meloun 
28e9034789SMichal Meloun #include <sys/param.h>
29e9034789SMichal Meloun #include <sys/systm.h>
30e9034789SMichal Meloun #include <sys/bus.h>
31e9034789SMichal Meloun #include <sys/kernel.h>
32e9034789SMichal Meloun #include <sys/module.h>
33e9034789SMichal Meloun #include <sys/malloc.h>
34e9034789SMichal Meloun #include <sys/rman.h>
35e9034789SMichal Meloun 
36e9034789SMichal Meloun #include <machine/bus.h>
37e9034789SMichal Meloun 
38be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h>
391f469a9fSEmmanuel Vadot #include <dev/hwreset/hwreset.h>
40*950a6087SEmmanuel Vadot #include <dev/phy/phy.h>
41b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator.h>
42e9034789SMichal Meloun #include <dev/fdt/fdt_common.h>
43e9034789SMichal Meloun #include <dev/fdt/fdt_pinctrl.h>
44e9034789SMichal Meloun #include <dev/ofw/openfirm.h>
45e9034789SMichal Meloun #include <dev/ofw/ofw_bus.h>
46e9034789SMichal Meloun #include <dev/ofw/ofw_bus_subr.h>
47e9034789SMichal Meloun 
48e9034789SMichal Meloun #include <arm/nvidia/tegra_efuse.h>
49e9034789SMichal Meloun 
50c38fe878SEmmanuel Vadot #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
51e9034789SMichal Meloun 
52e9034789SMichal Meloun #include "phynode_if.h"
53e9034789SMichal Meloun 
54e9034789SMichal Meloun /* FUSE calibration data. */
55e9034789SMichal Meloun #define	FUSE_SKU_CALIB_0			0x0F0
56e9034789SMichal Meloun #define	  FUSE_SKU_CALIB_0_HS_CURR_LEVEL_123(x, i)	(((x) >> (11 + ((i) - 1) * 6)) & 0x3F);
57e9034789SMichal Meloun #define	  FUSE_SKU_CALIB_0_HS_TERM_RANGE_ADJ(x)		(((x) >>  7) & 0x0F);
58e9034789SMichal Meloun #define	  FUSE_SKU_CALIB_0_HS_CURR_LEVEL_0(x)		(((x) >>  0) & 0x3F);
59e9034789SMichal Meloun 
60e9034789SMichal Meloun #define	FUSE_USB_CALIB_EXT_0			0x250
61e9034789SMichal Meloun #define	  FUSE_USB_CALIB_EXT_0_RPD_CTRL(x)		(((x) >>  0) & 0x1F);
62e9034789SMichal Meloun 
63e9034789SMichal Meloun 
64e9034789SMichal Meloun /* Registers. */
65e9034789SMichal Meloun #define	XUSB_PADCTL_USB2_PAD_MUX		0x004
66e9034789SMichal Meloun 
67e9034789SMichal Meloun #define	XUSB_PADCTL_USB2_PORT_CAP		0x008
68e9034789SMichal Meloun #define	 USB2_PORT_CAP_PORT_REVERSE_ID(p)		(1 << (3 + (p) * 4))
69e9034789SMichal Meloun #define	 USB2_PORT_CAP_PORT_INTERNAL(p)			(1 << (2 + (p) * 4))
70e9034789SMichal Meloun #define	 USB2_PORT_CAP_PORT_CAP(p, x)			(((x) & 3) << ((p) * 4))
71e9034789SMichal Meloun #define	  USB2_PORT_CAP_PORT_CAP_OTG			0x3
72e9034789SMichal Meloun #define	  USB2_PORT_CAP_PORT_CAP_DEVICE			0x2
73e9034789SMichal Meloun #define	  USB2_PORT_CAP_PORT_CAP_HOST			0x1
74e9034789SMichal Meloun #define	  USB2_PORT_CAP_PORT_CAP_DISABLED		0x0
75e9034789SMichal Meloun 
76e9034789SMichal Meloun #define	XUSB_PADCTL_SS_PORT_MAP			0x014
77e9034789SMichal Meloun #define	 SS_PORT_MAP_PORT_INTERNAL(p)			(1 << (3 + (p) * 4))
78e9034789SMichal Meloun #define	 SS_PORT_MAP_PORT_MAP(p, x)			(((x) & 7) << ((p) * 4))
79e9034789SMichal Meloun 
80e9034789SMichal Meloun #define	XUSB_PADCTL_ELPG_PROGRAM1		0x024
81e9034789SMichal Meloun #define	 ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN		(1 << 31)
82e9034789SMichal Meloun #define	 ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY	(1 << 30)
83e9034789SMichal Meloun #define	 ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN		(1 << 29)
84e9034789SMichal Meloun #define	 ELPG_PROGRAM1_SSP_ELPG_VCORE_DOWN(x) 		(1 << (2 + (x) * 3))
85e9034789SMichal Meloun #define	 ELPG_PROGRAM1_SSP_ELPG_CLAMP_EN_EARLY(x) 	(1 << (1 + (x) * 3))
86e9034789SMichal Meloun #define	 ELPG_PROGRAM1_SSP_ELPG_CLAMP_EN(x)		(1 << (0 + (x) * 3))
87e9034789SMichal Meloun 
88e9034789SMichal Meloun #define	XUSB_PADCTL_USB3_PAD_MUX		0x028
89e9034789SMichal Meloun #define	 USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) 		(1 << (8 + (x)))
90e9034789SMichal Meloun #define	 USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) 		(1 << (1 + (x)))
91e9034789SMichal Meloun 
92e9034789SMichal Meloun #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1(x) (0x084 + (x) * 0x40)
93e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBON_RPU_OVRD_VAL (1 << 23)
94e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBON_RPU_OVRD	( 1 << 22)
95e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBON_RPD_OVRD_VAL (1 << 21)
96e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBON_RPD_OVRD	 (1 << 20)
97e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBOP_RPU_OVRD_VAL (1 << 19)
98e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBOP_RPU_OVRD	 (1 << 18)
99e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBOP_RPD_OVRD_VAL (1 << 17)
100e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_USBOP_RPD_OVRD	 (1 << 16)
101e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_DYN_DLY(x)	 (((x) & 0x3) <<  9)
102e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV(x)	 (((x) & 0x3) <<  7)
103e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18	 (1 <<  6)
104e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_DIV_DET_EN	 (1 <<  4)
105e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VOP_DIV2P7_DET	 (1 <<  3)
106e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VOP_DIV2P0_DET	 (1 <<  2)
107e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VON_DIV2P7_DET	 (1 <<  1)
108e9034789SMichal Meloun #define	 USB2_BATTERY_CHRG_OTGPAD_CTL1_VON_DIV2P0_DET	 (1 <<  0)
109e9034789SMichal Meloun 
110e9034789SMichal Meloun #define	XUSB_PADCTL_USB2_OTG_PAD_CTL0(x) 	(0x088 + (x) * 0x40)
111e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_PD_ZI			(1 << 29)
112e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_PD2_OVRD_EN			(1 << 28)
113e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_PD2				(1 << 27)
114e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_PD				(1 << 26)
115e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_TERM_EN			(1 << 25)
116e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_LS_FSLEW(x)			(((x) & 0x0F) << 21)
117e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_LS_RSLEW(x)			(((x) & 0x0F) << 17)
118e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_FS_FSLEW(x)			(((x) & 0x0F) << 13)
119e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_FS_RSLEW(x)			(((x) & 0x0F) <<  9)
120e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_HS_SLEW(x)			(((x) & 0x3F) <<  6)
121e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(x)		(((x) & 0x3F) <<  0)
122e9034789SMichal Meloun 
123e9034789SMichal Meloun #define XUSB_PADCTL_USB2_OTG_PAD_CTL1(x) 	(0x08C + (x) * 0x40)
124e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_RPD_CTRL(x)			(((x) & 0x1F) <<  26)
125e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_RPU_STATUS_HIGH		(1 <<  25)
126e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_RPU_SWITCH_LOW		(1 <<  24)
127e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_RPU_SWITCH_OVRD		(1 <<  23)
128e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_HS_LOOPBACK_OVRD_VAL		(1 <<  22)
129e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_HS_LOOPBACK_OVRD_EN		(1 <<  21)
130e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PTERM_RANGE_ADJ(x)		(((x) & 0x0F) << 17)
131e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PD_DISC_OVRD_VAL		(1 << 16)
132e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PD_CHRP_OVRD_VAL		(1 << 15)
133e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_RPU_RANGE_ADJ(x)		(((x) & 0x03) << 13)
134e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_HS_COUP_EN(x)		(((x) & 0x03) << 11)
135e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_SPARE(x)			(((x) & 0x0F) <<  7)
136e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(x)		(((x) & 0x0F) <<  3)
137e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PD_DR			(1 <<  2)
138e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PD_DISC_OVRD			(1 <<  1)
139e9034789SMichal Meloun #define	 USB2_OTG_PAD_CTL1_PD_CHRP_OVRD			(1 <<  0)
140e9034789SMichal Meloun 
141e9034789SMichal Meloun #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0(x) (0x0C0 + (x) * 0x40)
142e9034789SMichal Meloun #define	XUSB_PADCTL_USB2_BIAS_PAD_CTL0		0x0284
143e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_TRK_PWR_ENA			(1 << 29)
144e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_SPARE(x)			(((x) & 0xF) << 25)
145e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_CHG_DIV(x)			(((x) & 0xF) << 21)
146e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_TEMP_COEF(x)		(((x) & 0x7) << 18)
147e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_VREF_CTRL(x)		(((x) & 0x7) << 15)
148e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_ADJRPU(x)			(((x) & 0x7) << 12)
149e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_PD				(1 << 11)
150e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_TERM_OFFSETL(x)		(((x) & 0x7) <<  8)
151e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_HS_CHIRP_LEVEL(x)		(((x) & 0x3) <<  6)
152e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(x)		(((x) & 0x7) <<  3)
153e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(x)		(((x) & 0x7) <<  0)
154e9034789SMichal Meloun 
155e9034789SMichal Meloun #define	XUSB_PADCTL_USB2_BIAS_PAD_CTL1		0x0288
156e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_FORCE_TRK_CLK_EN		(1 << 30)
157e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TRK_SW_OVRD			(1 << 29)
158e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TRK_DONE			(1 << 28)
159e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TRK_START			(1 << 27)
160e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_PD_TRK			(1 << 26)
161e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER(x)	(((x) & 0x7F) << 19)
162e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TRK_START_TIMER(x)		(((x) & 0x7F) << 12)
163e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_PCTRL(x)			(((x) & 0x3F) <<  6)
164e9034789SMichal Meloun #define	 USB2_BIAS_PAD_CTL1_TCTRL(x)			(((x) & 0x3F) <<  0)
165e9034789SMichal Meloun 
166e9034789SMichal Meloun #define	XUSB_PADCTL_HSIC_PAD_CTL0(x)		(0x300 + (x) * 0x20)
167e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPU_STROBE			(1 << 18)
168e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPU_DATA1			(1 << 17)
169e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPU_DATA0			(1 << 16)
170e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPD_STROBE			(1 << 15)
171e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPD_DATA1			(1 << 14)
172e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_RPD_DATA0			(1 << 13)
173e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_LPBK_STROBE			(1 << 12)
174e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_LPBK_DATA1			(1 << 11)
175e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_LPBK_DATA0			(1 << 10)
176e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_ZI_STROBE			(1 <<  9)
177e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_ZI_DATA1			(1 <<  8)
178e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_ZI_DATA0			(1 <<  7)
179e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_RX_STROBE			(1 <<  6)
180e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_RX_DATA1			(1 <<  5)
181e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_RX_DATA0			(1 <<  4)
182e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_TX_STROBE			(1 <<  3)
183e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_TX_DATA1			(1 <<  2)
184e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_PD_TX_DATA0			(1 <<  1)
185e9034789SMichal Meloun #define	 HSIC_PAD_CTL0_IDDQ				(1 <<  0)
186e9034789SMichal Meloun 
187e9034789SMichal Meloun #define	XUSB_PADCTL_HSIC_PAD_CTL1(x)		(0x304 + (x) * 0x20)
188e9034789SMichal Meloun #define	 HSIC_PAD_CTL1_RTERM(x)				(((x) & 0xF) << 12)
189e9034789SMichal Meloun #define	 HSIC_PAD_CTL1_HSIC_OPT(x)			(((x) & 0xF) <<  8)
190e9034789SMichal Meloun #define	 HSIC_PAD_CTL1_TX_SLEW(x)			(((x) & 0xF) <<  4)
191e9034789SMichal Meloun #define	 HSIC_PAD_CTL1_TX_RTUNEP(x)			(((x) & 0xF) <<  0)
192e9034789SMichal Meloun 
193e9034789SMichal Meloun #define	XUSB_PADCTL_HSIC_PAD_CTL2(x)		(0x308 + (x) * 0x20)
194e9034789SMichal Meloun #define	 HSIC_PAD_CTL2_RX_STROBE_TRIM(x)		(((x) & 0xF) <<  8)
195e9034789SMichal Meloun #define	 HSIC_PAD_CTL2_RX_DATA1_TRIM(x)			(((x) & 0xF) <<  4)
196e9034789SMichal Meloun #define	 HSIC_PAD_CTL2_RX_DATA0_TRIM(x)			(((x) & 0xF) <<  0)
197e9034789SMichal Meloun 
198e9034789SMichal Meloun #define	XUSB_PADCTL_HSIC_PAD_TRK_CTL		0x340
199e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_AUTO_RTERM_EN			(1 << 24)
200e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_FORCE_TRK_CLK_EN		(1 << 23)
201e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_TRK_SW_OVRD			(1 << 22)
202e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_TRK_DONE			(1 << 21)
203e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_TRK_START			(1 << 20)
204e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_PD_TRK			(1 << 19)
205e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER(x)	(((x) & 0x3F) << 12)
206e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_TRK_START_TIMER(x)		(((x) & 0x7F) <<  5)
207e9034789SMichal Meloun #define	 HSIC_PAD_TRK_CTL_RTERM_OUT(x)			(((x) & 0x1F) <<  0)
208e9034789SMichal Meloun 
209e9034789SMichal Meloun #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL	0x344
210e9034789SMichal Meloun 
211e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_P0_CTL1		0x360
212e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_FREQ_PSDIV(x)		(((x) & 0x03) << 28)
213e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_FREQ_NDIV(x)		(((x) & 0xFF) << 20)
214e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_FREQ_MDIV(x)		(((x) & 0x03) << 16)
215e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_LOCKDET_STATUS 		(1 << 15)
216e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_MODE_GET(x)		(((x) >> 8) & 0x03)
217e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_BYPASS_EN 		(1 <<  7)
218e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_FREERUN_EN		(1 <<  6)
219e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_PWR_OVRD			(1 <<  4)
220e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_ENABLE 			(1 <<  3)
221e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_SLEEP(x)			(((x) & 0x03) <<  1)
222e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL1_PLL0_IDDQ 			(1 << 0)
223e9034789SMichal Meloun 
224e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_P0_CTL2		0x364
225e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL2_PLL0_CAL_CTRL(x)		(((x) & 0xFFFFFF) << 4)
226e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL2_PLL0_CAL_RESET		(1 << 3)
227e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL2_PLL0_CAL_OVRD			(1 << 2)
228e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL2_PLL0_CAL_DONE			(1 << 1)
229e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL2_PLL0_CAL_EN			(1 << 0)
230e9034789SMichal Meloun 
231e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_P0_CTL4		0x36c
232e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_TCLKOUT_EN		(1 << 28)
233e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_CLKDIST_CTRL(x)		(((x) & 0xF) << 20)
234e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_XDIGCLK_EN		(1 << 19)
235e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_XDIGCLK_SEL(x)		(((x) & 0x7) << 16)
236e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_TXCLKREF_EN		(1 << 15)
237e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_TXCLKREF_SEL(x)		(((x) & 0x3) << 12)
238e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_FBCLKBUF_EN		(1 <<  9)
239e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_REFCLKBUF_EN		(1 <<  8)
240e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_REFCLK_SEL(x)		(((x) & 0xF) <<  4)
241e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL4_PLL0_REFCLK_TERM100		(1 <<  0)
242e9034789SMichal Meloun 
243e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_P0_CTL5		0x370
244e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL5_PLL0_DCO_CTRL(x)		(((x) & 0xFF) << 16)
245e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL5_PLL0_LPF_CTRL(x)		(((x) & 0xFF) <<  8)
246e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL5_PLL0_CP_CTRL(x)		(((x) & 0x0F) <<  4)
247e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL5_PLL0_PFD_CTRL(x)		(((x) & 0x03) <<  0)
248e9034789SMichal Meloun 
249e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_P0_CTL8		0x37c
250e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_DONE		(1U << 31)
251e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_VAL(x)		(((x) & 0x1F) << 24)
252e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_BYP_EN		(1 << 23)
253e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_BYP_CODE(x)		(((x) & 0x1F) << 16)
254e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_OVRD		(1 << 15)
255e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_CLK_EN		(1 << 13)
256e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_RCAL_EN			(1 << 12)
257e9034789SMichal Meloun #define  UPHY_PLL_P0_CTL8_PLL0_BGAP_CTRL(x)		(((x) & 0xFFF) <<  0)
258e9034789SMichal Meloun 
259e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_MISC_PAD_P_CTL1(x)	(0x460 + (x) * 0x40)
260e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_S0_CTL1		0x860
261e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_FREQ_PSDIV(x)		(((x) & 0x03) << 28)
262e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_FREQ_NDIV(x)		(((x) & 0xFF) << 20)
263e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_FREQ_MDIV(x)		(((x) & 0x03) << 16)
264e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_LOCKDET_STATUS 		(1 << 15)
265e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_MODE_GET(x)		(((x) >> 8) & 0x03)
266e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_BYPASS_EN 		(1 <<  7)
267e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_FREERUN_EN		(1 <<  6)
268e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_PWR_OVRD			(1 <<  4)
269e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_ENABLE 			(1 <<  3)
270e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_SLEEP(x)			(((x) & 0x03) <<  1)
271e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL1_PLL0_IDDQ 			(1 << 0)
272e9034789SMichal Meloun 
273e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_S0_CTL2		0x864
274e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL2_PLL0_CAL_CTRL(x)		(((x) & 0xFFFFFF) << 4)
275e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL2_PLL0_CAL_RESET		(1 << 3)
276e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL2_PLL0_CAL_OVRD			(1 << 2)
277e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL2_PLL0_CAL_DONE			(1 << 1)
278e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL2_PLL0_CAL_EN			(1 << 0)
279e9034789SMichal Meloun 
280e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_S0_CTL4		0x86c
281e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_TCLKOUT_EN		(1 << 28)
282e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_CLKDIST_CTRL(x)		(((x) & 0xF) << 20)
283e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_XDIGCLK_EN		(1 << 19)
284e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_XDIGCLK_SEL(x)		(((x) & 0x7) << 16)
285e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_EN		(1 << 15)
286e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_SEL(x)		(((x) & 0x3) << 12)
287e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_FBCLKBUF_EN		(1 <<  9)
288e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_REFCLKBUF_EN		(1 <<  8)
289e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_REFCLK_SEL(x)		(((x) & 0xF) <<  4)
290e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL4_PLL0_REFCLK_TERM100		(1 <<  0)
291e9034789SMichal Meloun 
292e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_S0_CTL5		0x870
293e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL5_PLL0_DCO_CTRL(x)		(((x) & 0xFF) << 16)
294e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL5_PLL0_LPF_CTRL(x)		(((x) & 0xFF) <<  8)
295e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL5_PLL0_CP_CTRL(x)		(((x) & 0x0F) <<  4)
296e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL5_PLL0_PFD_CTRL(x)		(((x) & 0x03) <<  0)
297e9034789SMichal Meloun 
298e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_PLL_S0_CTL8		0x87c
299e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_DONE		(1U << 31)
300e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_VAL(x)		(((x) & 0x1F) << 24)
301e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_BYP_EN		(1 << 23)
302e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_BYP_CODE(x)		(((x) & 0x1F) << 16)
303e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_OVRD		(1 << 15)
304e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_CLK_EN		(1 << 13)
305e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_RCAL_EN			(1 << 12)
306e9034789SMichal Meloun #define  UPHY_PLL_S0_CTL8_PLL0_BGAP_CTRL(x)		(((x) & 0xFFF) <<  0)
307e9034789SMichal Meloun 
308e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1	0x960
309e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1(x)	(0xa60 + (x) * 0x40)
310e9034789SMichal Meloun #define	 UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL(x)		(((x) & 0x3) << 16)
311e9034789SMichal Meloun 
312e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2(x)	(0xa64 + (x) * 0x40)
313e9034789SMichal Meloun #define	 UPHY_USB3_PAD_ECTL2_RX_IQ_CTRL(x)		(((x) & 0x000F) << 16)
314e9034789SMichal Meloun #define	 UPHY_USB3_PAD_ECTL2_RX_CTLE(x)			(((x) & 0xFFFF) <<  0)
315e9034789SMichal Meloun 
316e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3(x)	(0xa68 + (x) * 0x40)
317e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4(x)	(0xa6c + (x) * 0x40)
318e9034789SMichal Meloun #define	 UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL(x)		(((x) & 0xFFFF) << 16)
319e9034789SMichal Meloun #define	 UPHY_USB3_PAD_ECTL4_RX_PI_CTRL(x)		(((x) & 0x00FF) <<  0)
320e9034789SMichal Meloun 
321e9034789SMichal Meloun #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6(x)	(0xa74 + (x) * 0x40)
322e9034789SMichal Meloun 
323e9034789SMichal Meloun 
324e9034789SMichal Meloun #define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, (_r), (_v))
325e9034789SMichal Meloun #define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, (_r))
326e9034789SMichal Meloun 
327e9034789SMichal Meloun 
328e9034789SMichal Meloun struct padctl_softc {
329e9034789SMichal Meloun 	device_t	dev;
330e9034789SMichal Meloun 	struct resource	*mem_res;
331e9034789SMichal Meloun 	hwreset_t	rst;
332e9034789SMichal Meloun 	int		phy_ena_cnt;
333e9034789SMichal Meloun 	int		pcie_ena_cnt;
334e9034789SMichal Meloun 	int		sata_ena_cnt;
335e9034789SMichal Meloun 
336e9034789SMichal Meloun 	/* Fuses calibration data */
337e9034789SMichal Meloun 	/* USB2 */
338e9034789SMichal Meloun 	uint32_t	hs_curr_level[4];
339e9034789SMichal Meloun 	uint32_t	hs_curr_level_offs;	/* Not inited yet, always 0 */
340e9034789SMichal Meloun 	uint32_t	hs_term_range_adj;
341e9034789SMichal Meloun 	uint32_t	rpd_ctrl;
342e9034789SMichal Meloun 
343e9034789SMichal Meloun 	/* HSIC */
344e9034789SMichal Meloun 	uint32_t	rx_strobe_trim;		/* Not inited yet, always 0 */
345e9034789SMichal Meloun 	uint32_t	rx_data0_trim;		/* Not inited yet, always 0 */
346e9034789SMichal Meloun 	uint32_t	rx_data1_trim;		/* Not inited yet, always 0 */
347e9034789SMichal Meloun 	uint32_t	tx_rtune_p;		/* Not inited yet, always 0 */
348e9034789SMichal Meloun 	uint32_t	strobe_trim;		/* Not inited yet, always 0 */
349e9034789SMichal Meloun };
350e9034789SMichal Meloun 
351e9034789SMichal Meloun static struct ofw_compat_data compat_data[] = {
352e9034789SMichal Meloun 	{"nvidia,tegra210-xusb-padctl",	1},
353e9034789SMichal Meloun 	{NULL,				0},
354e9034789SMichal Meloun };
355e9034789SMichal Meloun 
356e9034789SMichal Meloun /* Ports. */
357e9034789SMichal Meloun enum padctl_port_type {
358e9034789SMichal Meloun 	PADCTL_PORT_USB2,
359e9034789SMichal Meloun 	PADCTL_PORT_HSIC,
360e9034789SMichal Meloun 	PADCTL_PORT_USB3,
361e9034789SMichal Meloun };
362e9034789SMichal Meloun 
363e9034789SMichal Meloun struct padctl_lane;
364e9034789SMichal Meloun struct padctl_port {
365e9034789SMichal Meloun 	enum padctl_port_type	type;
366e9034789SMichal Meloun 	const char		*name;
367e9034789SMichal Meloun 	const char		*base_name;
368e9034789SMichal Meloun 	int			idx;
369e9034789SMichal Meloun 	int			(*init)(struct padctl_softc *sc,
370e9034789SMichal Meloun 				    struct padctl_port *port);
371e9034789SMichal Meloun 
372e9034789SMichal Meloun 	/* Runtime data. */
373e9034789SMichal Meloun 	phandle_t		xref;
374e9034789SMichal Meloun 	bool			enabled;
375e9034789SMichal Meloun 	bool			internal;
376e9034789SMichal Meloun 	uint32_t		companion;
377e9034789SMichal Meloun 	regulator_t		supply_vbus;
378e9034789SMichal Meloun 	struct padctl_lane	*lane;
379e9034789SMichal Meloun };
380e9034789SMichal Meloun 
381e9034789SMichal Meloun static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port);
382e9034789SMichal Meloun 
383e9034789SMichal Meloun #define	PORT(t, n, p, i) {						\
384e9034789SMichal Meloun 	.type = t,							\
385e9034789SMichal Meloun 	.name = n "-" #p,						\
386e9034789SMichal Meloun 	.base_name = n,							\
387e9034789SMichal Meloun 	.idx = p,							\
388e9034789SMichal Meloun 	.init = i,							\
389e9034789SMichal Meloun }
390e9034789SMichal Meloun static struct padctl_port ports_tbl[] = {
391e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB2, "usb2", 0, NULL),
392e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB2, "usb2", 1, NULL),
393e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB2, "usb2", 2, NULL),
394e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB2, "usb2", 3, NULL),
395e9034789SMichal Meloun 	PORT(PADCTL_PORT_HSIC, "hsic", 0, NULL),
396e9034789SMichal Meloun 	PORT(PADCTL_PORT_HSIC, "hsic", 1, NULL),
397e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB3, "usb3", 0, usb3_port_init),
398e9034789SMichal Meloun 	PORT(PADCTL_PORT_USB3, "usb3", 1, usb3_port_init),
399e9034789SMichal Meloun };
400e9034789SMichal Meloun 
401e9034789SMichal Meloun /* Pads - a group of lannes. */
402e9034789SMichal Meloun enum padctl_pad_type {
403e9034789SMichal Meloun 	PADCTL_PAD_USB2,
404e9034789SMichal Meloun 	PADCTL_PAD_HSIC,
405e9034789SMichal Meloun 	PADCTL_PAD_PCIE,
406e9034789SMichal Meloun 	PADCTL_PAD_SATA,
407e9034789SMichal Meloun };
408e9034789SMichal Meloun 
409e9034789SMichal Meloun struct padctl_lane;
410e9034789SMichal Meloun struct padctl_pad {
411e9034789SMichal Meloun 	const char		*name;
412e9034789SMichal Meloun 	enum padctl_pad_type	type;
413e9034789SMichal Meloun 	const char		*clock_name;
414e9034789SMichal Meloun 	char			*reset_name; 	/* XXX constify !!!!!! */
415e9034789SMichal Meloun 	int			(*enable)(struct padctl_softc *sc,
416e9034789SMichal Meloun 				    struct padctl_lane *lane);
417e9034789SMichal Meloun 	int			(*disable)(struct padctl_softc *sc,
418e9034789SMichal Meloun 				    struct padctl_lane *lane);
419e9034789SMichal Meloun 	/* Runtime data. */
420e9034789SMichal Meloun 	bool			enabled;
421e9034789SMichal Meloun 	clk_t			clk;
422e9034789SMichal Meloun 	hwreset_t		reset;
423e9034789SMichal Meloun 	int			nlanes;
424e9034789SMichal Meloun 	struct padctl_lane	*lanes[8]; 	/* Safe maximum value. */
425e9034789SMichal Meloun };
426e9034789SMichal Meloun 
427e9034789SMichal Meloun static int usb2_enable(struct padctl_softc *sc, struct padctl_lane *lane);
428e9034789SMichal Meloun static int usb2_disable(struct padctl_softc *sc, struct padctl_lane *lane);
429e9034789SMichal Meloun static int hsic_enable(struct padctl_softc *sc, struct padctl_lane *lane);
430e9034789SMichal Meloun static int hsic_disable(struct padctl_softc *sc, struct padctl_lane *lane);
431e9034789SMichal Meloun static int pcie_enable(struct padctl_softc *sc, struct padctl_lane *lane);
432e9034789SMichal Meloun static int pcie_disable(struct padctl_softc *sc, struct padctl_lane *lane);
433e9034789SMichal Meloun static int sata_enable(struct padctl_softc *sc, struct padctl_lane *lane);
434e9034789SMichal Meloun static int sata_disable(struct padctl_softc *sc, struct padctl_lane *lane);
435e9034789SMichal Meloun 
436e9034789SMichal Meloun #define	PAD(n, t, cn, rn, e, d) {						\
437e9034789SMichal Meloun 	.name = n,							\
438e9034789SMichal Meloun 	.type = t,							\
439e9034789SMichal Meloun 	.clock_name = cn,						\
440e9034789SMichal Meloun 	.reset_name = rn,						\
441e9034789SMichal Meloun 	.enable = e,							\
442e9034789SMichal Meloun 	.disable = d,							\
443e9034789SMichal Meloun }
444e9034789SMichal Meloun static struct padctl_pad pads_tbl[] = {
445e9034789SMichal Meloun 	PAD("usb2", PADCTL_PAD_USB2, "trk",  NULL, usb2_enable, usb2_disable),
446e9034789SMichal Meloun 	PAD("hsic", PADCTL_PAD_HSIC, "trk",  NULL, hsic_enable, hsic_disable),
447e9034789SMichal Meloun 	PAD("pcie", PADCTL_PAD_PCIE, "pll", "phy", pcie_enable, pcie_disable),
448e9034789SMichal Meloun 	PAD("sata", PADCTL_PAD_SATA, "pll", "phy", sata_enable, sata_disable),
449e9034789SMichal Meloun };
450e9034789SMichal Meloun 
451e9034789SMichal Meloun /* Lanes. */
452e9034789SMichal Meloun static char *usb_mux[] = {"snps", "xusb", "uart", "rsvd"};
453e9034789SMichal Meloun static char *hsic_mux[] = {"snps", "xusb"};
454e9034789SMichal Meloun static char *pci_mux[] = {"pcie-x1", "usb3-ss", "sata", "pcie-x4"};
455e9034789SMichal Meloun 
456e9034789SMichal Meloun struct padctl_lane {
457e9034789SMichal Meloun 	const char		*name;
458e9034789SMichal Meloun 	int			idx;
459e9034789SMichal Meloun 	bus_size_t		reg;
460e9034789SMichal Meloun 	uint32_t		shift;
461e9034789SMichal Meloun 	uint32_t		mask;
462e9034789SMichal Meloun 	char			**mux;
463e9034789SMichal Meloun 	int			nmux;
464e9034789SMichal Meloun 	/* Runtime data. */
465e9034789SMichal Meloun 	bool			enabled;
466e9034789SMichal Meloun 	phandle_t		xref;
467e9034789SMichal Meloun 	struct padctl_pad	*pad;
468e9034789SMichal Meloun 	struct padctl_port	*port;
469e9034789SMichal Meloun 	int			mux_idx;
470e9034789SMichal Meloun 
471e9034789SMichal Meloun };
472e9034789SMichal Meloun 
473e9034789SMichal Meloun #define	LANE(n, p, r, s, m, mx) {					\
474e9034789SMichal Meloun 	.name = n "-" #p,						\
475e9034789SMichal Meloun 	.idx = p,							\
476e9034789SMichal Meloun 	.reg = r,							\
477e9034789SMichal Meloun 	.shift = s,							\
478e9034789SMichal Meloun 	.mask = m,							\
479e9034789SMichal Meloun 	.mux = mx,							\
480e9034789SMichal Meloun 	.nmux = nitems(mx),						\
481e9034789SMichal Meloun }
482e9034789SMichal Meloun static struct padctl_lane lanes_tbl[] = {
483e9034789SMichal Meloun 	LANE("usb2", 0, XUSB_PADCTL_USB2_PAD_MUX,  0, 0x3, usb_mux),
484e9034789SMichal Meloun 	LANE("usb2", 1, XUSB_PADCTL_USB2_PAD_MUX,  2, 0x3, usb_mux),
485e9034789SMichal Meloun 	LANE("usb2", 2, XUSB_PADCTL_USB2_PAD_MUX,  4, 0x3, usb_mux),
486e9034789SMichal Meloun 	LANE("usb2", 3, XUSB_PADCTL_USB2_PAD_MUX,  6, 0x3, usb_mux),
487e9034789SMichal Meloun 	LANE("hsic", 0, XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, hsic_mux),
488e9034789SMichal Meloun 	LANE("hsic", 1, XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, hsic_mux),
489e9034789SMichal Meloun 	LANE("pcie", 0, XUSB_PADCTL_USB3_PAD_MUX, 12, 0x3, pci_mux),
490e9034789SMichal Meloun 	LANE("pcie", 1, XUSB_PADCTL_USB3_PAD_MUX, 14, 0x3, pci_mux),
491e9034789SMichal Meloun 	LANE("pcie", 2, XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, pci_mux),
492e9034789SMichal Meloun 	LANE("pcie", 3, XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, pci_mux),
493e9034789SMichal Meloun 	LANE("pcie", 4, XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, pci_mux),
494e9034789SMichal Meloun 	LANE("pcie", 5, XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, pci_mux),
495e9034789SMichal Meloun 	LANE("pcie", 6, XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, pci_mux),
496e9034789SMichal Meloun 	LANE("sata", 0, XUSB_PADCTL_USB3_PAD_MUX, 30, 0x3, pci_mux),
497e9034789SMichal Meloun };
498e9034789SMichal Meloun 
499e9034789SMichal Meloun /* Define all possible mappings for USB3 port lanes */
500e9034789SMichal Meloun struct padctl_lane_map {
501e9034789SMichal Meloun 	int			port_idx;
502e9034789SMichal Meloun 	enum padctl_pad_type	pad_type;
503e9034789SMichal Meloun 	int			lane_idx;
504e9034789SMichal Meloun };
505e9034789SMichal Meloun 
506e9034789SMichal Meloun #define	LANE_MAP(pi, pt, li) {						\
507e9034789SMichal Meloun 	.port_idx = pi,							\
508e9034789SMichal Meloun 	.pad_type = pt,							\
509e9034789SMichal Meloun 	.lane_idx = li,							\
510e9034789SMichal Meloun }
511e9034789SMichal Meloun static struct padctl_lane_map lane_map_tbl[] = {
512e9034789SMichal Meloun 	LANE_MAP(0, PADCTL_PAD_PCIE, 6), 	/* port USB3-0 -> lane PCIE-0 */
513e9034789SMichal Meloun 	LANE_MAP(1, PADCTL_PAD_PCIE, 5), 	/* port USB3-1 -> lane PCIE-1 */
514e9034789SMichal Meloun 	LANE_MAP(2, PADCTL_PAD_PCIE, 0), 	/* port USB3-2 -> lane PCIE-0 */
515e9034789SMichal Meloun 	LANE_MAP(2, PADCTL_PAD_PCIE, 2), 	/* port USB3-2 -> lane PCIE-2 */
516e9034789SMichal Meloun 	LANE_MAP(3, PADCTL_PAD_PCIE, 4), 	/* port USB3-3 -> lane PCIE-4 */
517e9034789SMichal Meloun };
518e9034789SMichal Meloun 
519e9034789SMichal Meloun /* Phy class and methods. */
520e9034789SMichal Meloun static int xusbpadctl_phy_enable(struct phynode *phy, bool enable);
521e9034789SMichal Meloun static phynode_method_t xusbpadctl_phynode_methods[] = {
522e9034789SMichal Meloun 	PHYNODEMETHOD(phynode_enable,	xusbpadctl_phy_enable),
523e9034789SMichal Meloun 	PHYNODEMETHOD_END
524e9034789SMichal Meloun 
525e9034789SMichal Meloun };
526e9034789SMichal Meloun DEFINE_CLASS_1(xusbpadctl_phynode, xusbpadctl_phynode_class,
527e9034789SMichal Meloun     xusbpadctl_phynode_methods, 0, phynode_class);
528e9034789SMichal Meloun 
529e9034789SMichal Meloun static struct padctl_port *search_lane_port(struct padctl_softc *sc,
530e9034789SMichal Meloun     struct padctl_lane *lane);
531e9034789SMichal Meloun 
532e9034789SMichal Meloun 
tegra210_xusb_pll_hw_control_enable(void)533e9034789SMichal Meloun static void tegra210_xusb_pll_hw_control_enable(void) {}
tegra210_xusb_pll_hw_sequence_start(void)534e9034789SMichal Meloun static void tegra210_xusb_pll_hw_sequence_start(void) {}
tegra210_sata_pll_hw_control_enable(void)535e9034789SMichal Meloun static void tegra210_sata_pll_hw_control_enable(void) {}
tegra210_sata_pll_hw_sequence_start(void)536e9034789SMichal Meloun static void tegra210_sata_pll_hw_sequence_start(void) {}
537e9034789SMichal Meloun 
538e9034789SMichal Meloun /* -------------------------------------------------------------------------
539e9034789SMichal Meloun  *
540e9034789SMichal Meloun  *   PEX functions
541e9034789SMichal Meloun  */
542e9034789SMichal Meloun static int
uphy_pex_enable(struct padctl_softc * sc,struct padctl_pad * pad)543e9034789SMichal Meloun uphy_pex_enable(struct padctl_softc *sc, struct padctl_pad *pad)
544e9034789SMichal Meloun {
545e9034789SMichal Meloun 	uint32_t reg;
546e9034789SMichal Meloun 	int rv, i;
547e9034789SMichal Meloun 
548e9034789SMichal Meloun 	if (sc->pcie_ena_cnt > 0) {
549e9034789SMichal Meloun 		sc->pcie_ena_cnt++;
550e9034789SMichal Meloun 		return (0);
551e9034789SMichal Meloun 	}
552e9034789SMichal Meloun 
553e9034789SMichal Meloun 	/* 22.8.4 UPHY PLLs, Step 4, page 1346 */
554e9034789SMichal Meloun 	/* 1. Deassert PLL/Lane resets. */
555e9034789SMichal Meloun 	rv = clk_enable(pad->clk);
556e9034789SMichal Meloun 	if (rv < 0) {
557e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot enable clock for pad '%s': %d\n",
558e9034789SMichal Meloun 		    pad->name, rv);
559e9034789SMichal Meloun 		return (rv);
560e9034789SMichal Meloun 	}
561e9034789SMichal Meloun 
562e9034789SMichal Meloun 	rv = hwreset_deassert(pad->reset);
563e9034789SMichal Meloun 	if (rv < 0) {
564e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot unreset pad '%s': %d\n",
565e9034789SMichal Meloun 		    pad->name, rv);
566e9034789SMichal Meloun 		clk_disable(pad->clk);
567e9034789SMichal Meloun 		return (rv);
568e9034789SMichal Meloun 	}
569e9034789SMichal Meloun 
570e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
571e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL2_PLL0_CAL_CTRL(~0);
572e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL2_PLL0_CAL_CTRL(0x136);
573e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
574e9034789SMichal Meloun 
575e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
576e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL5_PLL0_DCO_CTRL(~0);
577e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL5_PLL0_DCO_CTRL(0x2a);
578e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL5, reg);
579e9034789SMichal Meloun 
580e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
581e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL1_PLL0_PWR_OVRD;
582e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
583e9034789SMichal Meloun 
584e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
585e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL2_PLL0_CAL_OVRD;
586e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
587e9034789SMichal Meloun 
588e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
589e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL8_PLL0_RCAL_OVRD;
590e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8, reg);
591e9034789SMichal Meloun 
592e9034789SMichal Meloun 	/*
593e9034789SMichal Meloun 	 * 2. For the following registers, default values
594e9034789SMichal Meloun 	 *    take care of the desired frequency.
595e9034789SMichal Meloun 	 */
596e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
597e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL4_PLL0_TXCLKREF_SEL(~0);
598e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL4_PLL0_REFCLK_SEL(~0);
599e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL4_PLL0_TXCLKREF_SEL(0x2);
600e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL4_PLL0_TXCLKREF_EN;
601e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL4, reg);
602e9034789SMichal Meloun 
603e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
604e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL1_PLL0_FREQ_MDIV(~0);
605e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL1_PLL0_FREQ_NDIV(~0);
606e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL1_PLL0_FREQ_NDIV(0x19);
607e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
608e9034789SMichal Meloun 
609e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
610e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL1_PLL0_IDDQ;
611e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
612e9034789SMichal Meloun 
613e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
614e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL1_PLL0_SLEEP(~0);
615e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
616e9034789SMichal Meloun 
617e9034789SMichal Meloun 	/* 3. Wait 100 ns. */
618e9034789SMichal Meloun 	DELAY(10);
619e9034789SMichal Meloun 
620e9034789SMichal Meloun 	/* XXX This in not in TRM */
621e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
622e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL4_PLL0_REFCLKBUF_EN;
623e9034789SMichal Meloun 	WR4(sc,  XUSB_PADCTL_UPHY_PLL_P0_CTL4, reg);
624e9034789SMichal Meloun 
625e9034789SMichal Meloun 	/* 4. Calibration. */
626e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
627e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL2_PLL0_CAL_EN;
628e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
629e9034789SMichal Meloun 	for (i = 30; i > 0; i--) {
630e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
631e9034789SMichal Meloun 		if (reg & UPHY_PLL_P0_CTL2_PLL0_CAL_DONE)
632e9034789SMichal Meloun 			break;
633e9034789SMichal Meloun 		DELAY(10);
634e9034789SMichal Meloun 	}
635e9034789SMichal Meloun 	if (i <= 0) {
636e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in calibration step 1 "
637e9034789SMichal Meloun 		    "for pad '%s' (0x%08X).\n", pad->name, reg);
638e9034789SMichal Meloun 		rv = ETIMEDOUT;
639e9034789SMichal Meloun 		goto err;
640e9034789SMichal Meloun 	}
641e9034789SMichal Meloun 
642e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
643e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL2_PLL0_CAL_EN;
644e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
645e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
646e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
647e9034789SMichal Meloun 		if ((reg & UPHY_PLL_P0_CTL2_PLL0_CAL_DONE) == 0)
648e9034789SMichal Meloun 			break;
649e9034789SMichal Meloun 		DELAY(10);
650e9034789SMichal Meloun 	}
651e9034789SMichal Meloun 	if (i <= 0) {
652e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in calibration step 2 "
653e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
654e9034789SMichal Meloun 		rv = ETIMEDOUT;
655e9034789SMichal Meloun 		goto err;
656e9034789SMichal Meloun 	}
657e9034789SMichal Meloun 
65856c202deSEd Maste 	/* 5. Enable the PLL (20 μs Lock time) */
659e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
660e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL1_PLL0_ENABLE;
661e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
662e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
663e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
664e9034789SMichal Meloun 		if (reg & UPHY_PLL_P0_CTL1_PLL0_LOCKDET_STATUS)
665e9034789SMichal Meloun 			break;
666e9034789SMichal Meloun 		DELAY(10);
667e9034789SMichal Meloun 	}
668e9034789SMichal Meloun 	if (i <= 0) {
669e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout while enabling PLL "
670e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
671e9034789SMichal Meloun 		rv = ETIMEDOUT;
672e9034789SMichal Meloun 		goto err;
673e9034789SMichal Meloun 	}
674e9034789SMichal Meloun 
675e9034789SMichal Meloun 	/* 6. RCAL. */
676e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
677e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL8_PLL0_RCAL_EN;
678e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL8_PLL0_RCAL_CLK_EN;
679e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8, reg);
680e9034789SMichal Meloun 
681e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
682e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
683e9034789SMichal Meloun 		if (reg & UPHY_PLL_P0_CTL8_PLL0_RCAL_DONE)
684e9034789SMichal Meloun 			break;
685e9034789SMichal Meloun 		DELAY(10);
686e9034789SMichal Meloun 	}
687e9034789SMichal Meloun 	if (i <= 0) {
688e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in RX calibration step 1 "
689e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
690e9034789SMichal Meloun 		rv = ETIMEDOUT;
691e9034789SMichal Meloun 		goto err;
692e9034789SMichal Meloun 	}
693e9034789SMichal Meloun 
694e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
695e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL8_PLL0_RCAL_EN;
696e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8, reg);
697e9034789SMichal Meloun 
698e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
699e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
700e9034789SMichal Meloun 		if (!(reg & UPHY_PLL_P0_CTL8_PLL0_RCAL_DONE))
701e9034789SMichal Meloun 			break;
702e9034789SMichal Meloun 
703e9034789SMichal Meloun 		DELAY(10);
704e9034789SMichal Meloun 	}
705e9034789SMichal Meloun 	if (i <= 0) {
706e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in RX calibration step 2 "
707e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
708e9034789SMichal Meloun 		rv = ETIMEDOUT;
709e9034789SMichal Meloun 		goto err;
710e9034789SMichal Meloun 	}
711e9034789SMichal Meloun 
712e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
713e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL8_PLL0_RCAL_CLK_EN;
714e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8, reg);
715e9034789SMichal Meloun 
716e9034789SMichal Meloun 	/* Enable Hardware Power Sequencer. */
717e9034789SMichal Meloun 	tegra210_xusb_pll_hw_control_enable();
718e9034789SMichal Meloun 
719e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
720e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL1_PLL0_PWR_OVRD;
721e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL1, reg);
722e9034789SMichal Meloun 
723e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
724e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL2_PLL0_CAL_OVRD;
725e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
726e9034789SMichal Meloun 
727e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
728e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL8_PLL0_RCAL_OVRD;
729e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL8, reg);
730e9034789SMichal Meloun 
731e9034789SMichal Meloun 	DELAY(50);
732e9034789SMichal Meloun 
733e9034789SMichal Meloun 	tegra210_xusb_pll_hw_sequence_start();
734e9034789SMichal Meloun 
735e9034789SMichal Meloun 	sc->pcie_ena_cnt++;
736e9034789SMichal Meloun 
737e9034789SMichal Meloun 	return (0);
738e9034789SMichal Meloun 
739e9034789SMichal Meloun err:
740e9034789SMichal Meloun 	hwreset_deassert(pad->reset);
741e9034789SMichal Meloun 	clk_disable(pad->clk);
742e9034789SMichal Meloun 	return (rv);
743e9034789SMichal Meloun }
744e9034789SMichal Meloun 
745e9034789SMichal Meloun static void
uphy_pex_disable(struct padctl_softc * sc,struct padctl_pad * pad)746e9034789SMichal Meloun uphy_pex_disable(struct padctl_softc *sc, struct padctl_pad *pad)
747e9034789SMichal Meloun {
748e9034789SMichal Meloun 	int rv;
749e9034789SMichal Meloun 
750e9034789SMichal Meloun 	sc->pcie_ena_cnt--;
751e9034789SMichal Meloun 	if (sc->pcie_ena_cnt <= 0) {
752e9034789SMichal Meloun 		rv = hwreset_assert(pad->reset);
753e9034789SMichal Meloun 		if (rv != 0) {
754e9034789SMichal Meloun 			device_printf(sc->dev, "Cannot reset pad '%s': %d\n",
755e9034789SMichal Meloun 			    pad->name, rv);
756e9034789SMichal Meloun 		}
757e9034789SMichal Meloun 		rv = clk_disable(pad->clk);
758e9034789SMichal Meloun 		if (rv != 0) {
759e9034789SMichal Meloun 			device_printf(sc->dev,
760e9034789SMichal Meloun 			    "Cannot dicable clock for pad '%s': %d\n",
761e9034789SMichal Meloun 			    pad->name, rv);
762e9034789SMichal Meloun 		}
763e9034789SMichal Meloun 	}
764e9034789SMichal Meloun }
765e9034789SMichal Meloun 
766e9034789SMichal Meloun static int
uphy_sata_enable(struct padctl_softc * sc,struct padctl_pad * pad,bool usb)767e9034789SMichal Meloun uphy_sata_enable(struct padctl_softc *sc, struct padctl_pad *pad, bool usb)
768e9034789SMichal Meloun {
769e9034789SMichal Meloun 	uint32_t reg;
770e9034789SMichal Meloun 	int rv, i;
771e9034789SMichal Meloun 
772e9034789SMichal Meloun 	/* 22.8.4 UPHY PLLs, Step 4, page 1346 */
773e9034789SMichal Meloun 	/* 1. Deassert PLL/Lane resets. */
774e9034789SMichal Meloun 	if (sc->sata_ena_cnt > 0) {
775e9034789SMichal Meloun 		sc->sata_ena_cnt++;
776e9034789SMichal Meloun 		return (0);
777e9034789SMichal Meloun 	}
778e9034789SMichal Meloun 
779e9034789SMichal Meloun 	rv = clk_enable(pad->clk);
780e9034789SMichal Meloun 	if (rv < 0) {
781e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot enable clock for pad '%s': %d\n",
782e9034789SMichal Meloun 		    pad->name, rv);
783e9034789SMichal Meloun 		return (rv);
784e9034789SMichal Meloun 	}
785e9034789SMichal Meloun 
786e9034789SMichal Meloun 	rv = hwreset_deassert(pad->reset);
787e9034789SMichal Meloun 	if (rv < 0) {
788e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot unreset pad '%s': %d\n",
789e9034789SMichal Meloun 		    pad->name, rv);
790e9034789SMichal Meloun 		clk_disable(pad->clk);
791e9034789SMichal Meloun 		return (rv);
792e9034789SMichal Meloun 	}
793e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
794e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL2_PLL0_CAL_CTRL(~0);
795e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL2_PLL0_CAL_CTRL(0x136);
796e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL2, reg);
797e9034789SMichal Meloun 
798e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
799e9034789SMichal Meloun 	reg &= ~UPHY_PLL_P0_CTL5_PLL0_DCO_CTRL(~0);
800e9034789SMichal Meloun 	reg |= UPHY_PLL_P0_CTL5_PLL0_DCO_CTRL(0x2a);
801e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_P0_CTL5, reg);
802e9034789SMichal Meloun 
803e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
804e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL1_PLL0_PWR_OVRD;
805e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
806e9034789SMichal Meloun 
807e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
808e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL2_PLL0_CAL_OVRD;
809e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2, reg);
810e9034789SMichal Meloun 
811e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
812e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL8_PLL0_RCAL_OVRD;
813e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8, reg);
814e9034789SMichal Meloun 
815e9034789SMichal Meloun 	/*
816e9034789SMichal Meloun 	 * 2. For the following registers, default values
817e9034789SMichal Meloun 	 *    take care of the desired frequency.
818e9034789SMichal Meloun 	 */
819e9034789SMichal Meloun 	 reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
820e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_SEL(~0);
821e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL4_PLL0_REFCLK_SEL(~0);
822e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_EN;
823e9034789SMichal Meloun 
824e9034789SMichal Meloun 	if (usb)
825e9034789SMichal Meloun 		reg |= UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_SEL(0x2);
826e9034789SMichal Meloun 	else
827e9034789SMichal Meloun 		reg |= UPHY_PLL_S0_CTL4_PLL0_TXCLKREF_SEL(0x0);
828e9034789SMichal Meloun 
829e9034789SMichal Meloun 	/* XXX PLL0_XDIGCLK_EN */
830e9034789SMichal Meloun 	/*
831e9034789SMichal Meloun 	value &= ~(1 << 19);
832e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL4, reg);
833e9034789SMichal Meloun 	*/
834e9034789SMichal Meloun 
835e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
836e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL1_PLL0_FREQ_MDIV(~0);
837e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL1_PLL0_FREQ_NDIV(~0);
838e9034789SMichal Meloun 	if (usb)
839e9034789SMichal Meloun 		reg |= UPHY_PLL_S0_CTL1_PLL0_FREQ_NDIV(0x19);
840e9034789SMichal Meloun 	else
841e9034789SMichal Meloun 		reg |= UPHY_PLL_S0_CTL1_PLL0_FREQ_NDIV(0x1e);
842e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
843e9034789SMichal Meloun 
844e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
845e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL1_PLL0_IDDQ;
846e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
847e9034789SMichal Meloun 
848e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
849e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL1_PLL0_SLEEP(~0);
850e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
851e9034789SMichal Meloun 
852e9034789SMichal Meloun 	/* 3. Wait 100 ns. */
853e9034789SMichal Meloun 	DELAY(1);
854e9034789SMichal Meloun 
855e9034789SMichal Meloun 	/* XXX This in not in TRM */
856e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
857e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL4_PLL0_REFCLKBUF_EN;
858e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL4, reg);
859e9034789SMichal Meloun 
860e9034789SMichal Meloun 	/* 4. Calibration. */
861e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
862e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL2_PLL0_CAL_EN;
863e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2, reg);
864e9034789SMichal Meloun 	for (i = 30; i > 0; i--) {
865e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
866e9034789SMichal Meloun 		if (reg & UPHY_PLL_S0_CTL2_PLL0_CAL_DONE)
867e9034789SMichal Meloun 			break;
868e9034789SMichal Meloun 		DELAY(10);
869e9034789SMichal Meloun 	}
870e9034789SMichal Meloun 	if (i <= 0) {
871e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in calibration step 1 "
872e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
873e9034789SMichal Meloun 		rv = ETIMEDOUT;
874e9034789SMichal Meloun 		goto err;
875e9034789SMichal Meloun 	}
876e9034789SMichal Meloun 
877e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
878e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL2_PLL0_CAL_EN;
879e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2, reg);
880e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
881e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
882e9034789SMichal Meloun 		if ((reg & UPHY_PLL_S0_CTL2_PLL0_CAL_DONE) == 0)
883e9034789SMichal Meloun 			break;
884e9034789SMichal Meloun 		DELAY(10);
885e9034789SMichal Meloun 	}
886e9034789SMichal Meloun 	if (i <= 0) {
887e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in calibration step 2 "
888e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
889e9034789SMichal Meloun 		rv = ETIMEDOUT;
890e9034789SMichal Meloun 		goto err;
891e9034789SMichal Meloun 	}
892e9034789SMichal Meloun 
89356c202deSEd Maste 	/* 5. Enable the PLL (20 μs Lock time) */
894e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
895e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL1_PLL0_ENABLE;
896e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
897e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
898e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
899e9034789SMichal Meloun 		if (reg & UPHY_PLL_S0_CTL1_PLL0_LOCKDET_STATUS)
900e9034789SMichal Meloun 			break;
901e9034789SMichal Meloun 		DELAY(10);
902e9034789SMichal Meloun 	}
903e9034789SMichal Meloun 	if (i <= 0) {
904e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout while enabling PLL "
905e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
906e9034789SMichal Meloun 		rv = ETIMEDOUT;
907e9034789SMichal Meloun 		goto err;
908e9034789SMichal Meloun 	}
909e9034789SMichal Meloun 
910e9034789SMichal Meloun 	/* 6. RCAL. */
911e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
912e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL8_PLL0_RCAL_EN;
913e9034789SMichal Meloun 	reg |= UPHY_PLL_S0_CTL8_PLL0_RCAL_CLK_EN;
914e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8, reg);
915e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
916e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
917e9034789SMichal Meloun 		if (reg & UPHY_PLL_S0_CTL8_PLL0_RCAL_DONE)
918e9034789SMichal Meloun 			break;
919e9034789SMichal Meloun 		DELAY(10);
920e9034789SMichal Meloun 	}
921e9034789SMichal Meloun 	if (i <= 0) {
922e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in RX calibration step 1 "
923e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
924e9034789SMichal Meloun 		rv = ETIMEDOUT;
925e9034789SMichal Meloun 		goto err;
926e9034789SMichal Meloun 	}
927e9034789SMichal Meloun 
928e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
929e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL8_PLL0_RCAL_EN;
930e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8, reg);
931e9034789SMichal Meloun 	for (i = 10; i > 0; i--) {
932e9034789SMichal Meloun 		reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
933e9034789SMichal Meloun 		if (!(reg & UPHY_PLL_S0_CTL8_PLL0_RCAL_DONE))
934e9034789SMichal Meloun 			break;
935e9034789SMichal Meloun 		DELAY(10);
936e9034789SMichal Meloun 	}
937e9034789SMichal Meloun 	if (i <= 0) {
938e9034789SMichal Meloun 		device_printf(sc->dev, "Timedout in RX calibration step 2 "
939e9034789SMichal Meloun 		    "for pad '%s'.\n", pad->name);
940e9034789SMichal Meloun 		rv = ETIMEDOUT;
941e9034789SMichal Meloun 		goto err;
942e9034789SMichal Meloun 	}
943e9034789SMichal Meloun 
944e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
945e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL8_PLL0_RCAL_CLK_EN;
946e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8, reg);
947e9034789SMichal Meloun 
948e9034789SMichal Meloun 	/* Enable Hardware Power Sequencer. */
949e9034789SMichal Meloun 	tegra210_sata_pll_hw_control_enable();
950e9034789SMichal Meloun 
951e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
952e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL1_PLL0_PWR_OVRD;
953e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL1, reg);
954e9034789SMichal Meloun 
955e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
956e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL2_PLL0_CAL_OVRD;
957e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL2, reg);
958e9034789SMichal Meloun 
959e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
960e9034789SMichal Meloun 	reg &= ~UPHY_PLL_S0_CTL8_PLL0_RCAL_OVRD;
961e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_PLL_S0_CTL8, reg);
962e9034789SMichal Meloun 
963e9034789SMichal Meloun 	DELAY(50);
964e9034789SMichal Meloun 
965e9034789SMichal Meloun 	tegra210_sata_pll_hw_sequence_start();
966e9034789SMichal Meloun 
967e9034789SMichal Meloun 	sc->sata_ena_cnt++;
968e9034789SMichal Meloun 
969e9034789SMichal Meloun 	return (0);
970e9034789SMichal Meloun 
971e9034789SMichal Meloun err:
972e9034789SMichal Meloun 	hwreset_deassert(pad->reset);
973e9034789SMichal Meloun 	clk_disable(pad->clk);
974e9034789SMichal Meloun 	return (rv);
975e9034789SMichal Meloun }
976e9034789SMichal Meloun 
977e9034789SMichal Meloun static void
uphy_sata_disable(struct padctl_softc * sc,struct padctl_pad * pad)978e9034789SMichal Meloun uphy_sata_disable(struct padctl_softc *sc, struct padctl_pad *pad)
979e9034789SMichal Meloun {
980e9034789SMichal Meloun 	int rv;
981e9034789SMichal Meloun 
982e9034789SMichal Meloun 	sc->sata_ena_cnt--;
983e9034789SMichal Meloun 	if (sc->sata_ena_cnt <= 0) {
984e9034789SMichal Meloun 		rv = hwreset_assert(pad->reset);
985e9034789SMichal Meloun 		if (rv != 0) {
986e9034789SMichal Meloun 			device_printf(sc->dev, "Cannot reset pad '%s': %d\n",
987e9034789SMichal Meloun 			    pad->name, rv);
988e9034789SMichal Meloun 		}
989e9034789SMichal Meloun 		rv = clk_disable(pad->clk);
990e9034789SMichal Meloun 		if (rv != 0) {
991e9034789SMichal Meloun 			device_printf(sc->dev,
992e9034789SMichal Meloun 			    "Cannot dicable clock for pad '%s': %d\n",
993e9034789SMichal Meloun 			    pad->name, rv);
994e9034789SMichal Meloun 		}
995e9034789SMichal Meloun 	}
996e9034789SMichal Meloun }
997e9034789SMichal Meloun 
998e9034789SMichal Meloun 
999e9034789SMichal Meloun static int
usb3_port_init(struct padctl_softc * sc,struct padctl_port * port)1000e9034789SMichal Meloun usb3_port_init(struct padctl_softc *sc, struct padctl_port *port)
1001e9034789SMichal Meloun {
1002e9034789SMichal Meloun 	uint32_t reg;
1003e9034789SMichal Meloun 	struct padctl_pad *pad;
1004e9034789SMichal Meloun 	int rv;
1005e9034789SMichal Meloun 
1006e9034789SMichal Meloun 	pad = port->lane->pad;
1007e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_SS_PORT_MAP);
1008e9034789SMichal Meloun 	if (port->internal)
1009e9034789SMichal Meloun 		reg &= ~SS_PORT_MAP_PORT_INTERNAL(port->idx);
1010e9034789SMichal Meloun 	else
1011e9034789SMichal Meloun 		reg |= SS_PORT_MAP_PORT_INTERNAL(port->idx);
1012e9034789SMichal Meloun 	reg &= ~SS_PORT_MAP_PORT_MAP(port->idx, ~0);
1013e9034789SMichal Meloun 	reg |= SS_PORT_MAP_PORT_MAP(port->idx, port->companion);
1014e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_SS_PORT_MAP, reg);
1015e9034789SMichal Meloun 
1016e9034789SMichal Meloun 	if (port->supply_vbus != NULL) {
1017e9034789SMichal Meloun 		rv = regulator_enable(port->supply_vbus);
1018e9034789SMichal Meloun 		if (rv != 0) {
1019e9034789SMichal Meloun 			device_printf(sc->dev,
1020e9034789SMichal Meloun 			    "Cannot enable vbus regulator\n");
1021e9034789SMichal Meloun 			return (rv);
1022e9034789SMichal Meloun 		}
1023e9034789SMichal Meloun 	}
1024e9034789SMichal Meloun 
1025e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL1(port->idx));
1026e9034789SMichal Meloun 	reg &= ~UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL(~0);
1027e9034789SMichal Meloun 	reg |= UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL(2);
1028e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL1(port->idx), reg);
1029e9034789SMichal Meloun 
1030e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL2(port->idx));
1031e9034789SMichal Meloun 	reg &= ~UPHY_USB3_PAD_ECTL2_RX_CTLE(~0);
1032e9034789SMichal Meloun 	reg |= UPHY_USB3_PAD_ECTL2_RX_CTLE(0x00fc);
1033e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL2(port->idx), reg);
1034e9034789SMichal Meloun 
1035e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3(port->idx), 0xc0077f1f);
1036e9034789SMichal Meloun 
1037e9034789SMichal Meloun 	reg = RD4(sc,  XUSB_PADCTL_UPHY_USB3_PAD_ECTL4(port->idx));
1038e9034789SMichal Meloun 	reg &= ~UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL(~0);
1039e9034789SMichal Meloun 	reg |= UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL(0x01c7);
1040e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL4(port->idx), reg);
1041e9034789SMichal Meloun 
1042e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6(port->idx), 0xfcf01368);
1043e9034789SMichal Meloun 
1044e9034789SMichal Meloun 	if (pad->type == PADCTL_PAD_SATA)
1045e9034789SMichal Meloun 		rv = uphy_sata_enable(sc, pad, true);
1046e9034789SMichal Meloun 	else
1047e9034789SMichal Meloun 		rv = uphy_pex_enable(sc, pad);
1048e9034789SMichal Meloun 	if (rv != 0)
1049e9034789SMichal Meloun 		return (rv);
1050e9034789SMichal Meloun 
1051e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1052e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_SSP_ELPG_VCORE_DOWN(port->idx);
1053e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1054e9034789SMichal Meloun 	DELAY(100);
1055e9034789SMichal Meloun 
1056e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1057e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_SSP_ELPG_CLAMP_EN_EARLY(port->idx);
1058e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1059e9034789SMichal Meloun 	DELAY(100);
1060e9034789SMichal Meloun 
1061e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1062e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_SSP_ELPG_CLAMP_EN(port->idx);
1063e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1064e9034789SMichal Meloun 	DELAY(100);
1065e9034789SMichal Meloun 
1066e9034789SMichal Meloun 	return (0);
1067e9034789SMichal Meloun }
1068e9034789SMichal Meloun 
1069e9034789SMichal Meloun static int
pcie_enable(struct padctl_softc * sc,struct padctl_lane * lane)1070e9034789SMichal Meloun pcie_enable(struct padctl_softc *sc, struct padctl_lane *lane)
1071e9034789SMichal Meloun {
1072e9034789SMichal Meloun 	uint32_t reg;
1073e9034789SMichal Meloun 	int rv;
1074e9034789SMichal Meloun 
1075e9034789SMichal Meloun 	rv = uphy_pex_enable(sc, lane->pad);
1076e9034789SMichal Meloun 	if (rv != 0)
1077e9034789SMichal Meloun 		return (rv);
1078e9034789SMichal Meloun 
1079e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
1080e9034789SMichal Meloun 	reg |= USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
1081e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
1082e9034789SMichal Meloun 
1083e9034789SMichal Meloun 	return (0);
1084e9034789SMichal Meloun }
1085e9034789SMichal Meloun 
1086e9034789SMichal Meloun static int
pcie_disable(struct padctl_softc * sc,struct padctl_lane * lane)1087e9034789SMichal Meloun pcie_disable(struct padctl_softc *sc, struct padctl_lane *lane)
1088e9034789SMichal Meloun {
1089e9034789SMichal Meloun 	uint32_t reg;
1090e9034789SMichal Meloun 
1091e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
1092e9034789SMichal Meloun 	reg &= ~USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
1093e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
1094e9034789SMichal Meloun 
1095e9034789SMichal Meloun 	uphy_pex_disable(sc, lane->pad);
1096e9034789SMichal Meloun 
1097e9034789SMichal Meloun 	return (0);
1098e9034789SMichal Meloun 
1099e9034789SMichal Meloun }
1100e9034789SMichal Meloun 
1101e9034789SMichal Meloun static int
sata_enable(struct padctl_softc * sc,struct padctl_lane * lane)1102e9034789SMichal Meloun sata_enable(struct padctl_softc *sc, struct padctl_lane *lane)
1103e9034789SMichal Meloun {
1104e9034789SMichal Meloun 	uint32_t reg;
1105e9034789SMichal Meloun 	int rv;
1106e9034789SMichal Meloun 
1107e9034789SMichal Meloun 	rv = uphy_sata_enable(sc, lane->pad, false);
1108e9034789SMichal Meloun 	if (rv != 0)
1109e9034789SMichal Meloun 		return (rv);
1110e9034789SMichal Meloun 
1111e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
1112e9034789SMichal Meloun 	reg |= USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->idx);
1113e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
1114e9034789SMichal Meloun 
1115e9034789SMichal Meloun 	return (0);
1116e9034789SMichal Meloun }
1117e9034789SMichal Meloun 
1118e9034789SMichal Meloun static int
sata_disable(struct padctl_softc * sc,struct padctl_lane * lane)1119e9034789SMichal Meloun sata_disable(struct padctl_softc *sc, struct padctl_lane *lane)
1120e9034789SMichal Meloun {
1121e9034789SMichal Meloun 	uint32_t reg;
1122e9034789SMichal Meloun 
1123e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
1124e9034789SMichal Meloun 	reg &= ~USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->idx);
1125e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
1126e9034789SMichal Meloun 
1127e9034789SMichal Meloun 	uphy_sata_disable(sc, lane->pad);
1128e9034789SMichal Meloun 
1129e9034789SMichal Meloun 	return (0);
1130e9034789SMichal Meloun }
1131e9034789SMichal Meloun 
1132e9034789SMichal Meloun static int
hsic_enable(struct padctl_softc * sc,struct padctl_lane * lane)1133e9034789SMichal Meloun hsic_enable(struct padctl_softc *sc, struct padctl_lane *lane)
1134e9034789SMichal Meloun {
1135e9034789SMichal Meloun 	uint32_t reg;
1136e9034789SMichal Meloun 	struct padctl_pad *pad;
1137e9034789SMichal Meloun 	struct padctl_port *port;
1138e9034789SMichal Meloun 	int rv;
1139e9034789SMichal Meloun 
1140e9034789SMichal Meloun 	port = search_lane_port(sc, lane);
1141e9034789SMichal Meloun 	if (port == NULL) {
1142e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find port for lane: %s\n",
1143e9034789SMichal Meloun 		    lane->name);
1144e9034789SMichal Meloun 	}
1145e9034789SMichal Meloun 	pad = lane->pad;
1146e9034789SMichal Meloun 
1147e9034789SMichal Meloun 	if (port->supply_vbus != NULL) {
1148e9034789SMichal Meloun 		rv = regulator_enable(port->supply_vbus);
1149e9034789SMichal Meloun 		if (rv != 0) {
1150e9034789SMichal Meloun 			device_printf(sc->dev,
1151e9034789SMichal Meloun 			    "Cannot enable vbus regulator\n");
1152e9034789SMichal Meloun 			return (rv);
1153e9034789SMichal Meloun 		}
1154e9034789SMichal Meloun 	}
1155e9034789SMichal Meloun 
1156e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL, sc->strobe_trim);
1157e9034789SMichal Meloun 
1158e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_CTL1(lane->idx));
1159e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL1_TX_RTUNEP(~0);
1160e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL1_TX_RTUNEP(sc->tx_rtune_p);
1161e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_CTL1(lane->idx), reg);
1162e9034789SMichal Meloun 
1163e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_CTL2(lane->idx));
1164e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL2_RX_STROBE_TRIM(~0);
1165e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL2_RX_DATA1_TRIM(~0);
1166e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL2_RX_DATA0_TRIM(~0);
1167e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL2_RX_STROBE_TRIM(sc->rx_strobe_trim);
1168e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL2_RX_DATA1_TRIM(sc->rx_data1_trim);
1169e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL2_RX_DATA0_TRIM(sc->rx_data0_trim);
1170e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_CTL2(lane->idx), reg);
1171e9034789SMichal Meloun 
1172e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_CTL0(lane->idx));
1173e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_RPU_DATA0;
1174e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_RPU_DATA1;
1175e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_RPU_STROBE;
1176e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_RX_DATA0;
1177e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_RX_DATA1;
1178e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_RX_STROBE;
1179e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_ZI_DATA0;
1180e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_ZI_DATA1;
1181e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_ZI_STROBE;
1182e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_TX_DATA0;
1183e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_TX_DATA1;
1184e9034789SMichal Meloun 	reg &= ~HSIC_PAD_CTL0_PD_TX_STROBE;
1185e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_RPD_DATA0;
1186e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_RPD_DATA1;
1187e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_RPD_STROBE;
1188e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_CTL0(lane->idx), reg);
1189e9034789SMichal Meloun 
1190e9034789SMichal Meloun 	rv = clk_enable(pad->clk);
1191e9034789SMichal Meloun 	if (rv < 0) {
1192e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot enable clock for pad '%s': %d\n",
1193e9034789SMichal Meloun 		    pad->name, rv);
1194e9034789SMichal Meloun 		if (port->supply_vbus != NULL)
1195e9034789SMichal Meloun 			regulator_disable(port->supply_vbus);
1196e9034789SMichal Meloun 		return (rv);
1197e9034789SMichal Meloun 	}
1198e9034789SMichal Meloun 
1199e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
1200e9034789SMichal Meloun 	reg &= ~HSIC_PAD_TRK_CTL_TRK_START_TIMER(~0);
1201e9034789SMichal Meloun 	reg &= ~HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER(~0);
1202e9034789SMichal Meloun 	reg |= HSIC_PAD_TRK_CTL_TRK_START_TIMER(0x1e);
1203e9034789SMichal Meloun 	reg |= HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER(0x0a);
1204e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_TRK_CTL, reg);
1205e9034789SMichal Meloun 
1206e9034789SMichal Meloun 	DELAY(10);
1207e9034789SMichal Meloun 
1208e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
1209e9034789SMichal Meloun 	reg &= ~HSIC_PAD_TRK_CTL_PD_TRK;
1210e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_TRK_CTL, reg);
1211e9034789SMichal Meloun 
1212e9034789SMichal Meloun 	DELAY(50);
1213e9034789SMichal Meloun 	clk_disable(pad->clk);
1214e9034789SMichal Meloun 	return (0);
1215e9034789SMichal Meloun }
1216e9034789SMichal Meloun 
1217e9034789SMichal Meloun static int
hsic_disable(struct padctl_softc * sc,struct padctl_lane * lane)1218e9034789SMichal Meloun hsic_disable(struct padctl_softc *sc, struct padctl_lane *lane)
1219e9034789SMichal Meloun {
1220e9034789SMichal Meloun 	uint32_t reg;
1221e9034789SMichal Meloun 	struct padctl_port *port;
1222e9034789SMichal Meloun 	int rv;
1223e9034789SMichal Meloun 
1224e9034789SMichal Meloun 	port = search_lane_port(sc, lane);
1225e9034789SMichal Meloun 	if (port == NULL) {
1226e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find port for lane: %s\n",
1227e9034789SMichal Meloun 		    lane->name);
1228e9034789SMichal Meloun 	}
1229e9034789SMichal Meloun 
1230e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_HSIC_PAD_CTL0(lane->idx));
1231e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_RX_DATA0;
1232e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_RX_DATA1;
1233e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_RX_STROBE;
1234e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_ZI_DATA0;
1235e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_ZI_DATA1;
1236e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_ZI_STROBE;
1237e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_TX_DATA0;
1238e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_TX_DATA1;
1239e9034789SMichal Meloun 	reg |= HSIC_PAD_CTL0_PD_TX_STROBE;
1240e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_HSIC_PAD_CTL1(lane->idx), reg);
1241e9034789SMichal Meloun 
1242e9034789SMichal Meloun 	if (port->supply_vbus != NULL) {
1243e9034789SMichal Meloun 		rv = regulator_disable(port->supply_vbus);
1244e9034789SMichal Meloun 		if (rv != 0) {
1245e9034789SMichal Meloun 			device_printf(sc->dev,
1246e9034789SMichal Meloun 			    "Cannot disable vbus regulator\n");
1247e9034789SMichal Meloun 			return (rv);
1248e9034789SMichal Meloun 		}
1249e9034789SMichal Meloun 	}
1250e9034789SMichal Meloun 
1251e9034789SMichal Meloun 	return (0);
1252e9034789SMichal Meloun }
1253e9034789SMichal Meloun 
1254e9034789SMichal Meloun static int
usb2_enable(struct padctl_softc * sc,struct padctl_lane * lane)1255e9034789SMichal Meloun usb2_enable(struct padctl_softc *sc, struct padctl_lane *lane)
1256e9034789SMichal Meloun {
1257e9034789SMichal Meloun 	uint32_t reg;
1258e9034789SMichal Meloun 	struct padctl_pad *pad;
1259e9034789SMichal Meloun 	struct padctl_port *port;
1260e9034789SMichal Meloun 	int rv;
1261e9034789SMichal Meloun 
1262e9034789SMichal Meloun 	port = search_lane_port(sc, lane);
1263e9034789SMichal Meloun 	if (port == NULL) {
1264e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find port for lane: %s\n",
1265e9034789SMichal Meloun 		    lane->name);
1266e9034789SMichal Meloun 	}
1267e9034789SMichal Meloun 	pad = lane->pad;
1268e9034789SMichal Meloun 
1269e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
1270e9034789SMichal Meloun 	reg &= ~USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(~0);
1271e9034789SMichal Meloun 	reg &= ~USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(~0);
1272e9034789SMichal Meloun 	reg |= USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(0x7);
1273e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
1274e9034789SMichal Meloun 
1275e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_PORT_CAP);
1276e9034789SMichal Meloun 	reg &= ~USB2_PORT_CAP_PORT_CAP(lane->idx, ~0);
1277e9034789SMichal Meloun 	reg |= USB2_PORT_CAP_PORT_CAP(lane->idx, USB2_PORT_CAP_PORT_CAP_HOST);
1278e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_PORT_CAP, reg);
1279e9034789SMichal Meloun 
1280e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx));
1281e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(~0);
1282e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL0_HS_SLEW(~0);
1283e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL0_PD;
1284e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL0_PD2;
1285e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL0_PD_ZI;
1286e9034789SMichal Meloun 	reg |= USB2_OTG_PAD_CTL0_HS_SLEW(14);
1287e9034789SMichal Meloun 	reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level[lane->idx] +
1288e9034789SMichal Meloun 	    sc->hs_curr_level_offs);
1289e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx), reg);
1290e9034789SMichal Meloun 
1291e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx));
1292e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(~0);
1293e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL1_RPD_CTRL(~0);
1294e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL1_PD_DR;
1295e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL1_PD_CHRP_OVRD;
1296e9034789SMichal Meloun 	reg &= ~USB2_OTG_PAD_CTL1_PD_DISC_OVRD;
1297e9034789SMichal Meloun 	reg |= USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(sc->hs_term_range_adj);
1298e9034789SMichal Meloun 	reg |= USB2_OTG_PAD_CTL1_RPD_CTRL(sc->rpd_ctrl);
1299e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx), reg);
1300e9034789SMichal Meloun 
1301e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1(lane->idx));
1302e9034789SMichal Meloun 	reg &= ~USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV(~0);
1303e9034789SMichal Meloun 	reg |= USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18;
1304e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1(lane->idx), reg);
1305e9034789SMichal Meloun 
1306e9034789SMichal Meloun 	if (port->supply_vbus != NULL) {
1307e9034789SMichal Meloun 		rv = regulator_enable(port->supply_vbus);
1308e9034789SMichal Meloun 		if (rv != 0) {
1309e9034789SMichal Meloun 			device_printf(sc->dev,
1310e9034789SMichal Meloun 			    "Cannot enable vbus regulator\n");
1311e9034789SMichal Meloun 			return (rv);
1312e9034789SMichal Meloun 		}
1313e9034789SMichal Meloun 	}
1314e9034789SMichal Meloun 	rv = clk_enable(pad->clk);
1315e9034789SMichal Meloun 	if (rv < 0) {
1316e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot enable clock for pad '%s': %d\n",
1317e9034789SMichal Meloun 		    pad->name, rv);
1318e9034789SMichal Meloun 		if (port->supply_vbus != NULL)
1319e9034789SMichal Meloun 			regulator_disable(port->supply_vbus);
1320e9034789SMichal Meloun 		return (rv);
1321e9034789SMichal Meloun 	}
1322e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
1323e9034789SMichal Meloun 	reg &= ~USB2_BIAS_PAD_CTL1_TRK_START_TIMER(~0);
1324e9034789SMichal Meloun 	reg &= ~USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER(~0);
1325e9034789SMichal Meloun 	reg |= USB2_BIAS_PAD_CTL1_TRK_START_TIMER(0x1e);
1326e9034789SMichal Meloun 	reg |= USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER(0x0a);
1327e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL1, reg);
1328e9034789SMichal Meloun 
1329e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
1330e9034789SMichal Meloun 	reg &= ~USB2_BIAS_PAD_CTL0_PD;
1331e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
1332e9034789SMichal Meloun 	return (0);
1333e9034789SMichal Meloun }
1334e9034789SMichal Meloun 
1335e9034789SMichal Meloun static int
usb2_disable(struct padctl_softc * sc,struct padctl_lane * lane)1336e9034789SMichal Meloun usb2_disable(struct padctl_softc *sc, struct padctl_lane *lane)
1337e9034789SMichal Meloun {
1338e9034789SMichal Meloun 	uint32_t reg;
1339e9034789SMichal Meloun 	struct padctl_pad *pad;
1340e9034789SMichal Meloun 	struct padctl_port *port;
1341e9034789SMichal Meloun 	int rv;
1342e9034789SMichal Meloun 
1343e9034789SMichal Meloun 	port = search_lane_port(sc, lane);
1344e9034789SMichal Meloun 	if (port == NULL) {
1345e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find port for lane: %s\n",
1346e9034789SMichal Meloun 		    lane->name);
1347e9034789SMichal Meloun 	}
1348e9034789SMichal Meloun 	pad = lane->pad;
1349e9034789SMichal Meloun 
1350e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
1351e9034789SMichal Meloun 	reg |= USB2_BIAS_PAD_CTL0_PD;
1352e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
1353e9034789SMichal Meloun 
1354e9034789SMichal Meloun 	if (port->supply_vbus != NULL) {
1355e9034789SMichal Meloun 		rv = regulator_disable(port->supply_vbus);
1356e9034789SMichal Meloun 		if (rv != 0) {
1357e9034789SMichal Meloun 			device_printf(sc->dev,
1358e9034789SMichal Meloun 			    "Cannot disable vbus regulator\n");
1359e9034789SMichal Meloun 			return (rv);
1360e9034789SMichal Meloun 		}
1361e9034789SMichal Meloun 	}
1362e9034789SMichal Meloun 
1363e9034789SMichal Meloun 	rv = clk_disable(pad->clk);
1364e9034789SMichal Meloun 	if (rv < 0) {
1365e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot disable clock for pad '%s': %d\n",
1366e9034789SMichal Meloun 		    pad->name, rv);
1367e9034789SMichal Meloun 		return (rv);
1368e9034789SMichal Meloun 	}
1369e9034789SMichal Meloun 
1370e9034789SMichal Meloun 	return (0);
1371e9034789SMichal Meloun }
1372e9034789SMichal Meloun 
1373e9034789SMichal Meloun 
1374e9034789SMichal Meloun static int
pad_common_enable(struct padctl_softc * sc)1375e9034789SMichal Meloun pad_common_enable(struct padctl_softc *sc)
1376e9034789SMichal Meloun {
1377e9034789SMichal Meloun 	uint32_t reg;
1378e9034789SMichal Meloun 
1379e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1380e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
1381e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1382e9034789SMichal Meloun 	DELAY(100);
1383e9034789SMichal Meloun 
1384e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1385e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
1386e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1387e9034789SMichal Meloun 	DELAY(100);
1388e9034789SMichal Meloun 
1389e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1390e9034789SMichal Meloun 	reg &= ~ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
1391e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1392e9034789SMichal Meloun 	DELAY(100);
1393e9034789SMichal Meloun 
1394e9034789SMichal Meloun 	return (0);
1395e9034789SMichal Meloun }
1396e9034789SMichal Meloun 
1397e9034789SMichal Meloun static int
pad_common_disable(struct padctl_softc * sc)1398e9034789SMichal Meloun pad_common_disable(struct padctl_softc *sc)
1399e9034789SMichal Meloun {
1400e9034789SMichal Meloun 	uint32_t reg;
1401e9034789SMichal Meloun 
1402e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1403e9034789SMichal Meloun 	reg |= ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
1404e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1405e9034789SMichal Meloun 	DELAY(100);
1406e9034789SMichal Meloun 
1407e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1408e9034789SMichal Meloun 	reg |= ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
1409e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1410e9034789SMichal Meloun 	DELAY(100);
1411e9034789SMichal Meloun 
1412e9034789SMichal Meloun 	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM1);
1413e9034789SMichal Meloun 	reg |= ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
1414e9034789SMichal Meloun 	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM1, reg);
1415e9034789SMichal Meloun 	DELAY(100);
1416e9034789SMichal Meloun 
1417e9034789SMichal Meloun 	return (0);
1418e9034789SMichal Meloun }
1419e9034789SMichal Meloun 
1420e9034789SMichal Meloun static int
xusbpadctl_phy_enable(struct phynode * phy,bool enable)1421e9034789SMichal Meloun xusbpadctl_phy_enable(struct phynode *phy, bool enable)
1422e9034789SMichal Meloun {
1423e9034789SMichal Meloun 	device_t dev;
1424e9034789SMichal Meloun 	intptr_t id;
1425e9034789SMichal Meloun 	struct padctl_softc *sc;
1426e9034789SMichal Meloun 	struct padctl_lane *lane;
1427e9034789SMichal Meloun 	struct padctl_pad *pad;
1428e9034789SMichal Meloun 	int rv;
1429e9034789SMichal Meloun 
1430e9034789SMichal Meloun 	dev = phynode_get_device(phy);
1431e9034789SMichal Meloun 	id = phynode_get_id(phy);
1432e9034789SMichal Meloun 	sc = device_get_softc(dev);
1433e9034789SMichal Meloun 
1434e9034789SMichal Meloun 	if (id < 0 || id >= nitems(lanes_tbl)) {
1435e9034789SMichal Meloun 		device_printf(dev, "Unknown phy: %d\n", (int)id);
1436e9034789SMichal Meloun 		return (ENXIO);
1437e9034789SMichal Meloun 	}
1438e9034789SMichal Meloun 
1439e9034789SMichal Meloun 	lane = lanes_tbl + id;
1440e9034789SMichal Meloun 	if (!lane->enabled) {
1441e9034789SMichal Meloun 		device_printf(dev, "Lane is not enabled/configured: %s\n",
1442e9034789SMichal Meloun 		    lane->name);
1443e9034789SMichal Meloun 		return (ENXIO);
1444e9034789SMichal Meloun 	}
1445e9034789SMichal Meloun 
1446e9034789SMichal Meloun 	pad = lane->pad;
1447e9034789SMichal Meloun 	if (enable) {
1448e9034789SMichal Meloun 		if (sc->phy_ena_cnt == 0) {
1449e9034789SMichal Meloun 			rv = pad_common_enable(sc);
1450e9034789SMichal Meloun 			if (rv != 0)
1451e9034789SMichal Meloun 				return (rv);
1452e9034789SMichal Meloun 		}
1453e9034789SMichal Meloun 		sc->phy_ena_cnt++;
1454e9034789SMichal Meloun 	}
1455e9034789SMichal Meloun 
1456e9034789SMichal Meloun 	if (enable)
1457e9034789SMichal Meloun 		rv = pad->enable(sc, lane);
1458e9034789SMichal Meloun 	else
1459e9034789SMichal Meloun 		rv = pad->disable(sc, lane);
1460e9034789SMichal Meloun 	if (rv != 0)
1461e9034789SMichal Meloun 		return (rv);
1462e9034789SMichal Meloun 
1463e9034789SMichal Meloun 	if (!enable) {
1464e9034789SMichal Meloun 		 if (sc->phy_ena_cnt == 1) {
1465e9034789SMichal Meloun 			rv = pad_common_disable(sc);
1466e9034789SMichal Meloun 			if (rv != 0)
1467e9034789SMichal Meloun 				return (rv);
1468e9034789SMichal Meloun 		}
1469e9034789SMichal Meloun 		sc->phy_ena_cnt--;
1470e9034789SMichal Meloun 	}
1471e9034789SMichal Meloun 
1472e9034789SMichal Meloun 	return (0);
1473e9034789SMichal Meloun }
1474e9034789SMichal Meloun 
1475e9034789SMichal Meloun /* -------------------------------------------------------------------------
1476e9034789SMichal Meloun  *
1477e9034789SMichal Meloun  *   FDT processing
1478e9034789SMichal Meloun  */
1479e9034789SMichal Meloun static struct padctl_port *
search_port(struct padctl_softc * sc,char * port_name)1480e9034789SMichal Meloun search_port(struct padctl_softc *sc, char *port_name)
1481e9034789SMichal Meloun {
1482e9034789SMichal Meloun 	int i;
1483e9034789SMichal Meloun 
1484e9034789SMichal Meloun 	for (i = 0; i < nitems(ports_tbl); i++) {
1485e9034789SMichal Meloun 		if (strcmp(port_name, ports_tbl[i].name) == 0)
1486e9034789SMichal Meloun 			return (&ports_tbl[i]);
1487e9034789SMichal Meloun 	}
1488e9034789SMichal Meloun 	return (NULL);
1489e9034789SMichal Meloun }
1490e9034789SMichal Meloun 
1491e9034789SMichal Meloun static struct padctl_port *
search_lane_port(struct padctl_softc * sc,struct padctl_lane * lane)1492e9034789SMichal Meloun search_lane_port(struct padctl_softc *sc, struct padctl_lane *lane)
1493e9034789SMichal Meloun {
1494e9034789SMichal Meloun 	int i;
1495e9034789SMichal Meloun 
1496e9034789SMichal Meloun 	for (i = 0; i < nitems(ports_tbl); i++) {
1497e9034789SMichal Meloun 		if (!ports_tbl[i].enabled)
1498e9034789SMichal Meloun 			continue;
1499e9034789SMichal Meloun 		if (ports_tbl[i].lane == lane)
1500e9034789SMichal Meloun 			return (ports_tbl + i);
1501e9034789SMichal Meloun 	}
1502e9034789SMichal Meloun 	return (NULL);
1503e9034789SMichal Meloun }
1504e9034789SMichal Meloun 
1505e9034789SMichal Meloun static struct padctl_lane *
search_lane(struct padctl_softc * sc,char * lane_name)1506e9034789SMichal Meloun search_lane(struct padctl_softc *sc, char *lane_name)
1507e9034789SMichal Meloun {
1508e9034789SMichal Meloun 	int i;
1509e9034789SMichal Meloun 
1510e9034789SMichal Meloun 	for (i = 0; i < nitems(lanes_tbl); i++) {
1511e9034789SMichal Meloun 		if (strcmp(lane_name, lanes_tbl[i].name) == 0)
1512e9034789SMichal Meloun 			return 	(lanes_tbl + i);
1513e9034789SMichal Meloun 	}
1514e9034789SMichal Meloun 	return (NULL);
1515e9034789SMichal Meloun }
1516e9034789SMichal Meloun 
1517e9034789SMichal Meloun static struct padctl_lane *
search_pad_lane(struct padctl_softc * sc,enum padctl_pad_type type,int idx)1518e9034789SMichal Meloun search_pad_lane(struct padctl_softc *sc, enum padctl_pad_type type, int idx)
1519e9034789SMichal Meloun {
1520e9034789SMichal Meloun 	int i;
1521e9034789SMichal Meloun 
1522e9034789SMichal Meloun 	for (i = 0; i < nitems(lanes_tbl); i++) {
1523e9034789SMichal Meloun 		if (!lanes_tbl[i].enabled)
1524e9034789SMichal Meloun 			continue;
1525e9034789SMichal Meloun 		if (type == lanes_tbl[i].pad->type && idx == lanes_tbl[i].idx)
1526e9034789SMichal Meloun 			return 	(lanes_tbl + i);
1527e9034789SMichal Meloun 	}
1528e9034789SMichal Meloun 	return (NULL);
1529e9034789SMichal Meloun }
1530e9034789SMichal Meloun 
1531e9034789SMichal Meloun static struct padctl_lane *
search_usb3_pad_lane(struct padctl_softc * sc,int idx)1532e9034789SMichal Meloun search_usb3_pad_lane(struct padctl_softc *sc, int idx)
1533e9034789SMichal Meloun {
1534e9034789SMichal Meloun 	int i;
1535e9034789SMichal Meloun 	struct padctl_lane *lane, *tmp;
1536e9034789SMichal Meloun 
1537e9034789SMichal Meloun 	lane = NULL;
1538e9034789SMichal Meloun 	for (i = 0; i < nitems(lane_map_tbl); i++) {
1539e9034789SMichal Meloun 		if (idx != lane_map_tbl[i].port_idx)
1540e9034789SMichal Meloun 			continue;
1541e9034789SMichal Meloun 		tmp = search_pad_lane(sc, lane_map_tbl[i].pad_type,
1542e9034789SMichal Meloun 		    lane_map_tbl[i].lane_idx);
1543e9034789SMichal Meloun 		if (tmp == NULL)
1544e9034789SMichal Meloun 			continue;
1545e9034789SMichal Meloun 		if (strcmp(tmp->mux[tmp->mux_idx], "usb3-ss") != 0)
1546e9034789SMichal Meloun 			continue;
1547e9034789SMichal Meloun 		if (lane != NULL) {
1548e9034789SMichal Meloun 			device_printf(sc->dev, "Duplicated mappings found for"
1549e9034789SMichal Meloun 			 " lanes: %s and %s\n", lane->name, tmp->name);
1550e9034789SMichal Meloun 			return (NULL);
1551e9034789SMichal Meloun 		}
1552e9034789SMichal Meloun 		lane = tmp;
1553e9034789SMichal Meloun 	}
1554e9034789SMichal Meloun 	return (lane);
1555e9034789SMichal Meloun }
1556e9034789SMichal Meloun 
1557e9034789SMichal Meloun static struct padctl_pad *
search_pad(struct padctl_softc * sc,char * pad_name)1558e9034789SMichal Meloun search_pad(struct padctl_softc *sc, char *pad_name)
1559e9034789SMichal Meloun {
1560e9034789SMichal Meloun 	int i;
1561e9034789SMichal Meloun 
1562e9034789SMichal Meloun 	for (i = 0; i < nitems(pads_tbl); i++) {
1563e9034789SMichal Meloun 		if (strcmp(pad_name, pads_tbl[i].name) == 0)
1564e9034789SMichal Meloun 			return 	(pads_tbl + i);
1565e9034789SMichal Meloun 	}
1566e9034789SMichal Meloun 	return (NULL);
1567e9034789SMichal Meloun }
1568e9034789SMichal Meloun 
1569e9034789SMichal Meloun static int
search_mux(struct padctl_softc * sc,struct padctl_lane * lane,char * fnc_name)1570e9034789SMichal Meloun search_mux(struct padctl_softc *sc, struct padctl_lane *lane, char *fnc_name)
1571e9034789SMichal Meloun {
1572e9034789SMichal Meloun 	int i;
1573e9034789SMichal Meloun 
1574e9034789SMichal Meloun 	for (i = 0; i < lane->nmux; i++) {
1575e9034789SMichal Meloun 		if (strcmp(fnc_name, lane->mux[i]) == 0)
1576e9034789SMichal Meloun 			return 	(i);
1577e9034789SMichal Meloun 	}
1578e9034789SMichal Meloun 	return (-1);
1579e9034789SMichal Meloun }
1580e9034789SMichal Meloun 
1581e9034789SMichal Meloun static int
config_lane(struct padctl_softc * sc,struct padctl_lane * lane)1582e9034789SMichal Meloun config_lane(struct padctl_softc *sc, struct padctl_lane *lane)
1583e9034789SMichal Meloun {
1584e9034789SMichal Meloun 	uint32_t reg;
1585e9034789SMichal Meloun 
1586e9034789SMichal Meloun 	reg = RD4(sc, lane->reg);
1587e9034789SMichal Meloun 	reg &= ~(lane->mask << lane->shift);
1588e9034789SMichal Meloun 	reg |=  (lane->mux_idx & lane->mask) << lane->shift;
1589e9034789SMichal Meloun 	WR4(sc, lane->reg, reg);
1590e9034789SMichal Meloun 	return (0);
1591e9034789SMichal Meloun }
1592e9034789SMichal Meloun 
1593e9034789SMichal Meloun static int
process_lane(struct padctl_softc * sc,phandle_t node,struct padctl_pad * pad)1594e9034789SMichal Meloun process_lane(struct padctl_softc *sc, phandle_t node, struct padctl_pad *pad)
1595e9034789SMichal Meloun {
1596e9034789SMichal Meloun 	struct padctl_lane *lane;
1597e9034789SMichal Meloun 	struct phynode *phynode;
1598e9034789SMichal Meloun 	struct phynode_init_def phy_init;
1599e9034789SMichal Meloun 	char *name;
1600e9034789SMichal Meloun 	char *function;
1601e9034789SMichal Meloun 	int rv;
1602e9034789SMichal Meloun 
1603e9034789SMichal Meloun 	name = NULL;
1604e9034789SMichal Meloun 	function = NULL;
1605e9034789SMichal Meloun 	rv = OF_getprop_alloc(node, "name", (void **)&name);
1606e9034789SMichal Meloun 	if (rv <= 0) {
1607e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read lane name.\n");
1608e9034789SMichal Meloun 		return (ENXIO);
1609e9034789SMichal Meloun 	}
1610e9034789SMichal Meloun 
1611e9034789SMichal Meloun 	lane = search_lane(sc, name);
1612e9034789SMichal Meloun 	if (lane == NULL) {
1613e9034789SMichal Meloun 		device_printf(sc->dev, "Unknown lane: %s\n", name);
1614e9034789SMichal Meloun 		rv = ENXIO;
1615e9034789SMichal Meloun 		goto end;
1616e9034789SMichal Meloun 	}
1617e9034789SMichal Meloun 
1618e9034789SMichal Meloun 	/* Read function (mux) settings. */
1619e9034789SMichal Meloun 	rv = OF_getprop_alloc(node, "nvidia,function", (void **)&function);
1620e9034789SMichal Meloun 	if (rv <= 0) {
1621e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read lane function.\n");
1622e9034789SMichal Meloun 		rv = ENXIO;
1623e9034789SMichal Meloun 		goto end;
1624e9034789SMichal Meloun 	}
1625e9034789SMichal Meloun 
1626e9034789SMichal Meloun 	lane->mux_idx = search_mux(sc, lane, function);
1627e9034789SMichal Meloun 	if (lane->mux_idx == ~0) {
1628e9034789SMichal Meloun 		device_printf(sc->dev, "Unknown function %s for lane %s\n",
1629e9034789SMichal Meloun 		    function, name);
1630e9034789SMichal Meloun 		rv = ENXIO;
1631e9034789SMichal Meloun 		goto end;
1632e9034789SMichal Meloun 	}
1633e9034789SMichal Meloun 
1634e9034789SMichal Meloun 	rv = config_lane(sc, lane);
1635e9034789SMichal Meloun 	if (rv != 0) {
1636e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot configure lane: %s: %d\n",
1637e9034789SMichal Meloun 		    name, rv);
1638e9034789SMichal Meloun 		rv = ENXIO;
1639e9034789SMichal Meloun 		goto end;
1640e9034789SMichal Meloun 	}
1641e9034789SMichal Meloun 	lane->xref = OF_xref_from_node(node);
1642e9034789SMichal Meloun 	lane->pad = pad;
1643e9034789SMichal Meloun 	lane->enabled = true;
1644e9034789SMichal Meloun 	pad->lanes[pad->nlanes++] = lane;
1645e9034789SMichal Meloun 
1646e9034789SMichal Meloun 	/* Create and register phy. */
1647e9034789SMichal Meloun 	bzero(&phy_init, sizeof(phy_init));
1648e9034789SMichal Meloun 	phy_init.id = lane - lanes_tbl;
1649e9034789SMichal Meloun 	phy_init.ofw_node = node;
1650e9034789SMichal Meloun 	phynode = phynode_create(sc->dev, &xusbpadctl_phynode_class, &phy_init);
1651e9034789SMichal Meloun 	if (phynode == NULL) {
1652e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot create phy\n");
1653e9034789SMichal Meloun 		rv = ENXIO;
1654e9034789SMichal Meloun 		goto end;
1655e9034789SMichal Meloun 	}
1656e9034789SMichal Meloun 	if (phynode_register(phynode) == NULL) {
1657e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot create phy\n");
1658e9034789SMichal Meloun 		return (ENXIO);
1659e9034789SMichal Meloun 	}
1660e9034789SMichal Meloun 
1661e9034789SMichal Meloun 	rv = 0;
1662e9034789SMichal Meloun 
1663e9034789SMichal Meloun end:
1664e9034789SMichal Meloun 	if (name != NULL)
1665e9034789SMichal Meloun 		OF_prop_free(name);
1666e9034789SMichal Meloun 	if (function != NULL)
1667e9034789SMichal Meloun 		OF_prop_free(function);
1668e9034789SMichal Meloun 	return (rv);
1669e9034789SMichal Meloun }
1670e9034789SMichal Meloun 
1671e9034789SMichal Meloun static int
process_pad(struct padctl_softc * sc,phandle_t node)1672e9034789SMichal Meloun process_pad(struct padctl_softc *sc, phandle_t node)
1673e9034789SMichal Meloun {
1674e9034789SMichal Meloun 	phandle_t  xref;
1675e9034789SMichal Meloun 	struct padctl_pad *pad;
1676e9034789SMichal Meloun 	char *name;
1677e9034789SMichal Meloun 	int rv;
1678e9034789SMichal Meloun 
1679e9034789SMichal Meloun 	name = NULL;
1680e9034789SMichal Meloun 	rv = OF_getprop_alloc(node, "name", (void **)&name);
1681e9034789SMichal Meloun 	if (rv <= 0) {
1682e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read pad name.\n");
1683e9034789SMichal Meloun 		return (ENXIO);
1684e9034789SMichal Meloun 	}
1685e9034789SMichal Meloun 
1686e9034789SMichal Meloun 	pad = search_pad(sc, name);
1687e9034789SMichal Meloun 	if (pad == NULL) {
1688e9034789SMichal Meloun 		device_printf(sc->dev, "Unknown pad: %s\n", name);
1689e9034789SMichal Meloun 		rv = ENXIO;
1690e9034789SMichal Meloun 		goto end;
1691e9034789SMichal Meloun 	}
1692e9034789SMichal Meloun 
1693e9034789SMichal Meloun 	if (pad->clock_name != NULL) {
1694e9034789SMichal Meloun 		rv = clk_get_by_ofw_name(sc->dev, node, pad->clock_name,
1695e9034789SMichal Meloun 		    &pad->clk);
1696e9034789SMichal Meloun 		if (rv != 0) {
1697e9034789SMichal Meloun 			device_printf(sc->dev, "Cannot get '%s' clock\n",
1698e9034789SMichal Meloun 			    pad->clock_name);
1699e9034789SMichal Meloun 			return (ENXIO);
1700e9034789SMichal Meloun 		}
1701e9034789SMichal Meloun 	}
1702e9034789SMichal Meloun 
1703e9034789SMichal Meloun 	if (pad->reset_name != NULL) {
1704e9034789SMichal Meloun 		rv = hwreset_get_by_ofw_name(sc->dev, node, pad->reset_name,
1705e9034789SMichal Meloun 		    &pad->reset);
1706e9034789SMichal Meloun 		if (rv != 0) {
1707e9034789SMichal Meloun 			device_printf(sc->dev, "Cannot get '%s' reset\n",
1708e9034789SMichal Meloun 			    pad->reset_name);
1709e9034789SMichal Meloun 			return (ENXIO);
1710e9034789SMichal Meloun 		}
1711e9034789SMichal Meloun 	}
1712e9034789SMichal Meloun 
1713e9034789SMichal Meloun 	/* Read and process associated lanes. */
1714e9034789SMichal Meloun 	node = ofw_bus_find_child(node, "lanes");
1715e9034789SMichal Meloun 	if (node <= 0) {
1716e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find 'lanes' subnode\n");
1717e9034789SMichal Meloun 		rv = ENXIO;
1718e9034789SMichal Meloun 		goto end;
1719e9034789SMichal Meloun 	}
1720e9034789SMichal Meloun 
1721e9034789SMichal Meloun 	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
1722e9034789SMichal Meloun 		if (!ofw_bus_node_status_okay(node))
1723e9034789SMichal Meloun 			continue;
1724e9034789SMichal Meloun 
1725e9034789SMichal Meloun 		rv = process_lane(sc, node, pad);
1726e9034789SMichal Meloun 		if (rv != 0)
1727e9034789SMichal Meloun 			goto end;
1728e9034789SMichal Meloun 
1729e9034789SMichal Meloun 		xref = OF_xref_from_node(node);
1730e9034789SMichal Meloun 		OF_device_register_xref(xref, sc->dev);
1731e9034789SMichal Meloun 	}
1732e9034789SMichal Meloun 	pad->enabled = true;
1733e9034789SMichal Meloun 	rv = 0;
1734e9034789SMichal Meloun end:
1735e9034789SMichal Meloun 	if (name != NULL)
1736e9034789SMichal Meloun 		OF_prop_free(name);
1737e9034789SMichal Meloun 	return (rv);
1738e9034789SMichal Meloun }
1739e9034789SMichal Meloun 
1740e9034789SMichal Meloun static int
process_port(struct padctl_softc * sc,phandle_t node)1741e9034789SMichal Meloun process_port(struct padctl_softc *sc, phandle_t node)
1742e9034789SMichal Meloun {
1743e9034789SMichal Meloun 
1744e9034789SMichal Meloun 	struct padctl_port *port;
1745e9034789SMichal Meloun 	char *name;
1746e9034789SMichal Meloun 	int rv;
1747e9034789SMichal Meloun 
1748e9034789SMichal Meloun 	name = NULL;
1749e9034789SMichal Meloun 	rv = OF_getprop_alloc(node, "name", (void **)&name);
1750e9034789SMichal Meloun 	if (rv <= 0) {
1751e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read port name.\n");
1752e9034789SMichal Meloun 		return (ENXIO);
1753e9034789SMichal Meloun 	}
1754e9034789SMichal Meloun 
1755e9034789SMichal Meloun 	port = search_port(sc, name);
1756e9034789SMichal Meloun 	if (port == NULL) {
1757e9034789SMichal Meloun 		device_printf(sc->dev, "Unknown port: %s\n", name);
1758e9034789SMichal Meloun 		rv = ENXIO;
1759e9034789SMichal Meloun 		goto end;
1760e9034789SMichal Meloun 	}
1761e9034789SMichal Meloun 
1762e9034789SMichal Meloun 	regulator_get_by_ofw_property(sc->dev, node,
1763e9034789SMichal Meloun 	    "vbus-supply", &port->supply_vbus);
1764e9034789SMichal Meloun 
1765e9034789SMichal Meloun 	if (OF_hasprop(node, "nvidia,internal"))
1766e9034789SMichal Meloun 		port->internal = true;
1767e9034789SMichal Meloun 
1768e9034789SMichal Meloun 	/* Find assigned lane */
1769e9034789SMichal Meloun 	if (port->lane == NULL) {
1770e9034789SMichal Meloun 		switch(port->type) {
1771e9034789SMichal Meloun 		/* Routing is fixed for USB2 AND HSIC. */
1772e9034789SMichal Meloun 		case PADCTL_PORT_USB2:
1773e9034789SMichal Meloun 			port->lane = search_pad_lane(sc, PADCTL_PAD_USB2,
1774e9034789SMichal Meloun 			    port->idx);
1775e9034789SMichal Meloun 			break;
1776e9034789SMichal Meloun 		case PADCTL_PORT_HSIC:
1777e9034789SMichal Meloun 			port->lane = search_pad_lane(sc, PADCTL_PAD_HSIC,
1778e9034789SMichal Meloun 			    port->idx);
1779e9034789SMichal Meloun 			break;
1780e9034789SMichal Meloun 		case PADCTL_PORT_USB3:
1781e9034789SMichal Meloun 			port->lane = search_usb3_pad_lane(sc, port->idx);
1782e9034789SMichal Meloun 			break;
1783e9034789SMichal Meloun 		}
1784e9034789SMichal Meloun 	}
1785e9034789SMichal Meloun 	if (port->lane == NULL) {
1786e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find lane for port: %s\n", name);
1787e9034789SMichal Meloun 		rv = ENXIO;
1788e9034789SMichal Meloun 		goto end;
1789e9034789SMichal Meloun 	}
1790e9034789SMichal Meloun 
1791e9034789SMichal Meloun 	if (port->type == PADCTL_PORT_USB3) {
1792e9034789SMichal Meloun 		rv = OF_getencprop(node,  "nvidia,usb2-companion",
1793e9034789SMichal Meloun 		   &(port->companion), sizeof(port->companion));
1794e9034789SMichal Meloun 		if (rv <= 0) {
1795e9034789SMichal Meloun 			device_printf(sc->dev,
1796e9034789SMichal Meloun 			    "Missing 'nvidia,usb2-companion' property "
1797e9034789SMichal Meloun 			    "for port: %s\n", name);
1798e9034789SMichal Meloun 			rv = ENXIO;
1799e9034789SMichal Meloun 			goto end;
1800e9034789SMichal Meloun 		}
1801e9034789SMichal Meloun 	}
1802e9034789SMichal Meloun 
1803e9034789SMichal Meloun 	port->enabled = true;
1804e9034789SMichal Meloun 	rv = 0;
1805e9034789SMichal Meloun end:
1806e9034789SMichal Meloun 	if (name != NULL)
1807e9034789SMichal Meloun 		OF_prop_free(name);
1808e9034789SMichal Meloun 	return (rv);
1809e9034789SMichal Meloun }
1810e9034789SMichal Meloun 
1811e9034789SMichal Meloun static int
parse_fdt(struct padctl_softc * sc,phandle_t base_node)1812e9034789SMichal Meloun parse_fdt(struct padctl_softc *sc, phandle_t base_node)
1813e9034789SMichal Meloun {
1814e9034789SMichal Meloun 	phandle_t node;
1815e9034789SMichal Meloun 	int rv;
1816e9034789SMichal Meloun 
1817e9034789SMichal Meloun 	rv = 0;
1818e9034789SMichal Meloun 	node = ofw_bus_find_child(base_node, "pads");
1819e9034789SMichal Meloun 
1820e9034789SMichal Meloun 	if (node <= 0) {
1821e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find pads subnode.\n");
1822e9034789SMichal Meloun 		return (ENXIO);
1823e9034789SMichal Meloun 	}
1824e9034789SMichal Meloun 	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
1825e9034789SMichal Meloun 		if (!ofw_bus_node_status_okay(node))
1826e9034789SMichal Meloun 			continue;
1827e9034789SMichal Meloun 		rv = process_pad(sc, node);
1828e9034789SMichal Meloun 		if (rv != 0)
1829e9034789SMichal Meloun 			return (rv);
1830e9034789SMichal Meloun 	}
1831e9034789SMichal Meloun 
1832e9034789SMichal Meloun 	node = ofw_bus_find_child(base_node, "ports");
1833e9034789SMichal Meloun 	if (node <= 0) {
1834e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot find ports subnode.\n");
1835e9034789SMichal Meloun 		return (ENXIO);
1836e9034789SMichal Meloun 	}
1837e9034789SMichal Meloun 	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
1838e9034789SMichal Meloun 		if (!ofw_bus_node_status_okay(node))
1839e9034789SMichal Meloun 			continue;
1840e9034789SMichal Meloun 		rv = process_port(sc, node);
1841e9034789SMichal Meloun 		if (rv != 0)
1842e9034789SMichal Meloun 			return (rv);
1843e9034789SMichal Meloun 	}
1844e9034789SMichal Meloun 
1845e9034789SMichal Meloun 	return (0);
1846e9034789SMichal Meloun }
1847e9034789SMichal Meloun 
1848e9034789SMichal Meloun static void
load_calibration(struct padctl_softc * sc)1849e9034789SMichal Meloun load_calibration(struct padctl_softc *sc)
1850e9034789SMichal Meloun {
1851e9034789SMichal Meloun 	uint32_t reg;
1852e9034789SMichal Meloun 	int i;
1853e9034789SMichal Meloun 
1854e9034789SMichal Meloun 	reg = tegra_fuse_read_4(FUSE_SKU_CALIB_0);
1855e9034789SMichal Meloun 	sc->hs_curr_level[0] = FUSE_SKU_CALIB_0_HS_CURR_LEVEL_0(reg);
1856e9034789SMichal Meloun 	for (i = 1; i < nitems(sc->hs_curr_level); i++) {
1857e9034789SMichal Meloun 		sc->hs_curr_level[i] =
1858e9034789SMichal Meloun 		    FUSE_SKU_CALIB_0_HS_CURR_LEVEL_123(reg, i);
1859e9034789SMichal Meloun 	}
1860e9034789SMichal Meloun 	sc->hs_term_range_adj = FUSE_SKU_CALIB_0_HS_TERM_RANGE_ADJ(reg);
1861e9034789SMichal Meloun 
1862e9034789SMichal Meloun 	tegra_fuse_read_4(FUSE_USB_CALIB_EXT_0);
1863e9034789SMichal Meloun 	sc->rpd_ctrl = FUSE_USB_CALIB_EXT_0_RPD_CTRL(reg);
1864e9034789SMichal Meloun }
1865e9034789SMichal Meloun 
1866e9034789SMichal Meloun /* -------------------------------------------------------------------------
1867e9034789SMichal Meloun  *
1868e9034789SMichal Meloun  *   BUS functions
1869e9034789SMichal Meloun  */
1870e9034789SMichal Meloun static int
xusbpadctl_probe(device_t dev)1871e9034789SMichal Meloun xusbpadctl_probe(device_t dev)
1872e9034789SMichal Meloun {
1873e9034789SMichal Meloun 
1874e9034789SMichal Meloun 	if (!ofw_bus_status_okay(dev))
1875e9034789SMichal Meloun 		return (ENXIO);
1876e9034789SMichal Meloun 
1877e9034789SMichal Meloun 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
1878e9034789SMichal Meloun 		return (ENXIO);
1879e9034789SMichal Meloun 
1880e9034789SMichal Meloun 	device_set_desc(dev, "Tegra XUSB phy");
1881e9034789SMichal Meloun 	return (BUS_PROBE_DEFAULT);
1882e9034789SMichal Meloun }
1883e9034789SMichal Meloun 
1884e9034789SMichal Meloun static int
xusbpadctl_detach(device_t dev)1885e9034789SMichal Meloun xusbpadctl_detach(device_t dev)
1886e9034789SMichal Meloun {
1887e9034789SMichal Meloun 
1888e9034789SMichal Meloun 	/* This device is always present. */
1889e9034789SMichal Meloun 	return (EBUSY);
1890e9034789SMichal Meloun }
1891e9034789SMichal Meloun 
1892e9034789SMichal Meloun static int
xusbpadctl_attach(device_t dev)1893e9034789SMichal Meloun xusbpadctl_attach(device_t dev)
1894e9034789SMichal Meloun {
1895e9034789SMichal Meloun 	struct padctl_softc * sc;
1896e9034789SMichal Meloun 	int i, rid, rv;
1897e9034789SMichal Meloun 	struct padctl_port *port;
1898e9034789SMichal Meloun 	phandle_t node;
1899e9034789SMichal Meloun 
1900e9034789SMichal Meloun 	sc = device_get_softc(dev);
1901e9034789SMichal Meloun 	sc->dev = dev;
1902e9034789SMichal Meloun 	node = ofw_bus_get_node(dev);
1903e9034789SMichal Meloun 	rid = 0;
1904e9034789SMichal Meloun 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
1905e9034789SMichal Meloun 	    RF_ACTIVE);
1906e9034789SMichal Meloun 	if (sc->mem_res == NULL) {
1907e9034789SMichal Meloun 		device_printf(dev, "Cannot allocate memory resources\n");
1908e9034789SMichal Meloun 		return (ENXIO);
1909e9034789SMichal Meloun 	}
1910e9034789SMichal Meloun 
1911e9034789SMichal Meloun 	rv = hwreset_get_by_ofw_name(dev, 0, "padctl", &sc->rst);
1912e9034789SMichal Meloun 	if (rv != 0) {
1913e9034789SMichal Meloun 		device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv);
1914e9034789SMichal Meloun 		return (rv);
1915e9034789SMichal Meloun 	}
1916e9034789SMichal Meloun 	rv = hwreset_deassert(sc->rst);
1917e9034789SMichal Meloun 	if (rv != 0) {
1918e9034789SMichal Meloun 		device_printf(dev, "Cannot unreset 'padctl' reset: %d\n", rv);
1919e9034789SMichal Meloun 		return (rv);
1920e9034789SMichal Meloun 	}
1921e9034789SMichal Meloun 
1922e9034789SMichal Meloun 	load_calibration(sc);
1923e9034789SMichal Meloun 
1924e9034789SMichal Meloun 	rv = parse_fdt(sc, node);
1925e9034789SMichal Meloun 	if (rv != 0) {
1926e9034789SMichal Meloun 		device_printf(dev, "Cannot parse fdt configuration: %d\n", rv);
1927e9034789SMichal Meloun 		return (rv);
1928e9034789SMichal Meloun 	}
1929e9034789SMichal Meloun 	for (i = 0; i < nitems(ports_tbl); i++) {
1930e9034789SMichal Meloun 		port = ports_tbl + i;
1931e9034789SMichal Meloun 		if (!port->enabled)
1932e9034789SMichal Meloun 			continue;
1933e9034789SMichal Meloun 		if (port->init == NULL)
1934e9034789SMichal Meloun 			continue;
1935e9034789SMichal Meloun 		rv = port->init(sc, port);
1936e9034789SMichal Meloun 		if (rv != 0) {
1937e9034789SMichal Meloun 			device_printf(dev, "Cannot init port '%s'\n",
1938e9034789SMichal Meloun 			    port->name);
1939e9034789SMichal Meloun 			return (rv);
1940e9034789SMichal Meloun 		}
1941e9034789SMichal Meloun 	}
1942e9034789SMichal Meloun 	return (0);
1943e9034789SMichal Meloun }
1944e9034789SMichal Meloun 
1945e9034789SMichal Meloun static device_method_t tegra_xusbpadctl_methods[] = {
1946e9034789SMichal Meloun 	/* Device interface */
1947e9034789SMichal Meloun 	DEVMETHOD(device_probe,         xusbpadctl_probe),
1948e9034789SMichal Meloun 	DEVMETHOD(device_attach,        xusbpadctl_attach),
1949e9034789SMichal Meloun 	DEVMETHOD(device_detach,        xusbpadctl_detach),
1950e9034789SMichal Meloun 
1951e9034789SMichal Meloun 	DEVMETHOD_END
1952e9034789SMichal Meloun };
1953e9034789SMichal Meloun 
1954e9034789SMichal Meloun static DEFINE_CLASS_0(xusbpadctl, tegra_xusbpadctl_driver,
1955e9034789SMichal Meloun     tegra_xusbpadctl_methods, sizeof(struct padctl_softc));
1956e9034789SMichal Meloun EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver,
1957289f133bSJohn Baldwin     NULL, NULL, 73);
1958