xref: /arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019 - 2021, Broadcom
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <platform_usb.h>
8*91f16700Schasinglulu #include <usb_phy.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #define USB_PHY_ALREADY_STARTED	(-2)
11*91f16700Schasinglulu #define USB_MAX_DEVICES		 2
12*91f16700Schasinglulu #define USB3H_USB2DRD_PHY	 0
13*91f16700Schasinglulu #define USB3_DRD_PHY		 1
14*91f16700Schasinglulu 
15*91f16700Schasinglulu /* Common bit fields for all the USB2 phy */
16*91f16700Schasinglulu #define USB2_PHY_ISO		DRDU2_U2PHY_ISO
17*91f16700Schasinglulu #define USB2_AFE_PLL_PWRDWNB	DRDU2_U2AFE_PLL_PWRDWNB
18*91f16700Schasinglulu #define USB2_AFE_BG_PWRDWNB	DRDU2_U2AFE_BG_PWRDWNB
19*91f16700Schasinglulu #define USB2_AFE_LDO_PWRDWNB	DRDU2_U2AFE_LDO_PWRDWNB
20*91f16700Schasinglulu #define USB2_CTRL_CORERDY	DRDU2_U2CTRL_CORERDY
21*91f16700Schasinglulu 
22*91f16700Schasinglulu #define USB2_PHY_PCTL_MASK	DRDU2_U2PHY_PCTL_MASK
23*91f16700Schasinglulu #define USB2_PHY_PCTL_OFFSET	DRDU2_U2PHY_PCTL_OFFSET
24*91f16700Schasinglulu #define USB2_PHY_PCTL_VAL	U2PHY_PCTL_VAL
25*91f16700Schasinglulu 
26*91f16700Schasinglulu #define USB2_PLL_RESETB		DRDU2_U2PLL_RESETB
27*91f16700Schasinglulu #define USB2_PHY_RESETB		DRDU2_U2PHY_RESETB
28*91f16700Schasinglulu 
29*91f16700Schasinglulu static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS];
30*91f16700Schasinglulu 
31*91f16700Schasinglulu static usb_phy_t usb_phy_info[2U] = {
32*91f16700Schasinglulu 	{DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY},
33*91f16700Schasinglulu 	{0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY}
34*91f16700Schasinglulu };
35*91f16700Schasinglulu 
36*91f16700Schasinglulu typedef struct {
37*91f16700Schasinglulu 	void *pcd_id;
38*91f16700Schasinglulu } usb_platform_dev;
39*91f16700Schasinglulu 
40*91f16700Schasinglulu /* index 0: USB3H + USB2 DRD, 1: USB3 DRD */
41*91f16700Schasinglulu static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = {
42*91f16700Schasinglulu 	{&usb_phy_info[0U]},
43*91f16700Schasinglulu 	{&usb_phy_info[1U]}
44*91f16700Schasinglulu };
45*91f16700Schasinglulu 
46*91f16700Schasinglulu static int32_t pll_lock_check(uint32_t address, uint32_t bit)
47*91f16700Schasinglulu {
48*91f16700Schasinglulu 	uint32_t retry;
49*91f16700Schasinglulu 	uint32_t data;
50*91f16700Schasinglulu 
51*91f16700Schasinglulu 	retry = PLL_LOCK_RETRY_COUNT;
52*91f16700Schasinglulu 	do {
53*91f16700Schasinglulu 		data = mmio_read_32(address);
54*91f16700Schasinglulu 		if ((data & bit) != 0U) {
55*91f16700Schasinglulu 			return 0;
56*91f16700Schasinglulu 		}
57*91f16700Schasinglulu 		udelay(1);
58*91f16700Schasinglulu 	} while (--retry != 0);
59*91f16700Schasinglulu 
60*91f16700Schasinglulu 	ERROR("%s(): FAIL (0x%08x)\n", __func__, address);
61*91f16700Schasinglulu 	return -1;
62*91f16700Schasinglulu }
63*91f16700Schasinglulu 
64*91f16700Schasinglulu /*
65*91f16700Schasinglulu  * USB2 PHY using external FSM bringup sequence
66*91f16700Schasinglulu  * Total #3 USB2 phys. All phys has the same
67*91f16700Schasinglulu  * bringup sequence. Register bit fields for
68*91f16700Schasinglulu  * some of the PHY's are different.
69*91f16700Schasinglulu  * Bit fields which are different are passed using
70*91f16700Schasinglulu  * struct u2_phy_ext_fsm with bit-fields and register addr.
71*91f16700Schasinglulu  */
72*91f16700Schasinglulu 
73*91f16700Schasinglulu static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy)
74*91f16700Schasinglulu {
75*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
76*91f16700Schasinglulu 	/* Delay as per external FSM spec */
77*91f16700Schasinglulu 	udelay(10U);
78*91f16700Schasinglulu 
79*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
80*91f16700Schasinglulu 	/* Delay as per external FSM spec */
81*91f16700Schasinglulu 	udelay(10U);
82*91f16700Schasinglulu 
83*91f16700Schasinglulu 	mmio_clrbits_32(u2_phy->phy_ctrl_reg,
84*91f16700Schasinglulu 			(USB2_AFE_BG_PWRDWNB |
85*91f16700Schasinglulu 			 USB2_AFE_PLL_PWRDWNB |
86*91f16700Schasinglulu 			 USB2_AFE_LDO_PWRDWNB |
87*91f16700Schasinglulu 			 USB2_CTRL_CORERDY));
88*91f16700Schasinglulu 
89*91f16700Schasinglulu 	mmio_clrsetbits_32(u2_phy->phy_ctrl_reg,
90*91f16700Schasinglulu 			   (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET),
91*91f16700Schasinglulu 			   (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET));
92*91f16700Schasinglulu 	/* Delay as per external FSM spec */
93*91f16700Schasinglulu 	udelay(160U);
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY);
96*91f16700Schasinglulu 	/* Delay as per external FSM spec */
97*91f16700Schasinglulu 	udelay(50U);
98*91f16700Schasinglulu 
99*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB);
100*91f16700Schasinglulu 	/* Delay as per external FSM spec */
101*91f16700Schasinglulu 	udelay(200U);
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin);
104*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB);
105*91f16700Schasinglulu 	/* Delay as per external FSM spec */
106*91f16700Schasinglulu 	udelay(10U);
107*91f16700Schasinglulu 
108*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin);
109*91f16700Schasinglulu 	/* Delay as per external FSM spec */
110*91f16700Schasinglulu 	udelay(10U);
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB);
113*91f16700Schasinglulu 	/* Delay as per external FSM spec */
114*91f16700Schasinglulu 	udelay(10U);
115*91f16700Schasinglulu 
116*91f16700Schasinglulu 	mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
117*91f16700Schasinglulu 	/* Delay as per external FSM spec */
118*91f16700Schasinglulu 	udelay(10U);
119*91f16700Schasinglulu 	mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
120*91f16700Schasinglulu 	/* Delay as per external FSM spec */
121*91f16700Schasinglulu 	udelay(1U);
122*91f16700Schasinglulu 
123*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB);
124*91f16700Schasinglulu 	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB);
125*91f16700Schasinglulu 
126*91f16700Schasinglulu }
127*91f16700Schasinglulu 
128*91f16700Schasinglulu static int32_t usb3h_u2_phy_power_on(uint32_t base)
129*91f16700Schasinglulu {
130*91f16700Schasinglulu 	int32_t status;
131*91f16700Schasinglulu 	struct u2_phy_ext_fsm u2_phy;
132*91f16700Schasinglulu 
133*91f16700Schasinglulu 	u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL;
134*91f16700Schasinglulu 	u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL;
135*91f16700Schasinglulu 	u2_phy.phy_iddq = USB3H_U2PHY_IDDQ;
136*91f16700Schasinglulu 	u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL;
137*91f16700Schasinglulu 	u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN;
138*91f16700Schasinglulu 	u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN;
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 	u2_phy_ext_fsm_power_on(&u2_phy);
141*91f16700Schasinglulu 
142*91f16700Schasinglulu 	status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK);
143*91f16700Schasinglulu 	if (status != 0) {
144*91f16700Schasinglulu 		/* re-try by toggling the PLL reset */
145*91f16700Schasinglulu 		mmio_clrbits_32(base + USB3H_U2PLL_CTRL,
146*91f16700Schasinglulu 				(uint32_t)USB3H_U2PLL_RESETB);
147*91f16700Schasinglulu 		mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB);
148*91f16700Schasinglulu 		status = pll_lock_check(base + USB3H_U2PLL_CTRL,
149*91f16700Schasinglulu 					USB3H_U2PLL_LOCK);
150*91f16700Schasinglulu 		if (status != 0)
151*91f16700Schasinglulu 			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
152*91f16700Schasinglulu 			      base + USB3H_U2PLL_CTRL);
153*91f16700Schasinglulu 	}
154*91f16700Schasinglulu 
155*91f16700Schasinglulu 	mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL,
156*91f16700Schasinglulu 			   (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET),
157*91f16700Schasinglulu 			   (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET));
158*91f16700Schasinglulu 	return status;
159*91f16700Schasinglulu }
160*91f16700Schasinglulu 
161*91f16700Schasinglulu static int32_t usb3h_u3_phy_power_on(uint32_t base)
162*91f16700Schasinglulu {
163*91f16700Schasinglulu 	int32_t status;
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 	/* Set pctl with mode and soft reset */
166*91f16700Schasinglulu 	mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL,
167*91f16700Schasinglulu 			   (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET),
168*91f16700Schasinglulu 			   (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET));
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL,
171*91f16700Schasinglulu 			(uint32_t) USB3H_U3SSPLL_SUSPEND_EN);
172*91f16700Schasinglulu 	mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START);
173*91f16700Schasinglulu 	mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB);
174*91f16700Schasinglulu 
175*91f16700Schasinglulu 	/* Time to stabilize the PLL Control */
176*91f16700Schasinglulu 	mdelay(1U);
177*91f16700Schasinglulu 
178*91f16700Schasinglulu 	status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL,
179*91f16700Schasinglulu 				USB3H_U3PLL_SS_LOCK);
180*91f16700Schasinglulu 
181*91f16700Schasinglulu 	return status;
182*91f16700Schasinglulu }
183*91f16700Schasinglulu 
184*91f16700Schasinglulu static int32_t drdu3_u2_phy_power_on(uint32_t base)
185*91f16700Schasinglulu {
186*91f16700Schasinglulu 	int32_t status;
187*91f16700Schasinglulu 	struct u2_phy_ext_fsm u2_phy;
188*91f16700Schasinglulu 
189*91f16700Schasinglulu 	u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL;
190*91f16700Schasinglulu 	u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL;
191*91f16700Schasinglulu 	u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ;
192*91f16700Schasinglulu 	u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL;
193*91f16700Schasinglulu 	u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN;
194*91f16700Schasinglulu 	u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN;
195*91f16700Schasinglulu 
196*91f16700Schasinglulu 	u2_phy_ext_fsm_power_on(&u2_phy);
197*91f16700Schasinglulu 
198*91f16700Schasinglulu 	status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK);
199*91f16700Schasinglulu 	if (status != 0) {
200*91f16700Schasinglulu 		/* re-try by toggling the PLL reset */
201*91f16700Schasinglulu 		mmio_clrbits_32(base + DRDU3_U2PLL_CTRL,
202*91f16700Schasinglulu 				(uint32_t)DRDU2_U2PLL_RESETB);
203*91f16700Schasinglulu 		mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB);
204*91f16700Schasinglulu 
205*91f16700Schasinglulu 		status = pll_lock_check(base + DRDU3_U2PLL_CTRL,
206*91f16700Schasinglulu 					DRDU3_U2PLL_LOCK);
207*91f16700Schasinglulu 		if (status != 0) {
208*91f16700Schasinglulu 			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
209*91f16700Schasinglulu 			      base + DRDU3_U2PLL_CTRL);
210*91f16700Schasinglulu 		}
211*91f16700Schasinglulu 	}
212*91f16700Schasinglulu 	mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL,
213*91f16700Schasinglulu 			   (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET),
214*91f16700Schasinglulu 			   (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET));
215*91f16700Schasinglulu 
216*91f16700Schasinglulu 	return status;
217*91f16700Schasinglulu }
218*91f16700Schasinglulu 
219*91f16700Schasinglulu static int32_t drdu3_u3_phy_power_on(uint32_t base)
220*91f16700Schasinglulu {
221*91f16700Schasinglulu 	int32_t status;
222*91f16700Schasinglulu 
223*91f16700Schasinglulu 	/* Set pctl with mode and soft reset */
224*91f16700Schasinglulu 	mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL,
225*91f16700Schasinglulu 			   (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET),
226*91f16700Schasinglulu 			   (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET));
227*91f16700Schasinglulu 
228*91f16700Schasinglulu 	mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL,
229*91f16700Schasinglulu 			(uint32_t) DRDU3_U3SSPLL_SUSPEND_EN);
230*91f16700Schasinglulu 	mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START);
231*91f16700Schasinglulu 	mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB);
232*91f16700Schasinglulu 
233*91f16700Schasinglulu 	/* Time to stabilize the PLL Control */
234*91f16700Schasinglulu 	mdelay(1U);
235*91f16700Schasinglulu 
236*91f16700Schasinglulu 	status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL,
237*91f16700Schasinglulu 				DRDU3_U3PLL_SS_LOCK);
238*91f16700Schasinglulu 
239*91f16700Schasinglulu 	return status;
240*91f16700Schasinglulu }
241*91f16700Schasinglulu 
242*91f16700Schasinglulu static int32_t drdu2_u2_phy_power_on(uint32_t base)
243*91f16700Schasinglulu {
244*91f16700Schasinglulu 	int32_t status;
245*91f16700Schasinglulu 	struct u2_phy_ext_fsm u2_phy;
246*91f16700Schasinglulu 
247*91f16700Schasinglulu 	u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL;
248*91f16700Schasinglulu 	u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL;
249*91f16700Schasinglulu 	u2_phy.phy_iddq = DRDU2_U2IDDQ;
250*91f16700Schasinglulu 	u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL;
251*91f16700Schasinglulu 	u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I;
252*91f16700Schasinglulu 	u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I;
253*91f16700Schasinglulu 
254*91f16700Schasinglulu 	u2_phy_ext_fsm_power_on(&u2_phy);
255*91f16700Schasinglulu 
256*91f16700Schasinglulu 	status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK);
257*91f16700Schasinglulu 	if (status != 0) {
258*91f16700Schasinglulu 		/* re-try by toggling the PLL reset */
259*91f16700Schasinglulu 		mmio_clrbits_32(base + DRDU2_U2PLL_CTRL,
260*91f16700Schasinglulu 				(uint32_t)DRDU2_U2PLL_RESETB);
261*91f16700Schasinglulu 		mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB);
262*91f16700Schasinglulu 
263*91f16700Schasinglulu 		status = pll_lock_check(base + DRDU2_U2PLL_CTRL,
264*91f16700Schasinglulu 					DRDU2_U2PLL_LOCK);
265*91f16700Schasinglulu 		if (status != 0)
266*91f16700Schasinglulu 			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
267*91f16700Schasinglulu 			      base + DRDU2_U2PLL_CTRL);
268*91f16700Schasinglulu 	}
269*91f16700Schasinglulu 	mmio_clrsetbits_32(base + DRDU2_PHY_CTRL,
270*91f16700Schasinglulu 			   (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET),
271*91f16700Schasinglulu 			   (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET));
272*91f16700Schasinglulu 
273*91f16700Schasinglulu 	return status;
274*91f16700Schasinglulu }
275*91f16700Schasinglulu 
276*91f16700Schasinglulu void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port)
277*91f16700Schasinglulu {
278*91f16700Schasinglulu 	usb_phy_t *phy = phy_port->p;
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 	switch (phy_port->port_id) {
281*91f16700Schasinglulu 	case USB3HS_PORT:
282*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
283*91f16700Schasinglulu 				(uint32_t) USB3H_U2CTRL_CORERDY);
284*91f16700Schasinglulu 		mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
285*91f16700Schasinglulu 				USB3H_U2CTRL_CORERDY);
286*91f16700Schasinglulu 		break;
287*91f16700Schasinglulu 	case DRDU2_PORT:
288*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
289*91f16700Schasinglulu 				(uint32_t) DRDU2_U2CTRL_CORERDY);
290*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
291*91f16700Schasinglulu 				DRDU2_U2CTRL_CORERDY);
292*91f16700Schasinglulu 		break;
293*91f16700Schasinglulu 	}
294*91f16700Schasinglulu }
295*91f16700Schasinglulu 
296*91f16700Schasinglulu void u3drd_phy_reset(usb_phy_port_t *phy_port)
297*91f16700Schasinglulu {
298*91f16700Schasinglulu 	usb_phy_t *phy = phy_port->p;
299*91f16700Schasinglulu 
300*91f16700Schasinglulu 	if (phy_port->port_id == DRD3HS_PORT) {
301*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
302*91f16700Schasinglulu 				(uint32_t) DRDU3_U2CTRL_CORERDY);
303*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
304*91f16700Schasinglulu 				DRDU3_U2CTRL_CORERDY);
305*91f16700Schasinglulu 	}
306*91f16700Schasinglulu }
307*91f16700Schasinglulu 
308*91f16700Schasinglulu static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port)
309*91f16700Schasinglulu {
310*91f16700Schasinglulu 	usb_phy_t *phy = phy_port->p;
311*91f16700Schasinglulu 	int32_t status;
312*91f16700Schasinglulu 
313*91f16700Schasinglulu 	switch (phy_port->port_id) {
314*91f16700Schasinglulu 	case USB3SS_PORT:
315*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
316*91f16700Schasinglulu 				(uint32_t) USB3H_DISABLE_USB30_P0);
317*91f16700Schasinglulu 		status = usb3h_u3_phy_power_on(phy->usb3hreg);
318*91f16700Schasinglulu 		if (status != 0) {
319*91f16700Schasinglulu 			goto err_usb3h_phy_on;
320*91f16700Schasinglulu 		}
321*91f16700Schasinglulu 		break;
322*91f16700Schasinglulu 	case USB3HS_PORT:
323*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
324*91f16700Schasinglulu 				(uint32_t) USB3H_DISABLE_EUSB_P1);
325*91f16700Schasinglulu 		mmio_setbits_32(AXI_DEBUG_CTRL,
326*91f16700Schasinglulu 				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
327*91f16700Schasinglulu 		mmio_setbits_32(USB3H_DEBUG_CTRL,
328*91f16700Schasinglulu 				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
329*91f16700Schasinglulu 
330*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
331*91f16700Schasinglulu 				USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN);
332*91f16700Schasinglulu 		/* Delay as per external FSM spec */
333*91f16700Schasinglulu 		udelay(10U);
334*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
335*91f16700Schasinglulu 				USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN);
336*91f16700Schasinglulu 		status = usb3h_u2_phy_power_on(phy->usb3hreg);
337*91f16700Schasinglulu 		if (status != 0) {
338*91f16700Schasinglulu 			goto err_usb3h_phy_on;
339*91f16700Schasinglulu 		}
340*91f16700Schasinglulu 		break;
341*91f16700Schasinglulu 	case DRDU2_PORT:
342*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
343*91f16700Schasinglulu 				(uint32_t) USB3H_DISABLE_EUSB_P0);
344*91f16700Schasinglulu 		mmio_setbits_32(AXI_DEBUG_CTRL,
345*91f16700Schasinglulu 				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
346*91f16700Schasinglulu 		mmio_setbits_32(USB3H_DEBUG_CTRL,
347*91f16700Schasinglulu 				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
348*91f16700Schasinglulu 
349*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
350*91f16700Schasinglulu 				DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I);
351*91f16700Schasinglulu 		/* Delay as per external FSM spec */
352*91f16700Schasinglulu 		udelay(10U);
353*91f16700Schasinglulu 		mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
354*91f16700Schasinglulu 				DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I);
355*91f16700Schasinglulu 
356*91f16700Schasinglulu 		status = drdu2_u2_phy_power_on(phy->drdu2reg);
357*91f16700Schasinglulu 		if (status != 0) {
358*91f16700Schasinglulu 			mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
359*91f16700Schasinglulu 					USB3H_DISABLE_EUSB_P0);
360*91f16700Schasinglulu 			goto err_drdu2_phy_on;
361*91f16700Schasinglulu 		}
362*91f16700Schasinglulu 		break;
363*91f16700Schasinglulu 	}
364*91f16700Schasinglulu 
365*91f16700Schasinglulu 	/* Device Mode */
366*91f16700Schasinglulu 	if (phy_port->port_id == DRDU2_PORT) {
367*91f16700Schasinglulu 		mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL,
368*91f16700Schasinglulu 			      DRDU2_BDC_AXI_SOFT_RST_N);
369*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
370*91f16700Schasinglulu 				DRDU2_U2SOFT_RST_N);
371*91f16700Schasinglulu 	}
372*91f16700Schasinglulu 	/* Host Mode */
373*91f16700Schasinglulu 	mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL,
374*91f16700Schasinglulu 		      USB3H_XHC_AXI_SOFT_RST_N);
375*91f16700Schasinglulu 	mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
376*91f16700Schasinglulu 
377*91f16700Schasinglulu 	return 0U;
378*91f16700Schasinglulu  err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
379*91f16700Schasinglulu 			(USB3H_DISABLE_EUSB_P1 |
380*91f16700Schasinglulu 			 USB3H_DISABLE_USB30_P0));
381*91f16700Schasinglulu  err_drdu2_phy_on:
382*91f16700Schasinglulu 
383*91f16700Schasinglulu 	return status;
384*91f16700Schasinglulu }
385*91f16700Schasinglulu 
386*91f16700Schasinglulu static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port)
387*91f16700Schasinglulu {
388*91f16700Schasinglulu 	usb_phy_t *phy = phy_port->p;
389*91f16700Schasinglulu 	int32_t status;
390*91f16700Schasinglulu 
391*91f16700Schasinglulu 	switch (phy_port->port_id) {
392*91f16700Schasinglulu 	case DRD3SS_PORT:
393*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
394*91f16700Schasinglulu 				(uint32_t) DRDU3_DISABLE_USB30_P0);
395*91f16700Schasinglulu 
396*91f16700Schasinglulu 		status = drdu3_u3_phy_power_on(phy->drdu3reg);
397*91f16700Schasinglulu 		if (status != 0) {
398*91f16700Schasinglulu 			goto err_drdu3_phy_on;
399*91f16700Schasinglulu 		}
400*91f16700Schasinglulu 		break;
401*91f16700Schasinglulu 	case DRD3HS_PORT:
402*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
403*91f16700Schasinglulu 				(uint32_t) DRDU3_DISABLE_EUSB_P0);
404*91f16700Schasinglulu 		mmio_setbits_32(AXI_DEBUG_CTRL,
405*91f16700Schasinglulu 				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
406*91f16700Schasinglulu 		mmio_setbits_32(USB3H_DEBUG_CTRL,
407*91f16700Schasinglulu 				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
408*91f16700Schasinglulu 
409*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
410*91f16700Schasinglulu 				DRDU3_U2PHY_DFE_SWITCH_PWRONIN);
411*91f16700Schasinglulu 		/* Delay as per external FSM spec */
412*91f16700Schasinglulu 		udelay(10U);
413*91f16700Schasinglulu 		mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
414*91f16700Schasinglulu 				DRDU3_U2PHY_DFE_SWITCH_PWROKIN);
415*91f16700Schasinglulu 
416*91f16700Schasinglulu 		status = drdu3_u2_phy_power_on(phy->drdu3reg);
417*91f16700Schasinglulu 		if (status != 0) {
418*91f16700Schasinglulu 			goto err_drdu3_phy_on;
419*91f16700Schasinglulu 		}
420*91f16700Schasinglulu 
421*91f16700Schasinglulu 		/* Host Mode */
422*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
423*91f16700Schasinglulu 				DRDU3_XHC_AXI_SOFT_RST_N);
424*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
425*91f16700Schasinglulu 				DRDU3_U3XHC_SOFT_RST_N);
426*91f16700Schasinglulu 		/* Device Mode */
427*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
428*91f16700Schasinglulu 				DRDU3_BDC_AXI_SOFT_RST_N);
429*91f16700Schasinglulu 		mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
430*91f16700Schasinglulu 				DRDU3_U3BDC_SOFT_RST_N);
431*91f16700Schasinglulu 		break;
432*91f16700Schasinglulu 	}
433*91f16700Schasinglulu 
434*91f16700Schasinglulu 	return 0U;
435*91f16700Schasinglulu  err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
436*91f16700Schasinglulu 			(DRDU3_DISABLE_EUSB_P0 |
437*91f16700Schasinglulu 			 DRDU3_DISABLE_USB30_P0));
438*91f16700Schasinglulu 
439*91f16700Schasinglulu 	return status;
440*91f16700Schasinglulu }
441*91f16700Schasinglulu 
442*91f16700Schasinglulu static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port)
443*91f16700Schasinglulu {
444*91f16700Schasinglulu 	usb_phy_t *p = phy_port->p;
445*91f16700Schasinglulu 
446*91f16700Schasinglulu 	switch (phy_port->port_id) {
447*91f16700Schasinglulu 	case USB3SS_PORT:
448*91f16700Schasinglulu 		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
449*91f16700Schasinglulu 				USB3H_DISABLE_USB30_P0);
450*91f16700Schasinglulu 		break;
451*91f16700Schasinglulu 	case USB3HS_PORT:
452*91f16700Schasinglulu 		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
453*91f16700Schasinglulu 				USB3H_DISABLE_EUSB_P1);
454*91f16700Schasinglulu 		break;
455*91f16700Schasinglulu 	case DRDU2_PORT:
456*91f16700Schasinglulu 		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
457*91f16700Schasinglulu 				USB3H_DISABLE_EUSB_P0);
458*91f16700Schasinglulu 		break;
459*91f16700Schasinglulu 	}
460*91f16700Schasinglulu }
461*91f16700Schasinglulu 
462*91f16700Schasinglulu static void u3drd_phy_power_off(usb_phy_port_t *phy_port)
463*91f16700Schasinglulu {
464*91f16700Schasinglulu 	usb_phy_t *p = phy_port->p;
465*91f16700Schasinglulu 
466*91f16700Schasinglulu 	switch (phy_port->port_id) {
467*91f16700Schasinglulu 	case DRD3SS_PORT:
468*91f16700Schasinglulu 		mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
469*91f16700Schasinglulu 				DRDU3_DISABLE_USB30_P0);
470*91f16700Schasinglulu 		break;
471*91f16700Schasinglulu 	case DRD3HS_PORT:
472*91f16700Schasinglulu 		mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
473*91f16700Schasinglulu 				DRDU3_DISABLE_EUSB_P0);
474*91f16700Schasinglulu 		break;
475*91f16700Schasinglulu 	}
476*91f16700Schasinglulu }
477*91f16700Schasinglulu 
478*91f16700Schasinglulu int32_t usb_info_fill(usb_phy_t *phy_info)
479*91f16700Schasinglulu {
480*91f16700Schasinglulu 	int32_t index;
481*91f16700Schasinglulu 
482*91f16700Schasinglulu 	if (phy_info->initialized != 0U) {
483*91f16700Schasinglulu 		return USB_PHY_ALREADY_STARTED;
484*91f16700Schasinglulu 	}
485*91f16700Schasinglulu 
486*91f16700Schasinglulu 	if (phy_info->phy_id == USB3H_DRDU2_PHY) {
487*91f16700Schasinglulu 		phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U];
488*91f16700Schasinglulu 		phy_info->ports_enabled = 0x7U;
489*91f16700Schasinglulu 	} else {
490*91f16700Schasinglulu 		phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U];
491*91f16700Schasinglulu 		phy_info->ports_enabled = 0x3U;
492*91f16700Schasinglulu 	}
493*91f16700Schasinglulu 
494*91f16700Schasinglulu 	for (index = MAX_NR_PORTS - 1U; index > -1; index--) {
495*91f16700Schasinglulu 		phy_info->phy_port[index].enabled = (phy_info->ports_enabled
496*91f16700Schasinglulu 						     >> index) & 0x1U;
497*91f16700Schasinglulu 		phy_info->phy_port[index].p = phy_info;
498*91f16700Schasinglulu 		phy_info->phy_port[index].port_id = index;
499*91f16700Schasinglulu 	}
500*91f16700Schasinglulu 
501*91f16700Schasinglulu 	return 0U;
502*91f16700Schasinglulu }
503*91f16700Schasinglulu 
504*91f16700Schasinglulu int32_t usb_phy_init(usb_platform_dev *device)
505*91f16700Schasinglulu {
506*91f16700Schasinglulu 	int32_t status;
507*91f16700Schasinglulu 	usb_phy_t *phy_info;
508*91f16700Schasinglulu 	uint32_t index;
509*91f16700Schasinglulu 
510*91f16700Schasinglulu 	phy_info = (usb_phy_t *)device->pcd_id;
511*91f16700Schasinglulu 
512*91f16700Schasinglulu 	status = usb_info_fill(phy_info);
513*91f16700Schasinglulu 	if (status != 0) {
514*91f16700Schasinglulu 		return (status == USB_PHY_ALREADY_STARTED) ? 0 : status;
515*91f16700Schasinglulu 	}
516*91f16700Schasinglulu 
517*91f16700Schasinglulu 	for (index = 0U; index < MAX_NR_PORTS; index++) {
518*91f16700Schasinglulu 		if (phy_info->phy_port[index].enabled != 0U) {
519*91f16700Schasinglulu 			switch (phy_info->phy_id) {
520*91f16700Schasinglulu 			case USB3H_DRDU2_PHY:
521*91f16700Schasinglulu 				status =
522*91f16700Schasinglulu 				    u3h_u2drd_phy_power_on(&phy_info->
523*91f16700Schasinglulu 							   phy_port[index]);
524*91f16700Schasinglulu 				break;
525*91f16700Schasinglulu 			default:
526*91f16700Schasinglulu 				status =
527*91f16700Schasinglulu 				    u3drd_phy_power_on(&phy_info->
528*91f16700Schasinglulu 						       phy_port[index]);
529*91f16700Schasinglulu 			}
530*91f16700Schasinglulu 		}
531*91f16700Schasinglulu 	}
532*91f16700Schasinglulu 
533*91f16700Schasinglulu 	phy_info->initialized = !status;
534*91f16700Schasinglulu 	return status;
535*91f16700Schasinglulu }
536*91f16700Schasinglulu 
537*91f16700Schasinglulu void usb_phy_shutdown(usb_platform_dev *device)
538*91f16700Schasinglulu {
539*91f16700Schasinglulu 	usb_phy_t *phy_info;
540*91f16700Schasinglulu 	uint32_t index;
541*91f16700Schasinglulu 
542*91f16700Schasinglulu 	phy_info = (usb_phy_t *)device->pcd_id;
543*91f16700Schasinglulu 
544*91f16700Schasinglulu 	phy_info->initialized = 0U;
545*91f16700Schasinglulu 
546*91f16700Schasinglulu 	for (index = 0U; index < MAX_NR_PORTS; index++) {
547*91f16700Schasinglulu 		if (phy_info->phy_port[index].enabled != 0U) {
548*91f16700Schasinglulu 			switch (phy_info->phy_id) {
549*91f16700Schasinglulu 			case USB3H_DRDU2_PHY:
550*91f16700Schasinglulu 				u3h_u2drd_phy_power_off(&phy_info->
551*91f16700Schasinglulu 							phy_port[index]);
552*91f16700Schasinglulu 				break;
553*91f16700Schasinglulu 			case DRDU3_PHY:
554*91f16700Schasinglulu 				u3drd_phy_power_off(&phy_info->phy_port[index]);
555*91f16700Schasinglulu 				break;
556*91f16700Schasinglulu 			default:
557*91f16700Schasinglulu 				INFO("%s: invalid phy id 0x%x\n", __func__,
558*91f16700Schasinglulu 				     phy_info->phy_id);
559*91f16700Schasinglulu 			}
560*91f16700Schasinglulu 		}
561*91f16700Schasinglulu 	}
562*91f16700Schasinglulu }
563*91f16700Schasinglulu 
564*91f16700Schasinglulu int32_t usb_xhci_init(usb_platform_dev *device)
565*91f16700Schasinglulu {
566*91f16700Schasinglulu 	int32_t status;
567*91f16700Schasinglulu 
568*91f16700Schasinglulu 	status = usb_phy_init(device);
569*91f16700Schasinglulu 	if (status == USB_PHY_ALREADY_STARTED) {
570*91f16700Schasinglulu 		status = 0U;
571*91f16700Schasinglulu 	}
572*91f16700Schasinglulu 
573*91f16700Schasinglulu 	return status;
574*91f16700Schasinglulu }
575*91f16700Schasinglulu 
576*91f16700Schasinglulu int32_t usb_device_init(unsigned int usb_func)
577*91f16700Schasinglulu {
578*91f16700Schasinglulu 	int32_t status;
579*91f16700Schasinglulu 	int32_t devices_initialized = 0U;
580*91f16700Schasinglulu 
581*91f16700Schasinglulu 	if ((usb_func & USB3H_USB2DRD) != 0U) {
582*91f16700Schasinglulu 		status = usb_xhci_init(
583*91f16700Schasinglulu 				&xhci_devices_configs[USB3H_USB2DRD_PHY]);
584*91f16700Schasinglulu 		if (status == 0) {
585*91f16700Schasinglulu 			devices_initialized++;
586*91f16700Schasinglulu 		} else {
587*91f16700Schasinglulu 			ERROR("%s(): USB3H_USB2DRD init failure\n", __func__);
588*91f16700Schasinglulu 		}
589*91f16700Schasinglulu 	}
590*91f16700Schasinglulu 
591*91f16700Schasinglulu 	if ((usb_func & USB3_DRD) != 0U) {
592*91f16700Schasinglulu 		status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]);
593*91f16700Schasinglulu 		if (status == 0) {
594*91f16700Schasinglulu 			devices_initialized++;
595*91f16700Schasinglulu 		} else {
596*91f16700Schasinglulu 			ERROR("%s(): USB3_DRD init failure\n", __func__);
597*91f16700Schasinglulu 		}
598*91f16700Schasinglulu 	}
599*91f16700Schasinglulu 
600*91f16700Schasinglulu 	return devices_initialized;
601*91f16700Schasinglulu }
602