1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <console/console.h>
10 /* USB BASE ADDRESS */
11 #define USB_HOST0_DWC3_BASE 0x758C100
12 #define USB3_USB30_QSCRATCH_BASE 0x7678800
13 #define USB2_FEMTO_PHY_PRI_BASE 0x007A000
14 #define USB_HOST1_DWC3_BASE 0x78CC100
15 #define USB2_USB30_QSCRATCH_BASE 0x79B8800
16 #define USB2_FEMTO_PHY_SEC_BASE 0x007C000
20 u32
*qscratch_cfg_reg
;
23 check_member(usb_qscratch
, qscratch_cfg_reg
, 0x08);
25 struct usb_usb2_phy_dig
{
43 check_member(usb_usb2_phy_dig
, utmi_ctrl5
, 0x74);
44 check_member(usb_usb2_phy_dig
, phy_ctrl1
, 0x8C);
45 check_member(usb_usb2_phy_dig
, override_x0
, 0x98);
46 check_member(usb_usb2_phy_dig
, tcsr_ctrl
, 0xC0);
47 check_member(usb_usb2_phy_dig
, refclk_ctrl
, 0xE8);
85 check_member(usb_dwc3
, usb3pipectl
, 0x1c0);
88 struct usb_dwc3
*usb_host_dwc3
;
89 struct usb_usb2_phy_dig
*usb2_phy_dig
;
90 struct usb_qscratch
*usb_qscratch_reg
;
92 u32
*usb2_phy_por_bcr
;
94 struct usb_board_data
*board_data
;
97 static struct usb_dwc3_cfg usb_host_base
[2] = {
99 .usb_host_dwc3
= (void *)USB_HOST0_DWC3_BASE
,
100 .usb2_phy_dig
= (void *)USB2_FEMTO_PHY_PRI_BASE
,
101 .usb2_phy_bcr
= (void *)GCC_USB_HS_PHY_CFG_AHB_BCR
,
102 .usb2_phy_por_bcr
= (void *)GCC_USB2A_PHY_BCR
,
103 .usb3_bcr
= (void *)GCC_USB_30_BCR
,
104 .usb_qscratch_reg
= (void *)USB3_USB30_QSCRATCH_BASE
,
106 [HSUSB_HS_PORT_1
] = {
107 .usb_host_dwc3
= (void *)USB_HOST1_DWC3_BASE
,
108 .usb2_phy_dig
= (void *)USB2_FEMTO_PHY_SEC_BASE
,
109 .usb2_phy_bcr
= (void *)GCC_QUSB2_PHY_BCR
,
110 .usb2_phy_por_bcr
= (void *)GCC_USB2_HS_PHY_ONLY_BCR
,
111 .usb3_bcr
= (void *)GCC_USB_HS_BCR
,
112 .usb_qscratch_reg
= (void *)USB2_USB30_QSCRATCH_BASE
,
116 void reset_usb(enum usb_port port
)
118 struct usb_dwc3_cfg
*dwc3
= &usb_host_base
[port
];
120 /* Put Core in Reset */
121 printk(BIOS_INFO
, "Starting DWC3 reset for USB%d\n", port
);
123 /* Assert Core reset */
124 clock_reset_bcr(dwc3
->usb3_bcr
, 1);
127 static void usb2_phy_override_phy_params(struct usb_dwc3_cfg
*dwc3
)
129 /* Override disconnect & squelch threshold values */
130 write8(&dwc3
->usb2_phy_dig
->override_x0
,
131 dwc3
->board_data
->parameter_override_x0
);
133 /* Override HS transmitter Pre-emphasis values */
134 write8(&dwc3
->usb2_phy_dig
->override_x1
,
135 dwc3
->board_data
->parameter_override_x1
);
137 /* Override HS transmitter Rise/Fall time values */
138 write8(&dwc3
->usb2_phy_dig
->override_x2
,
139 dwc3
->board_data
->parameter_override_x2
);
141 /* Override FS/LS Source impedance values */
142 write8(&dwc3
->usb2_phy_dig
->override_x3
,
143 dwc3
->board_data
->parameter_override_x3
);
146 static void hs_usb_phy_init(struct usb_dwc3_cfg
*dwc3
)
148 write8(&dwc3
->usb2_phy_dig
->tcsr_ctrl
, USB2PHY_TCSR_CTRL
);
149 write8(&dwc3
->usb2_phy_dig
->refclk_ctrl
, USB2PHY_REFCLK_CTRL
);
150 write8(&dwc3
->usb2_phy_dig
->utmi_ctrl5
, USB2PHY_UTMI_CTRL5
);
151 write8(&dwc3
->usb2_phy_dig
->override_x0
, USB2PHY_PARAMETER_OVERRIDE_X0
);
152 write8(&dwc3
->usb2_phy_dig
->override_x1
, USB2PHY_PARAMETER_OVERRIDE_X1
);
153 write8(&dwc3
->usb2_phy_dig
->override_x2
, USB2PHY_PARAMETER_OVERRIDE_X2
);
154 write8(&dwc3
->usb2_phy_dig
->override_x3
, USB2PHY_PARAMETER_OVERRIDE_X3
);
156 if (dwc3
->board_data
)
157 /* Override board specific PHY tuning values */
158 usb2_phy_override_phy_params(dwc3
);
160 write8(&dwc3
->usb2_phy_dig
->phy_ctrl1
, USB2PHY_HS_PHY_CTRL1
);
161 write8(&dwc3
->usb2_phy_dig
->ctrl_common0
, QUSB2PHY_HS_PHY_CTRL_COMMON0
);
162 write8(&dwc3
->usb2_phy_dig
->ctrl_common1
, QUSB2PHY_HS_PHY_CTRL_COMMON1
);
163 write8(&dwc3
->usb2_phy_dig
->phy_ctrl2
, USB2PHY_HS_PHY_CTRL2
);
165 write8(&dwc3
->usb2_phy_dig
->utmi_ctrl5
, USB2PHY_UTMI_CTRL5_POR_CLEAR
);
166 write8(&dwc3
->usb2_phy_dig
->phy_ctrl2
,
167 USB2PHY_HS_PHY_CTRL2_SUSPEND_N_SEL
);
170 static void setup_dwc3(struct usb_dwc3
*dwc3
)
172 /* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */
173 clrsetbits32(&dwc3
->usb3pipectl
,
174 DWC3_GUSB3PIPECTL_DELAYP1TRANS
,
175 DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX
);
177 clrsetbits32(&dwc3
->ctl
, (DWC3_GCTL_SCALEDOWN_MASK
|
178 DWC3_GCTL_DISSCRAMBLE
),
179 DWC3_GCTL_U2EXIT_LFPS
| DWC3_GCTL_DSBLCLKGTNG
);
181 /* configure controller in Host mode */
182 clrsetbits32(&dwc3
->ctl
, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG
)),
183 DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST
));
184 printk(BIOS_INFO
, "Configure USB in Host mode\n");
187 /* Initialization of DWC3 Core and PHY */
188 void setup_usb_host(enum usb_port port
, struct usb_board_data
*board_data
)
190 struct usb_dwc3_cfg
*dwc3
= &usb_host_base
[port
];
193 printk(BIOS_INFO
, "Setting up USB HOST%d controller.\n", port
);
195 dwc3
->board_data
= board_data
;
197 /* Clear core reset. */
198 clock_reset_bcr(dwc3
->usb3_bcr
, 0);
200 if (port
== HSUSB_SS_PORT_0
) {
202 setbits32(&dwc3
->usb2_phy_bcr
, BIT(1));
204 /* Clear PHY reset. */
205 clrbits32(&dwc3
->usb2_phy_bcr
, BIT(1));
207 clock_reset_bcr(dwc3
->usb2_phy_bcr
, 1);
209 clock_reset_bcr(dwc3
->usb2_phy_bcr
, 0);
213 /* Initialize PHYs */
214 hs_usb_phy_init(dwc3
);
216 if (port
== HSUSB_SS_PORT_0
) {
217 /* Set PHY POR reset. */
218 setbits32(&dwc3
->usb2_phy_por_bcr
, BIT(0));
219 val
= read8(&dwc3
->usb2_phy_dig
->ctrl_common0
);
221 write8(&dwc3
->usb2_phy_dig
->ctrl_common0
, val
);
223 /* Clear PHY POR reset. */
224 clrbits32(&dwc3
->usb2_phy_por_bcr
, BIT(0));
226 clock_reset_bcr(dwc3
->usb2_phy_por_bcr
, 1);
227 val
= read8(&dwc3
->usb2_phy_dig
->ctrl_common0
);
229 write8(&dwc3
->usb2_phy_dig
->ctrl_common0
, val
);
231 clock_reset_bcr(dwc3
->usb2_phy_por_bcr
, 0);
235 setup_dwc3(dwc3
->usb_host_dwc3
);
238 * Below sequence is used when dwc3 operates without
239 * SSPHY and only HS/FS/LS modes are supported.
242 /* Configure dwc3 to use UTMI clock as PIPE clock not present */
243 setbits32(&dwc3
->usb_qscratch_reg
->qscratch_cfg_reg
,
246 setbits32(&dwc3
->usb_qscratch_reg
->qscratch_cfg_reg
,
247 PIPE_UTMI_CLK_SEL
| PIPE3_PHYSTATUS_SW
);
249 clrbits32(&dwc3
->usb_qscratch_reg
->qscratch_cfg_reg
,
252 printk(BIOS_INFO
, "DWC3 and PHY setup finished\n");