1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ops.h>
8 #include <device/pci_ids.h>
10 #include <reg_script.h>
12 #include <soc/iomap.h>
15 #include <soc/pattrs.h>
16 #include <soc/pci_devs.h>
18 #include <soc/ramstage.h>
23 struct reg_script usb3_phy_script
[] = {
25 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_CDN_PLL_CONTROL
,
26 ~0x00700000, 0x00500000),
27 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_CDN_VCO_START_CAL_POINT
,
28 ~0x001f0000, 0x000A0000),
29 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_CCDRLF
,
30 ~0x0000000f, 0x0000000b),
31 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_PEAKING_AMP_CONFIG_DIAG
,
32 ~0x000000f0, 0x000000f0),
33 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_OFFSET_COR_CONFIG_DIAG
,
34 ~0x000001c0, 0x00000000),
35 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_VGA_GAIN_CONFIG_DIAG
,
36 ~0x00000070, 0x00000020),
37 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_REE_DAC_CONTROL
,
38 ~0x00000002, 0x00000002),
39 REG_IOSF_RMW(IOSF_PORT_USHPHY
, USHPHY_CDN_U1_POWER_STATE_DEF
,
40 ~0x00000000, 0x00040000),
44 const struct reg_script xhci_init_script
[] = {
45 /* CommonXhciHcInit() */
46 /* BAR + 0x0c[31:16] = 0x0200 */
47 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x000c, 0x0000ffff, 0x02000000),
48 /* BAR + 0x0c[7:0] = 0x0a */
49 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x000c, 0xffffff00, 0x0000000a),
50 /* BAR + 0x8094[23,21,14]=111b */
51 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8094, 0x00a04000),
52 /* BAR + 0x8110[20,11,8,2]=1100b */
53 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8110, ~0x00000104, 0x00100800),
54 /* BAR + 0x8144[8,7,6]=111b */
55 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8144, 0x000001c0),
56 /* BAR + 0x8154[21,13,3]=010b */
57 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8154, ~0x00200008, 0x80002000),
58 /* BAR + 0x816c[19:0]=1110x100000000111100b */
59 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x816c, 0xfff08000, 0x000e0030),
60 /* BAR + 0x8188[26,24]=11b */
61 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8188, 0x05000000),
62 /* BAR + 0x8174=0x1000c0a*/
63 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8174, 0xfe000000, 0x01000c0a),
64 /* BAR + 0x854c[29]=0b */
65 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x854c, ~0x20000000, 0),
66 /* BAR + 0x8178[12:0]=0b */
67 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8178, ~0xffffe000, 0),
68 /* BAR + 0x8164[7:0]=0xff */
69 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8164, 0x000000ff),
70 /* BAR + 0x0010[10,9,5]=110b */
71 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x0010, ~0x00000020, 0x00000600),
72 /* BAR + 0x8058[20,16,8]=110b */
73 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8058, ~0x00000100, 0x00110000),
74 /* BAR + 0x8060[25]=1b */
75 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8060, 0x02000000),
76 /* BAR + 0x80f0[20]=0b */
77 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x80f0, ~0x00100000, 0),
78 /* BAR + 0x8008[19]=1b (to enable LPM) */
79 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x8008, 0x00080000),
80 /* BAR + 0x80fc[25]=1b */
81 REG_RES_OR32(PCI_BASE_ADDRESS_0
, 0x80fc, 0x02000000),
82 /* 0x40/0x44 are written as bytes to avoid touching bit31 */
83 /* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */
84 REG_PCI_RMW8(0x41, ~0x06, 0x01),
85 /* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */
86 REG_PCI_RMW8(0x42, 0x3c, 0x04),
87 /* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */
88 REG_PCI_RMW8(0x44, 0x00, 0x8f),
89 REG_PCI_RMW8(0x45, ~0xcf, 0xc6),
90 REG_PCI_RMW8(0x46, ~0x0f, 0x0f),
91 /* BAR + 0x8140 = 0xff00f03c */
92 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x8140, 0, 0xff00f03c),
96 const struct reg_script xhci_init_boot_script
[] = {
98 REG_SCRIPT_NEXT(usb3_phy_script
),
99 /* Initialize host controller */
100 REG_SCRIPT_NEXT(xhci_init_script
),
101 /* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */
102 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x80e0, ~0x00010200, 0x01000040),
103 /* BAR + 0x80e0 toggle bit 24=0 */
104 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x80e0, ~0x01000000, 0),
108 const struct reg_script xhci_init_resume_script
[] = {
110 REG_SCRIPT_NEXT(usb3_phy_script
),
111 /* Initialize host controller */
112 REG_SCRIPT_NEXT(xhci_init_script
),
113 /* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */
114 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, 0x80e0, ~0x01010200, 0x00000040),
118 const struct reg_script xhci_clock_gating_script
[] = {
119 /* ConfigureXhciClockGating() */
120 /* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */
121 REG_PCI_RMW16(0x40, ~0x0600, 0x0100),
122 REG_PCI_RMW8(0x42, ~0x38, 0x04),
123 /* D20:F0:44[5:3]=001b */
124 REG_PCI_RMW16(0x44, ~0x0030, 0x0008),
125 /* D20:F0:A0[19:18]=01b */
126 REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000),
127 /* D20:F0:A4[15:0]=0x00 */
128 REG_PCI_WRITE16(0xa4, 0x0000),
129 /* D20:F0:B0[21:17,14:13]=0000000b */
130 REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000),
131 /* D20:F0:50[31:0]=0x0bce6e5f */
132 REG_PCI_WRITE32(0x50, 0x0bce6e5f),
136 /* Warm Reset a USB3 port */
137 static void xhci_reset_port_usb3(struct device
*dev
, int port
)
139 struct reg_script reset_port_usb3_script
[] = {
140 /* Issue Warm Port Rest to the port */
141 REG_RES_OR32(PCI_BASE_ADDRESS_0
, XHCI_USB3_PORTSC(port
),
142 XHCI_USB3_PORTSC_WPR
),
143 /* Wait up to 100ms for it to complete */
144 REG_RES_POLL32(PCI_BASE_ADDRESS_0
, XHCI_USB3_PORTSC(port
),
145 XHCI_USB3_PORTSC_WRC
, XHCI_USB3_PORTSC_WRC
,
147 /* Clear change status bits, do not set PED */
148 REG_RES_RMW32(PCI_BASE_ADDRESS_0
, XHCI_USB3_PORTSC(port
),
149 ~XHCI_USB3_PORTSC_PED
, XHCI_USB3_PORTSC_CHST
),
152 reg_script_run_on_dev(dev
, reset_port_usb3_script
);
155 /* Prepare ports to be routed to EHCI or XHCI */
156 static void xhci_route_all(struct device
*dev
)
158 static const struct reg_script xhci_route_all_script
[] = {
159 /* USB3 SuperSpeed Enable */
160 REG_PCI_WRITE32(XHCI_USB3PR
, BYTM_USB3_PORT_MAP
),
161 /* USB2 Port Route to XHCI */
162 REG_PCI_WRITE32(XHCI_USB2PR
, BYTM_USB2_PORT_MAP
),
168 printk(BIOS_INFO
, "USB: Route ports to XHCI controller\n");
170 /* Route ports to XHCI controller */
171 reg_script_run_on_dev(dev
, xhci_route_all_script
);
173 if (acpi_is_wakeup_s3())
176 /* Reset enabled USB3 ports */
177 port_disabled
= pci_read_config32(dev
, XHCI_USB3PDO
);
178 for (port
= 0; port
< BYTM_USB3_PORT_COUNT
; port
++) {
179 if (port_disabled
& (1 << port
))
181 xhci_reset_port_usb3(dev
, port
);
185 static void xhci_init(struct device
*dev
)
187 struct soc_intel_baytrail_config
*config
= config_of(dev
);
188 struct reg_script xhci_hc_init
[] = {
189 /* Initialize clock gating */
190 REG_SCRIPT_NEXT(xhci_clock_gating_script
),
191 /* Finalize XHCC1 and XHCC2 */
192 REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000),
193 REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000),
194 /* Set USB2 Port Routing Mask */
195 REG_PCI_WRITE32(XHCI_USB2PRM
, BYTM_USB2_PORT_MAP
),
196 /* Set USB3 Port Routing Mask */
197 REG_PCI_WRITE32(XHCI_USB3PRM
, BYTM_USB3_PORT_MAP
),
199 * Disable ports if requested
201 /* Open per-port disable control override */
202 REG_IO_RMW16(ACPI_BASE_ADDRESS
+ UPRWC
, ~0, UPRWC_WR_EN
),
203 REG_PCI_WRITE32(XHCI_USB2PDO
, config
->usb2_port_disable_mask
),
204 REG_PCI_WRITE32(XHCI_USB3PDO
, config
->usb3_port_disable_mask
),
205 /* Close per-port disable control override */
206 REG_IO_RMW16(ACPI_BASE_ADDRESS
+ UPRWC
, ~UPRWC_WR_EN
, 0),
210 /* Initialize XHCI controller for boot or resume path */
211 if (acpi_is_wakeup_s3())
212 reg_script_run_on_dev(dev
, xhci_init_resume_script
);
214 reg_script_run_on_dev(dev
, xhci_init_boot_script
);
216 /* C0 steppings change iCLK/USB PLL VCO settings from 5 to 7 */
217 if (pattrs_get()->stepping
== STEP_C0
) {
218 uint32_t reg
= iosf_ushphy_read(USHPHY_CDN_PLL_CONTROL
);
220 iosf_ushphy_write(USHPHY_CDN_PLL_CONTROL
, reg
);
223 /* Finalize Initialization */
224 reg_script_run_on_dev(dev
, xhci_hc_init
);
226 /* Route all ports to XHCI if requested */
227 if (config
->usb_route_to_xhci
)
231 static struct device_operations xhci_device_ops
= {
232 .read_resources
= pci_dev_read_resources
,
233 .set_resources
= pci_dev_set_resources
,
234 .enable_resources
= pci_dev_enable_resources
,
236 .ops_pci
= &soc_pci_ops
,
239 static const struct pci_driver baytrail_xhci __pci_driver
= {
240 .ops
= &xhci_device_ops
,
241 .vendor
= PCI_VID_INTEL
,