1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * phy-brcm-usb-init.c - Broadcom USB Phy chip specific init functions
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2014-2017 Broadcom
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * This module contains USB PHY initialization for power up and S3 resume
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/soc/brcmstb/brcmstb.h>
16*4882a593Smuzhiyun #include "phy-brcm-usb-init.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define PHY_PORTS 2
19*4882a593Smuzhiyun #define PHY_PORT_SELECT_0 0
20*4882a593Smuzhiyun #define PHY_PORT_SELECT_1 0x1000
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* Register definitions for the USB CTRL block */
23*4882a593Smuzhiyun #define USB_CTRL_SETUP 0x00
24*4882a593Smuzhiyun #define USB_CTRL_SETUP_IOC_MASK 0x00000010
25*4882a593Smuzhiyun #define USB_CTRL_SETUP_IPP_MASK 0x00000020
26*4882a593Smuzhiyun #define USB_CTRL_SETUP_BABO_MASK 0x00000001
27*4882a593Smuzhiyun #define USB_CTRL_SETUP_FNHW_MASK 0x00000002
28*4882a593Smuzhiyun #define USB_CTRL_SETUP_FNBO_MASK 0x00000004
29*4882a593Smuzhiyun #define USB_CTRL_SETUP_WABO_MASK 0x00000008
30*4882a593Smuzhiyun #define USB_CTRL_SETUP_SCB_CLIENT_SWAP_MASK 0x00002000 /* option */
31*4882a593Smuzhiyun #define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000 /* option */
32*4882a593Smuzhiyun #define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000 /* option */
33*4882a593Smuzhiyun #define USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK 0X00020000 /* option */
34*4882a593Smuzhiyun #define USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK 0x00010000 /* option */
35*4882a593Smuzhiyun #define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000 /* option */
36*4882a593Smuzhiyun #define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK 0x04000000 /* option */
37*4882a593Smuzhiyun #define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK 0x08000000 /* opt */
38*4882a593Smuzhiyun #define USB_CTRL_SETUP_OC3_DISABLE_MASK 0xc0000000 /* option */
39*4882a593Smuzhiyun #define USB_CTRL_PLL_CTL 0x04
40*4882a593Smuzhiyun #define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK 0x08000000
41*4882a593Smuzhiyun #define USB_CTRL_PLL_CTL_PLL_RESETB_MASK 0x40000000
42*4882a593Smuzhiyun #define USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK 0x80000000 /* option */
43*4882a593Smuzhiyun #define USB_CTRL_EBRIDGE 0x0c
44*4882a593Smuzhiyun #define USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK 0x00020000 /* option */
45*4882a593Smuzhiyun #define USB_CTRL_EBRIDGE_EBR_SCB_SIZE_MASK 0x00000f80 /* option */
46*4882a593Smuzhiyun #define USB_CTRL_OBRIDGE 0x10
47*4882a593Smuzhiyun #define USB_CTRL_OBRIDGE_LS_KEEP_ALIVE_MASK 0x08000000
48*4882a593Smuzhiyun #define USB_CTRL_MDIO 0x14
49*4882a593Smuzhiyun #define USB_CTRL_MDIO2 0x18
50*4882a593Smuzhiyun #define USB_CTRL_UTMI_CTL_1 0x2c
51*4882a593Smuzhiyun #define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
52*4882a593Smuzhiyun #define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_P1_MASK 0x08000000
53*4882a593Smuzhiyun #define USB_CTRL_USB_PM 0x34
54*4882a593Smuzhiyun #define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK 0x00800000 /* option */
55*4882a593Smuzhiyun #define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK 0x00400000 /* option */
56*4882a593Smuzhiyun #define USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK 0x40000000 /* option */
57*4882a593Smuzhiyun #define USB_CTRL_USB_PM_USB_PWRDN_MASK 0x80000000 /* option */
58*4882a593Smuzhiyun #define USB_CTRL_USB_PM_SOFT_RESET_MASK 0x40000000 /* option */
59*4882a593Smuzhiyun #define USB_CTRL_USB_PM_USB20_HC_RESETB_MASK 0x30000000 /* option */
60*4882a593Smuzhiyun #define USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK 0x00300000 /* option */
61*4882a593Smuzhiyun #define USB_CTRL_USB_PM_RMTWKUP_EN_MASK 0x00000001
62*4882a593Smuzhiyun #define USB_CTRL_USB_PM_STATUS 0x38
63*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1 0x60
64*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1_PHY3_PLL_SEQ_START_MASK 0x00000010
65*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1_PHY3_RESETB_MASK 0x00010000
66*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK 0x00020000 /* option */
67*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1_USB3_IOC_MASK 0x10000000 /* option */
68*4882a593Smuzhiyun #define USB_CTRL_USB30_CTL1_USB3_IPP_MASK 0x20000000 /* option */
69*4882a593Smuzhiyun #define USB_CTRL_USB30_PCTL 0x70
70*4882a593Smuzhiyun #define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK 0x00000002
71*4882a593Smuzhiyun #define USB_CTRL_USB30_PCTL_PHY3_IDDQ_OVERRIDE_MASK 0x00008000
72*4882a593Smuzhiyun #define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK 0x00020000
73*4882a593Smuzhiyun #define USB_CTRL_USB_DEVICE_CTL1 0x90
74*4882a593Smuzhiyun #define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 /* option */
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Register definitions for the XHCI EC block */
77*4882a593Smuzhiyun #define USB_XHCI_EC_IRAADR 0x658
78*4882a593Smuzhiyun #define USB_XHCI_EC_IRADAT 0x65c
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun enum brcm_family_type {
81*4882a593Smuzhiyun BRCM_FAMILY_3390A0,
82*4882a593Smuzhiyun BRCM_FAMILY_7250B0,
83*4882a593Smuzhiyun BRCM_FAMILY_7271A0,
84*4882a593Smuzhiyun BRCM_FAMILY_7364A0,
85*4882a593Smuzhiyun BRCM_FAMILY_7366C0,
86*4882a593Smuzhiyun BRCM_FAMILY_74371A0,
87*4882a593Smuzhiyun BRCM_FAMILY_7439B0,
88*4882a593Smuzhiyun BRCM_FAMILY_7445D0,
89*4882a593Smuzhiyun BRCM_FAMILY_7260A0,
90*4882a593Smuzhiyun BRCM_FAMILY_7278A0,
91*4882a593Smuzhiyun BRCM_FAMILY_COUNT,
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun #define USB_BRCM_FAMILY(chip) \
95*4882a593Smuzhiyun [BRCM_FAMILY_##chip] = __stringify(chip)
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun static const char *family_names[BRCM_FAMILY_COUNT] = {
98*4882a593Smuzhiyun USB_BRCM_FAMILY(3390A0),
99*4882a593Smuzhiyun USB_BRCM_FAMILY(7250B0),
100*4882a593Smuzhiyun USB_BRCM_FAMILY(7271A0),
101*4882a593Smuzhiyun USB_BRCM_FAMILY(7364A0),
102*4882a593Smuzhiyun USB_BRCM_FAMILY(7366C0),
103*4882a593Smuzhiyun USB_BRCM_FAMILY(74371A0),
104*4882a593Smuzhiyun USB_BRCM_FAMILY(7439B0),
105*4882a593Smuzhiyun USB_BRCM_FAMILY(7445D0),
106*4882a593Smuzhiyun USB_BRCM_FAMILY(7260A0),
107*4882a593Smuzhiyun USB_BRCM_FAMILY(7278A0),
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun enum {
111*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_SELECTOR,
112*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_SELECTOR,
113*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR,
114*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR,
115*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_SELECTOR,
116*4882a593Smuzhiyun USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR,
117*4882a593Smuzhiyun USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR,
118*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR,
119*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_SELECTOR,
120*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR,
121*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR,
122*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR,
123*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR,
124*4882a593Smuzhiyun USB_CTRL_USB_PM_SOFT_RESET_SELECTOR,
125*4882a593Smuzhiyun USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR,
126*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR,
127*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR,
128*4882a593Smuzhiyun USB_CTRL_SETUP_ENDIAN_SELECTOR,
129*4882a593Smuzhiyun USB_CTRL_SELECTOR_COUNT,
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #define USB_CTRL_MASK_FAMILY(params, reg, field) \
133*4882a593Smuzhiyun (params->usb_reg_bits_map[USB_CTRL_##reg##_##field##_SELECTOR])
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun #define USB_CTRL_SET_FAMILY(params, reg, field) \
136*4882a593Smuzhiyun usb_ctrl_set_family(params, USB_CTRL_##reg, \
137*4882a593Smuzhiyun USB_CTRL_##reg##_##field##_SELECTOR)
138*4882a593Smuzhiyun #define USB_CTRL_UNSET_FAMILY(params, reg, field) \
139*4882a593Smuzhiyun usb_ctrl_unset_family(params, USB_CTRL_##reg, \
140*4882a593Smuzhiyun USB_CTRL_##reg##_##field##_SELECTOR)
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun #define MDIO_USB2 0
143*4882a593Smuzhiyun #define MDIO_USB3 BIT(31)
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun #define USB_CTRL_SETUP_ENDIAN_BITS ( \
146*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, BABO) | \
147*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, FNHW) | \
148*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, FNBO) | \
149*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, WABO))
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN
152*4882a593Smuzhiyun #define ENDIAN_SETTINGS ( \
153*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, BABO) | \
154*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, FNHW))
155*4882a593Smuzhiyun #else
156*4882a593Smuzhiyun #define ENDIAN_SETTINGS ( \
157*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, FNHW) | \
158*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, FNBO) | \
159*4882a593Smuzhiyun USB_CTRL_MASK(SETUP, WABO))
160*4882a593Smuzhiyun #endif
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun struct id_to_type {
163*4882a593Smuzhiyun u32 id;
164*4882a593Smuzhiyun int type;
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static const struct id_to_type id_to_type_table[] = {
168*4882a593Smuzhiyun { 0x33900000, BRCM_FAMILY_3390A0 },
169*4882a593Smuzhiyun { 0x72500010, BRCM_FAMILY_7250B0 },
170*4882a593Smuzhiyun { 0x72600000, BRCM_FAMILY_7260A0 },
171*4882a593Smuzhiyun { 0x72550000, BRCM_FAMILY_7260A0 },
172*4882a593Smuzhiyun { 0x72680000, BRCM_FAMILY_7271A0 },
173*4882a593Smuzhiyun { 0x72710000, BRCM_FAMILY_7271A0 },
174*4882a593Smuzhiyun { 0x73640000, BRCM_FAMILY_7364A0 },
175*4882a593Smuzhiyun { 0x73660020, BRCM_FAMILY_7366C0 },
176*4882a593Smuzhiyun { 0x07437100, BRCM_FAMILY_74371A0 },
177*4882a593Smuzhiyun { 0x74390010, BRCM_FAMILY_7439B0 },
178*4882a593Smuzhiyun { 0x74450030, BRCM_FAMILY_7445D0 },
179*4882a593Smuzhiyun { 0x72780000, BRCM_FAMILY_7278A0 },
180*4882a593Smuzhiyun { 0, BRCM_FAMILY_7271A0 }, /* default */
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun static const u32
184*4882a593Smuzhiyun usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
185*4882a593Smuzhiyun /* 3390B0 */
186*4882a593Smuzhiyun [BRCM_FAMILY_3390A0] = {
187*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
188*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
189*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
190*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
191*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
192*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
193*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
194*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
195*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
196*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
197*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
198*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
199*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
200*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
201*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
202*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
203*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
204*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
205*4882a593Smuzhiyun },
206*4882a593Smuzhiyun /* 7250b0 */
207*4882a593Smuzhiyun [BRCM_FAMILY_7250B0] = {
208*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
209*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
210*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
211*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
212*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
213*4882a593Smuzhiyun USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
214*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
215*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
216*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
217*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
218*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
219*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
220*4882a593Smuzhiyun 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
221*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
222*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
223*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
224*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
225*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
226*4882a593Smuzhiyun },
227*4882a593Smuzhiyun /* 7271a0 */
228*4882a593Smuzhiyun [BRCM_FAMILY_7271A0] = {
229*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
230*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
231*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
232*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
233*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
234*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
235*4882a593Smuzhiyun USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
236*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
237*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
238*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
239*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
240*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
241*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
242*4882a593Smuzhiyun USB_CTRL_USB_PM_SOFT_RESET_MASK,
243*4882a593Smuzhiyun USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
244*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
245*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
246*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
247*4882a593Smuzhiyun },
248*4882a593Smuzhiyun /* 7364a0 */
249*4882a593Smuzhiyun [BRCM_FAMILY_7364A0] = {
250*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
251*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
252*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
253*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
254*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
255*4882a593Smuzhiyun USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
256*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
257*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
258*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
259*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
260*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
261*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
262*4882a593Smuzhiyun 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
263*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
264*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
265*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
266*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
267*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
268*4882a593Smuzhiyun },
269*4882a593Smuzhiyun /* 7366c0 */
270*4882a593Smuzhiyun [BRCM_FAMILY_7366C0] = {
271*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
272*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
273*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
274*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
275*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
276*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
277*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
278*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
279*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
280*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
281*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
282*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
283*4882a593Smuzhiyun 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
284*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
285*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
286*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
287*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
288*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
289*4882a593Smuzhiyun },
290*4882a593Smuzhiyun /* 74371A0 */
291*4882a593Smuzhiyun [BRCM_FAMILY_74371A0] = {
292*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
293*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
294*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
295*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
296*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
297*4882a593Smuzhiyun USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
298*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
299*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
300*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
301*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
302*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
303*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
304*4882a593Smuzhiyun 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
305*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
306*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
307*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
308*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
309*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
310*4882a593Smuzhiyun },
311*4882a593Smuzhiyun /* 7439B0 */
312*4882a593Smuzhiyun [BRCM_FAMILY_7439B0] = {
313*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
314*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
315*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
316*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
317*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
318*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
319*4882a593Smuzhiyun USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
320*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
321*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
322*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
323*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
324*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
325*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
326*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
327*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
328*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
329*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
330*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
331*4882a593Smuzhiyun },
332*4882a593Smuzhiyun /* 7445d0 */
333*4882a593Smuzhiyun [BRCM_FAMILY_7445D0] = {
334*4882a593Smuzhiyun USB_CTRL_SETUP_SCB1_EN_MASK,
335*4882a593Smuzhiyun USB_CTRL_SETUP_SCB2_EN_MASK,
336*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
337*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
338*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
339*4882a593Smuzhiyun USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
340*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
341*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
342*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
343*4882a593Smuzhiyun USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
344*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
345*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
346*4882a593Smuzhiyun 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
347*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
348*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
349*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
350*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
351*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
352*4882a593Smuzhiyun },
353*4882a593Smuzhiyun /* 7260a0 */
354*4882a593Smuzhiyun [BRCM_FAMILY_7260A0] = {
355*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
356*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
357*4882a593Smuzhiyun USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
358*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
359*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
360*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
361*4882a593Smuzhiyun USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
362*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
363*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
364*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
365*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
366*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
367*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
368*4882a593Smuzhiyun USB_CTRL_USB_PM_SOFT_RESET_MASK,
369*4882a593Smuzhiyun USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
370*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
371*4882a593Smuzhiyun USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
372*4882a593Smuzhiyun ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
373*4882a593Smuzhiyun },
374*4882a593Smuzhiyun /* 7278a0 */
375*4882a593Smuzhiyun [BRCM_FAMILY_7278A0] = {
376*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
377*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
378*4882a593Smuzhiyun 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
379*4882a593Smuzhiyun USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
380*4882a593Smuzhiyun USB_CTRL_SETUP_OC3_DISABLE_MASK,
381*4882a593Smuzhiyun 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
382*4882a593Smuzhiyun USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
383*4882a593Smuzhiyun USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
384*4882a593Smuzhiyun USB_CTRL_USB_PM_USB_PWRDN_MASK,
385*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
386*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
387*4882a593Smuzhiyun 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
388*4882a593Smuzhiyun USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
389*4882a593Smuzhiyun USB_CTRL_USB_PM_SOFT_RESET_MASK,
390*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
391*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
392*4882a593Smuzhiyun 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
393*4882a593Smuzhiyun 0, /* USB_CTRL_SETUP ENDIAN bits */
394*4882a593Smuzhiyun },
395*4882a593Smuzhiyun };
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun static inline
usb_ctrl_unset_family(struct brcm_usb_init_params * params,u32 reg_offset,u32 field)398*4882a593Smuzhiyun void usb_ctrl_unset_family(struct brcm_usb_init_params *params,
399*4882a593Smuzhiyun u32 reg_offset, u32 field)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun u32 mask;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun mask = params->usb_reg_bits_map[field];
404*4882a593Smuzhiyun brcm_usb_ctrl_unset(params->regs[BRCM_REGS_CTRL] + reg_offset, mask);
405*4882a593Smuzhiyun };
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun static inline
usb_ctrl_set_family(struct brcm_usb_init_params * params,u32 reg_offset,u32 field)408*4882a593Smuzhiyun void usb_ctrl_set_family(struct brcm_usb_init_params *params,
409*4882a593Smuzhiyun u32 reg_offset, u32 field)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun u32 mask;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun mask = params->usb_reg_bits_map[field];
414*4882a593Smuzhiyun brcm_usb_ctrl_set(params->regs[BRCM_REGS_CTRL] + reg_offset, mask);
415*4882a593Smuzhiyun };
416*4882a593Smuzhiyun
brcmusb_usb_mdio_read(void __iomem * ctrl_base,u32 reg,int mode)417*4882a593Smuzhiyun static u32 brcmusb_usb_mdio_read(void __iomem *ctrl_base, u32 reg, int mode)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun u32 data;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun data = (reg << 16) | mode;
422*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
423*4882a593Smuzhiyun data |= (1 << 24);
424*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
425*4882a593Smuzhiyun data &= ~(1 << 24);
426*4882a593Smuzhiyun /* wait for the 60MHz parallel to serial shifter */
427*4882a593Smuzhiyun usleep_range(10, 20);
428*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
429*4882a593Smuzhiyun /* wait for the 60MHz parallel to serial shifter */
430*4882a593Smuzhiyun usleep_range(10, 20);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun return brcm_usb_readl(USB_CTRL_REG(ctrl_base, MDIO2)) & 0xffff;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
brcmusb_usb_mdio_write(void __iomem * ctrl_base,u32 reg,u32 val,int mode)435*4882a593Smuzhiyun static void brcmusb_usb_mdio_write(void __iomem *ctrl_base, u32 reg,
436*4882a593Smuzhiyun u32 val, int mode)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun u32 data;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun data = (reg << 16) | val | mode;
441*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
442*4882a593Smuzhiyun data |= (1 << 25);
443*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
444*4882a593Smuzhiyun data &= ~(1 << 25);
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /* wait for the 60MHz parallel to serial shifter */
447*4882a593Smuzhiyun usleep_range(10, 20);
448*4882a593Smuzhiyun brcm_usb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
449*4882a593Smuzhiyun /* wait for the 60MHz parallel to serial shifter */
450*4882a593Smuzhiyun usleep_range(10, 20);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
brcmusb_usb_phy_ldo_fix(void __iomem * ctrl_base)453*4882a593Smuzhiyun static void brcmusb_usb_phy_ldo_fix(void __iomem *ctrl_base)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun /* first disable FSM but also leave it that way */
456*4882a593Smuzhiyun /* to allow normal suspend/resume */
457*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl_base, UTMI_CTL_1, POWER_UP_FSM_EN);
458*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl_base, UTMI_CTL_1, POWER_UP_FSM_EN_P1);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /* reset USB 2.0 PLL */
461*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl_base, PLL_CTL, PLL_RESETB);
462*4882a593Smuzhiyun /* PLL reset period */
463*4882a593Smuzhiyun udelay(1);
464*4882a593Smuzhiyun USB_CTRL_SET(ctrl_base, PLL_CTL, PLL_RESETB);
465*4882a593Smuzhiyun /* Give PLL enough time to lock */
466*4882a593Smuzhiyun usleep_range(1000, 2000);
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
brcmusb_usb2_eye_fix(void __iomem * ctrl_base)469*4882a593Smuzhiyun static void brcmusb_usb2_eye_fix(void __iomem *ctrl_base)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun /* Increase USB 2.0 TX level to meet spec requirement */
472*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x80a0, MDIO_USB2);
473*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x0a, 0xc6a0, MDIO_USB2);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
brcmusb_usb3_pll_fix(void __iomem * ctrl_base)476*4882a593Smuzhiyun static void brcmusb_usb3_pll_fix(void __iomem *ctrl_base)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun /* Set correct window for PLL lock detect */
479*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
480*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x07, 0x1503, MDIO_USB3);
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
brcmusb_usb3_enable_pipe_reset(void __iomem * ctrl_base)483*4882a593Smuzhiyun static void brcmusb_usb3_enable_pipe_reset(void __iomem *ctrl_base)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun u32 val;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /* Re-enable USB 3.0 pipe reset */
488*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
489*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x0f, MDIO_USB3) | 0x200;
490*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x0f, val, MDIO_USB3);
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
brcmusb_usb3_enable_sigdet(void __iomem * ctrl_base)493*4882a593Smuzhiyun static void brcmusb_usb3_enable_sigdet(void __iomem *ctrl_base)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun u32 val, ofs;
496*4882a593Smuzhiyun int ii;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun ofs = 0;
499*4882a593Smuzhiyun for (ii = 0; ii < PHY_PORTS; ++ii) {
500*4882a593Smuzhiyun /* Set correct default for sigdet */
501*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8080 + ofs),
502*4882a593Smuzhiyun MDIO_USB3);
503*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x05, MDIO_USB3);
504*4882a593Smuzhiyun val = (val & ~0x800f) | 0x800d;
505*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x05, val, MDIO_USB3);
506*4882a593Smuzhiyun ofs = PHY_PORT_SELECT_1;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
brcmusb_usb3_enable_skip_align(void __iomem * ctrl_base)510*4882a593Smuzhiyun static void brcmusb_usb3_enable_skip_align(void __iomem *ctrl_base)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun u32 val, ofs;
513*4882a593Smuzhiyun int ii;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun ofs = 0;
516*4882a593Smuzhiyun for (ii = 0; ii < PHY_PORTS; ++ii) {
517*4882a593Smuzhiyun /* Set correct default for SKIP align */
518*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8060 + ofs),
519*4882a593Smuzhiyun MDIO_USB3);
520*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0x200;
521*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
522*4882a593Smuzhiyun ofs = PHY_PORT_SELECT_1;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
brcmusb_usb3_unfreeze_aeq(void __iomem * ctrl_base)526*4882a593Smuzhiyun static void brcmusb_usb3_unfreeze_aeq(void __iomem *ctrl_base)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun u32 val, ofs;
529*4882a593Smuzhiyun int ii;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun ofs = 0;
532*4882a593Smuzhiyun for (ii = 0; ii < PHY_PORTS; ++ii) {
533*4882a593Smuzhiyun /* Let EQ freeze after TSEQ */
534*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x80e0 + ofs),
535*4882a593Smuzhiyun MDIO_USB3);
536*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3);
537*4882a593Smuzhiyun val &= ~0x0008;
538*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
539*4882a593Smuzhiyun ofs = PHY_PORT_SELECT_1;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
brcmusb_usb3_pll_54mhz(struct brcm_usb_init_params * params)543*4882a593Smuzhiyun static void brcmusb_usb3_pll_54mhz(struct brcm_usb_init_params *params)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun u32 ofs;
546*4882a593Smuzhiyun int ii;
547*4882a593Smuzhiyun void __iomem *ctrl_base = params->regs[BRCM_REGS_CTRL];
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /*
550*4882a593Smuzhiyun * On newer B53 based SoC's, the reference clock for the
551*4882a593Smuzhiyun * 3.0 PLL has been changed from 50MHz to 54MHz so the
552*4882a593Smuzhiyun * PLL needs to be reprogrammed.
553*4882a593Smuzhiyun * See SWLINUX-4006.
554*4882a593Smuzhiyun *
555*4882a593Smuzhiyun * On the 7364C0, the reference clock for the
556*4882a593Smuzhiyun * 3.0 PLL has been changed from 50MHz to 54MHz to
557*4882a593Smuzhiyun * work around a MOCA issue.
558*4882a593Smuzhiyun * See SWLINUX-4169.
559*4882a593Smuzhiyun */
560*4882a593Smuzhiyun switch (params->selected_family) {
561*4882a593Smuzhiyun case BRCM_FAMILY_3390A0:
562*4882a593Smuzhiyun case BRCM_FAMILY_7250B0:
563*4882a593Smuzhiyun case BRCM_FAMILY_7366C0:
564*4882a593Smuzhiyun case BRCM_FAMILY_74371A0:
565*4882a593Smuzhiyun case BRCM_FAMILY_7439B0:
566*4882a593Smuzhiyun case BRCM_FAMILY_7445D0:
567*4882a593Smuzhiyun case BRCM_FAMILY_7260A0:
568*4882a593Smuzhiyun return;
569*4882a593Smuzhiyun case BRCM_FAMILY_7364A0:
570*4882a593Smuzhiyun if (BRCM_REV(params->family_id) < 0x20)
571*4882a593Smuzhiyun return;
572*4882a593Smuzhiyun break;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun /* set USB 3.0 PLL to accept 54Mhz reference clock */
576*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl_base, USB30_CTL1, PHY3_PLL_SEQ_START);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
579*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x10, 0x5784, MDIO_USB3);
580*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x11, 0x01d0, MDIO_USB3);
581*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x12, 0x1DE8, MDIO_USB3);
582*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x13, 0xAA80, MDIO_USB3);
583*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x14, 0x8826, MDIO_USB3);
584*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x15, 0x0044, MDIO_USB3);
585*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x16, 0x8000, MDIO_USB3);
586*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x17, 0x0851, MDIO_USB3);
587*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x18, 0x0000, MDIO_USB3);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun /* both ports */
590*4882a593Smuzhiyun ofs = 0;
591*4882a593Smuzhiyun for (ii = 0; ii < PHY_PORTS; ++ii) {
592*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8040 + ofs),
593*4882a593Smuzhiyun MDIO_USB3);
594*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x03, 0x0090, MDIO_USB3);
595*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x04, 0x0134, MDIO_USB3);
596*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8020 + ofs),
597*4882a593Smuzhiyun MDIO_USB3);
598*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x01, 0x00e2, MDIO_USB3);
599*4882a593Smuzhiyun ofs = PHY_PORT_SELECT_1;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* restart PLL sequence */
603*4882a593Smuzhiyun USB_CTRL_SET(ctrl_base, USB30_CTL1, PHY3_PLL_SEQ_START);
604*4882a593Smuzhiyun /* Give PLL enough time to lock */
605*4882a593Smuzhiyun usleep_range(1000, 2000);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
brcmusb_usb3_ssc_enable(void __iomem * ctrl_base)608*4882a593Smuzhiyun static void brcmusb_usb3_ssc_enable(void __iomem *ctrl_base)
609*4882a593Smuzhiyun {
610*4882a593Smuzhiyun u32 val;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun /* Enable USB 3.0 TX spread spectrum */
613*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8040, MDIO_USB3);
614*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0xf;
615*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun /* Currently, USB 3.0 SSC is enabled via port 0 MDIO registers,
618*4882a593Smuzhiyun * which should have been adequate. However, due to a bug in the
619*4882a593Smuzhiyun * USB 3.0 PHY, it must be enabled via both ports (HWUSB3DVT-26).
620*4882a593Smuzhiyun */
621*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x9040, MDIO_USB3);
622*4882a593Smuzhiyun val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0xf;
623*4882a593Smuzhiyun brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
brcmusb_usb3_phy_workarounds(struct brcm_usb_init_params * params)626*4882a593Smuzhiyun static void brcmusb_usb3_phy_workarounds(struct brcm_usb_init_params *params)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun void __iomem *ctrl_base = params->regs[BRCM_REGS_CTRL];
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun brcmusb_usb3_pll_fix(ctrl_base);
631*4882a593Smuzhiyun brcmusb_usb3_pll_54mhz(params);
632*4882a593Smuzhiyun brcmusb_usb3_ssc_enable(ctrl_base);
633*4882a593Smuzhiyun brcmusb_usb3_enable_pipe_reset(ctrl_base);
634*4882a593Smuzhiyun brcmusb_usb3_enable_sigdet(ctrl_base);
635*4882a593Smuzhiyun brcmusb_usb3_enable_skip_align(ctrl_base);
636*4882a593Smuzhiyun brcmusb_usb3_unfreeze_aeq(ctrl_base);
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
brcmusb_memc_fix(struct brcm_usb_init_params * params)639*4882a593Smuzhiyun static void brcmusb_memc_fix(struct brcm_usb_init_params *params)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun u32 prid;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun if (params->selected_family != BRCM_FAMILY_7445D0)
644*4882a593Smuzhiyun return;
645*4882a593Smuzhiyun /*
646*4882a593Smuzhiyun * This is a workaround for HW7445-1869 where a DMA write ends up
647*4882a593Smuzhiyun * doing a read pre-fetch after the end of the DMA buffer. This
648*4882a593Smuzhiyun * causes a problem when the DMA buffer is at the end of physical
649*4882a593Smuzhiyun * memory, causing the pre-fetch read to access non-existent memory,
650*4882a593Smuzhiyun * and the chip bondout has MEMC2 disabled. When the pre-fetch read
651*4882a593Smuzhiyun * tries to use the disabled MEMC2, it hangs the bus. The workaround
652*4882a593Smuzhiyun * is to disable MEMC2 access in the usb controller which avoids
653*4882a593Smuzhiyun * the hang.
654*4882a593Smuzhiyun */
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun prid = params->product_id & 0xfffff000;
657*4882a593Smuzhiyun switch (prid) {
658*4882a593Smuzhiyun case 0x72520000:
659*4882a593Smuzhiyun case 0x74480000:
660*4882a593Smuzhiyun case 0x74490000:
661*4882a593Smuzhiyun case 0x07252000:
662*4882a593Smuzhiyun case 0x07448000:
663*4882a593Smuzhiyun case 0x07449000:
664*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, SETUP, SCB2_EN);
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
brcmusb_usb3_otp_fix(struct brcm_usb_init_params * params)668*4882a593Smuzhiyun static void brcmusb_usb3_otp_fix(struct brcm_usb_init_params *params)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun void __iomem *xhci_ec_base = params->regs[BRCM_REGS_XHCI_EC];
671*4882a593Smuzhiyun u32 val;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (params->family_id != 0x74371000 || !xhci_ec_base)
674*4882a593Smuzhiyun return;
675*4882a593Smuzhiyun brcm_usb_writel(0xa20c, USB_XHCI_EC_REG(xhci_ec_base, IRAADR));
676*4882a593Smuzhiyun val = brcm_usb_readl(USB_XHCI_EC_REG(xhci_ec_base, IRADAT));
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun /* set cfg_pick_ss_lock */
679*4882a593Smuzhiyun val |= (1 << 27);
680*4882a593Smuzhiyun brcm_usb_writel(val, USB_XHCI_EC_REG(xhci_ec_base, IRADAT));
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun /* Reset USB 3.0 PHY for workaround to take effect */
683*4882a593Smuzhiyun USB_CTRL_UNSET(params->regs[BRCM_REGS_CTRL], USB30_CTL1, PHY3_RESETB);
684*4882a593Smuzhiyun USB_CTRL_SET(params->regs[BRCM_REGS_CTRL], USB30_CTL1, PHY3_RESETB);
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
brcmusb_xhci_soft_reset(struct brcm_usb_init_params * params,int on_off)687*4882a593Smuzhiyun static void brcmusb_xhci_soft_reset(struct brcm_usb_init_params *params,
688*4882a593Smuzhiyun int on_off)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun /* Assert reset */
691*4882a593Smuzhiyun if (on_off) {
692*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, XHC_SOFT_RESETB))
693*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, USB_PM, XHC_SOFT_RESETB);
694*4882a593Smuzhiyun else
695*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params,
696*4882a593Smuzhiyun USB30_CTL1, XHC_SOFT_RESETB);
697*4882a593Smuzhiyun } else { /* De-assert reset */
698*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, XHC_SOFT_RESETB))
699*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB_PM, XHC_SOFT_RESETB);
700*4882a593Smuzhiyun else
701*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB30_CTL1,
702*4882a593Smuzhiyun XHC_SOFT_RESETB);
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun /*
707*4882a593Smuzhiyun * Return the best map table family. The order is:
708*4882a593Smuzhiyun * - exact match of chip and major rev
709*4882a593Smuzhiyun * - exact match of chip and closest older major rev
710*4882a593Smuzhiyun * - default chip/rev.
711*4882a593Smuzhiyun * NOTE: The minor rev is always ignored.
712*4882a593Smuzhiyun */
get_family_type(struct brcm_usb_init_params * params)713*4882a593Smuzhiyun static enum brcm_family_type get_family_type(
714*4882a593Smuzhiyun struct brcm_usb_init_params *params)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun int last_type = -1;
717*4882a593Smuzhiyun u32 last_family = 0;
718*4882a593Smuzhiyun u32 family_no_major;
719*4882a593Smuzhiyun unsigned int x;
720*4882a593Smuzhiyun u32 family;
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun family = params->family_id & 0xfffffff0;
723*4882a593Smuzhiyun family_no_major = params->family_id & 0xffffff00;
724*4882a593Smuzhiyun for (x = 0; id_to_type_table[x].id; x++) {
725*4882a593Smuzhiyun if (family == id_to_type_table[x].id)
726*4882a593Smuzhiyun return id_to_type_table[x].type;
727*4882a593Smuzhiyun if (family_no_major == (id_to_type_table[x].id & 0xffffff00))
728*4882a593Smuzhiyun if (family > id_to_type_table[x].id &&
729*4882a593Smuzhiyun last_family < id_to_type_table[x].id) {
730*4882a593Smuzhiyun last_family = id_to_type_table[x].id;
731*4882a593Smuzhiyun last_type = id_to_type_table[x].type;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun /* If no match, return the default family */
736*4882a593Smuzhiyun if (last_type == -1)
737*4882a593Smuzhiyun return id_to_type_table[x].type;
738*4882a593Smuzhiyun return last_type;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
usb_init_ipp(struct brcm_usb_init_params * params)741*4882a593Smuzhiyun static void usb_init_ipp(struct brcm_usb_init_params *params)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
744*4882a593Smuzhiyun u32 reg;
745*4882a593Smuzhiyun u32 orig_reg;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun /* Starting with the 7445d0, there are no longer separate 3.0
748*4882a593Smuzhiyun * versions of IOC and IPP.
749*4882a593Smuzhiyun */
750*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB30_CTL1, USB3_IOC)) {
751*4882a593Smuzhiyun if (params->ioc)
752*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB30_CTL1, USB3_IOC);
753*4882a593Smuzhiyun if (params->ipp == 1)
754*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB30_CTL1, USB3_IPP);
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
758*4882a593Smuzhiyun orig_reg = reg;
759*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, SETUP, STRAP_CC_DRD_MODE_ENABLE_SEL))
760*4882a593Smuzhiyun /* Never use the strap, it's going away. */
761*4882a593Smuzhiyun reg &= ~(USB_CTRL_MASK_FAMILY(params,
762*4882a593Smuzhiyun SETUP,
763*4882a593Smuzhiyun STRAP_CC_DRD_MODE_ENABLE_SEL));
764*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, SETUP, STRAP_IPP_SEL))
765*4882a593Smuzhiyun /* override ipp strap pin (if it exits) */
766*4882a593Smuzhiyun if (params->ipp != 2)
767*4882a593Smuzhiyun reg &= ~(USB_CTRL_MASK_FAMILY(params, SETUP,
768*4882a593Smuzhiyun STRAP_IPP_SEL));
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun /* Override the default OC and PP polarity */
771*4882a593Smuzhiyun reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));
772*4882a593Smuzhiyun if (params->ioc)
773*4882a593Smuzhiyun reg |= USB_CTRL_MASK(SETUP, IOC);
774*4882a593Smuzhiyun if (params->ipp == 1)
775*4882a593Smuzhiyun reg |= USB_CTRL_MASK(SETUP, IPP);
776*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun /*
779*4882a593Smuzhiyun * If we're changing IPP, make sure power is off long enough
780*4882a593Smuzhiyun * to turn off any connected devices.
781*4882a593Smuzhiyun */
782*4882a593Smuzhiyun if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP))
783*4882a593Smuzhiyun msleep(50);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
usb_wake_enable(struct brcm_usb_init_params * params,bool enable)786*4882a593Smuzhiyun static void usb_wake_enable(struct brcm_usb_init_params *params,
787*4882a593Smuzhiyun bool enable)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun if (enable)
792*4882a593Smuzhiyun USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN);
793*4882a593Smuzhiyun else
794*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl, USB_PM, RMTWKUP_EN);
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
usb_init_common(struct brcm_usb_init_params * params)797*4882a593Smuzhiyun static void usb_init_common(struct brcm_usb_init_params *params)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun u32 reg;
800*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun /* Clear any pending wake conditions */
803*4882a593Smuzhiyun usb_wake_enable(params, false);
804*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM_STATUS));
805*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_PM_STATUS));
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun /* Take USB out of power down */
808*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN)) {
809*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
810*4882a593Smuzhiyun /* 1 millisecond - for USB clocks to settle down */
811*4882a593Smuzhiyun usleep_range(1000, 2000);
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB_PWRDN)) {
815*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, USB_PM, USB_PWRDN);
816*4882a593Smuzhiyun /* 1 millisecond - for USB clocks to settle down */
817*4882a593Smuzhiyun usleep_range(1000, 2000);
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (params->selected_family != BRCM_FAMILY_74371A0 &&
821*4882a593Smuzhiyun (BRCM_ID(params->family_id) != 0x7364))
822*4882a593Smuzhiyun /*
823*4882a593Smuzhiyun * HW7439-637: 7439a0 and its derivatives do not have large
824*4882a593Smuzhiyun * enough descriptor storage for this.
825*4882a593Smuzhiyun */
826*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, SETUP, SS_EHCI64BIT_EN);
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun /* Block auto PLL suspend by USB2 PHY (Sasi) */
829*4882a593Smuzhiyun USB_CTRL_SET(ctrl, PLL_CTL, PLL_SUSPEND_EN);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
832*4882a593Smuzhiyun if (params->selected_family == BRCM_FAMILY_7364A0)
833*4882a593Smuzhiyun /* Suppress overcurrent indication from USB30 ports for A0 */
834*4882a593Smuzhiyun reg |= USB_CTRL_MASK_FAMILY(params, SETUP, OC3_DISABLE);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun brcmusb_usb_phy_ldo_fix(ctrl);
837*4882a593Smuzhiyun brcmusb_usb2_eye_fix(ctrl);
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun /*
840*4882a593Smuzhiyun * Make sure the the second and third memory controller
841*4882a593Smuzhiyun * interfaces are enabled if they exist.
842*4882a593Smuzhiyun */
843*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, SETUP, SCB1_EN))
844*4882a593Smuzhiyun reg |= USB_CTRL_MASK_FAMILY(params, SETUP, SCB1_EN);
845*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, SETUP, SCB2_EN))
846*4882a593Smuzhiyun reg |= USB_CTRL_MASK_FAMILY(params, SETUP, SCB2_EN);
847*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun brcmusb_memc_fix(params);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
852*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
853*4882a593Smuzhiyun reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
854*4882a593Smuzhiyun PORT_MODE);
855*4882a593Smuzhiyun reg |= params->mode;
856*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, BDC_SOFT_RESETB)) {
859*4882a593Smuzhiyun switch (params->mode) {
860*4882a593Smuzhiyun case USB_CTLR_MODE_HOST:
861*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
862*4882a593Smuzhiyun break;
863*4882a593Smuzhiyun default:
864*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
865*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
866*4882a593Smuzhiyun break;
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE)) {
870*4882a593Smuzhiyun if (params->mode == USB_CTLR_MODE_TYPEC_PD)
871*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE);
872*4882a593Smuzhiyun else
873*4882a593Smuzhiyun USB_CTRL_UNSET_FAMILY(params, SETUP,
874*4882a593Smuzhiyun CC_DRD_MODE_ENABLE);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun }
877*4882a593Smuzhiyun
usb_init_eohci(struct brcm_usb_init_params * params)878*4882a593Smuzhiyun static void usb_init_eohci(struct brcm_usb_init_params *params)
879*4882a593Smuzhiyun {
880*4882a593Smuzhiyun u32 reg;
881*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB20_HC_RESETB))
884*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB_PM, USB20_HC_RESETB);
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun if (params->selected_family == BRCM_FAMILY_7366C0)
887*4882a593Smuzhiyun /*
888*4882a593Smuzhiyun * Don't enable this so the memory controller doesn't read
889*4882a593Smuzhiyun * into memory holes. NOTE: This bit is low true on 7366C0.
890*4882a593Smuzhiyun */
891*4882a593Smuzhiyun USB_CTRL_SET(ctrl, EBRIDGE, ESTOP_SCB_REQ);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun /* Setup the endian bits */
894*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
895*4882a593Smuzhiyun reg &= ~USB_CTRL_SETUP_ENDIAN_BITS;
896*4882a593Smuzhiyun reg |= USB_CTRL_MASK_FAMILY(params, SETUP, ENDIAN);
897*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun if (params->selected_family == BRCM_FAMILY_7271A0)
900*4882a593Smuzhiyun /* Enable LS keep alive fix for certain keyboards */
901*4882a593Smuzhiyun USB_CTRL_SET(ctrl, OBRIDGE, LS_KEEP_ALIVE);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (params->family_id == 0x72550000) {
904*4882a593Smuzhiyun /*
905*4882a593Smuzhiyun * Make the burst size 512 bytes to fix a hardware bug
906*4882a593Smuzhiyun * on the 7255a0. See HW7255-24.
907*4882a593Smuzhiyun */
908*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, EBRIDGE));
909*4882a593Smuzhiyun reg &= ~USB_CTRL_MASK(EBRIDGE, EBR_SCB_SIZE);
910*4882a593Smuzhiyun reg |= 0x800;
911*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, EBRIDGE));
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun
usb_init_xhci(struct brcm_usb_init_params * params)915*4882a593Smuzhiyun static void usb_init_xhci(struct brcm_usb_init_params *params)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl, USB30_PCTL, PHY3_IDDQ_OVERRIDE);
920*4882a593Smuzhiyun /* 1 millisecond - for USB clocks to settle down */
921*4882a593Smuzhiyun usleep_range(1000, 2000);
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun if (BRCM_ID(params->family_id) == 0x7366) {
924*4882a593Smuzhiyun /*
925*4882a593Smuzhiyun * The PHY3_SOFT_RESETB bits default to the wrong state.
926*4882a593Smuzhiyun */
927*4882a593Smuzhiyun USB_CTRL_SET(ctrl, USB30_PCTL, PHY3_SOFT_RESETB);
928*4882a593Smuzhiyun USB_CTRL_SET(ctrl, USB30_PCTL, PHY3_SOFT_RESETB_P1);
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /*
932*4882a593Smuzhiyun * Kick start USB3 PHY
933*4882a593Smuzhiyun * Make sure it's low to insure a rising edge.
934*4882a593Smuzhiyun */
935*4882a593Smuzhiyun USB_CTRL_UNSET(ctrl, USB30_CTL1, PHY3_PLL_SEQ_START);
936*4882a593Smuzhiyun USB_CTRL_SET(ctrl, USB30_CTL1, PHY3_PLL_SEQ_START);
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun brcmusb_usb3_phy_workarounds(params);
939*4882a593Smuzhiyun brcmusb_xhci_soft_reset(params, 0);
940*4882a593Smuzhiyun brcmusb_usb3_otp_fix(params);
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
usb_uninit_common(struct brcm_usb_init_params * params)943*4882a593Smuzhiyun static void usb_uninit_common(struct brcm_usb_init_params *params)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB_PWRDN))
946*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, USB_PM, USB_PWRDN);
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN))
949*4882a593Smuzhiyun USB_CTRL_SET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
950*4882a593Smuzhiyun if (params->wake_enabled)
951*4882a593Smuzhiyun usb_wake_enable(params, true);
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun
usb_uninit_eohci(struct brcm_usb_init_params * params)954*4882a593Smuzhiyun static void usb_uninit_eohci(struct brcm_usb_init_params *params)
955*4882a593Smuzhiyun {
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
usb_uninit_xhci(struct brcm_usb_init_params * params)958*4882a593Smuzhiyun static void usb_uninit_xhci(struct brcm_usb_init_params *params)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun brcmusb_xhci_soft_reset(params, 1);
961*4882a593Smuzhiyun USB_CTRL_SET(params->regs[BRCM_REGS_CTRL], USB30_PCTL,
962*4882a593Smuzhiyun PHY3_IDDQ_OVERRIDE);
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun
usb_get_dual_select(struct brcm_usb_init_params * params)965*4882a593Smuzhiyun static int usb_get_dual_select(struct brcm_usb_init_params *params)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
968*4882a593Smuzhiyun u32 reg = 0;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun pr_debug("%s\n", __func__);
971*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
972*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
973*4882a593Smuzhiyun reg &= USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
974*4882a593Smuzhiyun PORT_MODE);
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun return reg;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
usb_set_dual_select(struct brcm_usb_init_params * params,int mode)979*4882a593Smuzhiyun static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
982*4882a593Smuzhiyun u32 reg;
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun pr_debug("%s\n", __func__);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
987*4882a593Smuzhiyun reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
988*4882a593Smuzhiyun reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
989*4882a593Smuzhiyun PORT_MODE);
990*4882a593Smuzhiyun reg |= mode;
991*4882a593Smuzhiyun brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun static const struct brcm_usb_init_ops bcm7445_ops = {
996*4882a593Smuzhiyun .init_ipp = usb_init_ipp,
997*4882a593Smuzhiyun .init_common = usb_init_common,
998*4882a593Smuzhiyun .init_eohci = usb_init_eohci,
999*4882a593Smuzhiyun .init_xhci = usb_init_xhci,
1000*4882a593Smuzhiyun .uninit_common = usb_uninit_common,
1001*4882a593Smuzhiyun .uninit_eohci = usb_uninit_eohci,
1002*4882a593Smuzhiyun .uninit_xhci = usb_uninit_xhci,
1003*4882a593Smuzhiyun .get_dual_select = usb_get_dual_select,
1004*4882a593Smuzhiyun .set_dual_select = usb_set_dual_select,
1005*4882a593Smuzhiyun };
1006*4882a593Smuzhiyun
brcm_usb_dvr_init_7445(struct brcm_usb_init_params * params)1007*4882a593Smuzhiyun void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun int fam;
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun pr_debug("%s\n", __func__);
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun fam = get_family_type(params);
1014*4882a593Smuzhiyun params->selected_family = fam;
1015*4882a593Smuzhiyun params->usb_reg_bits_map =
1016*4882a593Smuzhiyun &usb_reg_bits_map_table[fam][0];
1017*4882a593Smuzhiyun params->family_name = family_names[fam];
1018*4882a593Smuzhiyun params->ops = &bcm7445_ops;
1019*4882a593Smuzhiyun }
1020