blob: 473be2fcc3e955c37a6d7c82c42d6a89fa366a71 [file] [log] [blame]
Angel Ponsc3f58f62020-04-05 15:46:41 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Duncan Laurief81a91a2013-11-01 13:32:53 -07003
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -08004#include <arch/acpi.h>
Duncan Laurief81a91a2013-11-01 13:32:53 -07005#include <console/console.h>
6#include <device/device.h>
7#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02008#include <device/pci_ops.h>
Duncan Laurief81a91a2013-11-01 13:32:53 -07009#include <device/pci_ids.h>
10#include <stdint.h>
11#include <reg_script.h>
12
Julius Werner18ea2d32014-10-07 16:42:17 -070013#include <soc/iomap.h>
14#include <soc/iosf.h>
15#include <soc/lpc.h>
16#include <soc/pattrs.h>
17#include <soc/pci_devs.h>
18#include <soc/pmc.h>
19#include <soc/ramstage.h>
20#include <soc/xhci.h>
Duncan Laurief81a91a2013-11-01 13:32:53 -070021
22#include "chip.h"
23
24struct reg_script usb3_phy_script[] = {
25 /* USB3PHYInit() */
26 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_PLL_CONTROL,
27 ~0x00700000, 0x00500000),
28 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_VCO_START_CAL_POINT,
29 ~0x001f0000, 0x000A0000),
30 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CCDRLF,
31 ~0x0000000f, 0x0000000b),
32 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_PEAKING_AMP_CONFIG_DIAG,
33 ~0x000000f0, 0x000000f0),
34 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_OFFSET_COR_CONFIG_DIAG,
35 ~0x000001c0, 0x00000000),
36 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_VGA_GAIN_CONFIG_DIAG,
37 ~0x00000070, 0x00000020),
38 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_REE_DAC_CONTROL,
39 ~0x00000002, 0x00000002),
40 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_U1_POWER_STATE_DEF,
41 ~0x00000000, 0x00040000),
42 REG_SCRIPT_END
43};
44
45const struct reg_script xhci_init_script[] = {
46 /* CommonXhciHcInit() */
47 /* BAR + 0x0c[31:16] = 0x0200 */
48 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0x0000ffff, 0x02000000),
49 /* BAR + 0x0c[7:0] = 0x0a */
50 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0xffffff00, 0x0000000a),
51 /* BAR + 0x8094[23,21,14]=111b */
52 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8094, 0x00a04000),
53 /* BAR + 0x8110[20,11,8,2]=1100b */
54 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8110, ~0x00000104, 0x00100800),
55 /* BAR + 0x8144[8,7,6]=111b */
56 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8144, 0x000001c0),
57 /* BAR + 0x8154[21,13,3]=010b */
58 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8154, ~0x00200008, 0x80002000),
59 /* BAR + 0x816c[19:0]=1110x100000000111100b */
60 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x816c, 0xfff08000, 0x000e0030),
61 /* BAR + 0x8188[26,24]=11b */
62 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8188, 0x05000000),
63 /* BAR + 0x8174=0x1000c0a*/
64 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8174, 0xfe000000, 0x01000c0a),
65 /* BAR + 0x854c[29]=0b */
66 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x854c, ~0x20000000, 0),
67 /* BAR + 0x8178[12:0]=0b */
68 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8178, ~0xffffe000, 0),
69 /* BAR + 0x8164[7:0]=0xff */
70 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8164, 0x000000ff),
71 /* BAR + 0x0010[10,9,5]=110b */
72 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0010, ~0x00000020, 0x00000600),
73 /* BAR + 0x8058[20,16,8]=110b */
Duncan Lauriea90a59f52013-11-04 11:22:27 -080074 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8058, ~0x00000100, 0x00110000),
Duncan Laurief81a91a2013-11-01 13:32:53 -070075 /* BAR + 0x8060[25]=1b */
76 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8060, 0x02000000),
Duncan Laurief81a91a2013-11-01 13:32:53 -070077 /* BAR + 0x80f0[20]=0b */
78 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80f0, ~0x00100000, 0),
79 /* BAR + 0x8008[19]=1b (to enable LPM) */
80 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8008, 0x00080000),
81 /* BAR + 0x80fc[25]=1b */
82 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x80fc, 0x02000000),
83 /* 0x40/0x44 are written as bytes to avoid touching bit31 */
84 /* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */
85 REG_PCI_RMW8(0x41, ~0x06, 0x01),
86 /* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */
87 REG_PCI_RMW8(0x42, 0x3c, 0x04),
88 /* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */
89 REG_PCI_RMW8(0x44, 0x00, 0x8f),
90 REG_PCI_RMW8(0x45, ~0xcf, 0xc6),
91 REG_PCI_RMW8(0x46, ~0x0f, 0x0f),
92 /* BAR + 0x8140 = 0xff00f03c */
93 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8140, 0, 0xff00f03c),
94 REG_SCRIPT_END
95};
96
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080097const struct reg_script xhci_init_boot_script[] = {
98 /* Setup USB3 phy */
99 REG_SCRIPT_NEXT(usb3_phy_script),
100 /* Initialize host controller */
101 REG_SCRIPT_NEXT(xhci_init_script),
102 /* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */
103 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x00010200, 0x01000040),
104 /* BAR + 0x80e0 toggle bit 24=0 */
105 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01000000, 0),
106 REG_SCRIPT_END
107};
108
109const struct reg_script xhci_init_resume_script[] = {
110 /* Setup USB3 phy */
111 REG_SCRIPT_NEXT(usb3_phy_script),
112 /* Initialize host controller */
113 REG_SCRIPT_NEXT(xhci_init_script),
114 /* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */
115 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01010200, 0x00000040),
116 REG_SCRIPT_END
117};
118
Duncan Laurief81a91a2013-11-01 13:32:53 -0700119const struct reg_script xhci_clock_gating_script[] = {
120 /* ConfigureXhciClockGating() */
121 /* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */
Duncan Lauriea90a59f52013-11-04 11:22:27 -0800122 REG_PCI_RMW16(0x40, ~0x0600, 0x0100),
Duncan Laurief81a91a2013-11-01 13:32:53 -0700123 REG_PCI_RMW8(0x42, ~0x38, 0x04),
124 /* D20:F0:44[5:3]=001b */
125 REG_PCI_RMW16(0x44, ~0x0030, 0x0008),
126 /* D20:F0:A0[19:18]=01b */
127 REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000),
128 /* D20:F0:A4[15:0]=0x00 */
129 REG_PCI_WRITE16(0xa4, 0x0000),
130 /* D20:F0:B0[21:17,14:13]=0000000b */
131 REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000),
132 /* D20:F0:50[31:0]=0x0bce6e5f */
133 REG_PCI_WRITE32(0x50, 0x0bce6e5f),
134 REG_SCRIPT_END
135};
136
137/* Warm Reset a USB3 port */
Elyes HAOUAS17a3ceb2018-05-22 10:42:28 +0200138static void xhci_reset_port_usb3(struct device *dev, int port)
Duncan Laurief81a91a2013-11-01 13:32:53 -0700139{
140 struct reg_script reset_port_usb3_script[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700141 /* Issue Warm Port Rest to the port */
142 REG_RES_OR32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
143 XHCI_USB3_PORTSC_WPR),
144 /* Wait up to 100ms for it to complete */
145 REG_RES_POLL32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
146 XHCI_USB3_PORTSC_WRC, XHCI_USB3_PORTSC_WRC,
147 XHCI_RESET_TIMEOUT),
148 /* Clear change status bits, do not set PED */
149 REG_RES_RMW32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
150 ~XHCI_USB3_PORTSC_PED, XHCI_USB3_PORTSC_CHST),
151 REG_SCRIPT_END
152 };
Aaron Durbin616f3942013-12-10 17:12:44 -0800153 reg_script_run_on_dev(dev, reset_port_usb3_script);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700154}
155
156/* Prepare ports to be routed to EHCI or XHCI */
Elyes HAOUAS17a3ceb2018-05-22 10:42:28 +0200157static void xhci_route_all(struct device *dev)
Duncan Laurief81a91a2013-11-01 13:32:53 -0700158{
Aaron Durbin616f3942013-12-10 17:12:44 -0800159 static const struct reg_script xhci_route_all_script[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700160 /* USB3 SuperSpeed Enable */
161 REG_PCI_WRITE32(XHCI_USB3PR, BYTM_USB3_PORT_MAP),
162 /* USB2 Port Route to XHCI */
163 REG_PCI_WRITE32(XHCI_USB2PR, BYTM_USB2_PORT_MAP),
164 REG_SCRIPT_END
165 };
166 u32 port_disabled;
167 int port;
168
169 printk(BIOS_INFO, "USB: Route ports to XHCI controller\n");
170
171 /* Route ports to XHCI controller */
Aaron Durbin616f3942013-12-10 17:12:44 -0800172 reg_script_run_on_dev(dev, xhci_route_all_script);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700173
Kyösti Mälkki9e94dbf2015-01-08 20:03:18 +0200174 if (acpi_is_wakeup_s3())
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800175 return;
176
Duncan Laurief81a91a2013-11-01 13:32:53 -0700177 /* Reset enabled USB3 ports */
178 port_disabled = pci_read_config32(dev, XHCI_USB3PDO);
179 for (port = 0; port < BYTM_USB3_PORT_COUNT; port++) {
180 if (port_disabled & (1 << port))
181 continue;
182 xhci_reset_port_usb3(dev, port);
183 }
184}
185
Elyes HAOUAS17a3ceb2018-05-22 10:42:28 +0200186static void xhci_init(struct device *dev)
Duncan Laurief81a91a2013-11-01 13:32:53 -0700187{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300188 struct soc_intel_baytrail_config *config = config_of(dev);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700189 struct reg_script xhci_hc_init[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700190 /* Initialize clock gating */
191 REG_SCRIPT_NEXT(xhci_clock_gating_script),
Duncan Lauriea90a59f52013-11-04 11:22:27 -0800192 /* Finalize XHCC1 and XHCC2 */
193 REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000),
194 REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000),
Duncan Laurief81a91a2013-11-01 13:32:53 -0700195 /* Set USB2 Port Routing Mask */
196 REG_PCI_WRITE32(XHCI_USB2PRM, BYTM_USB2_PORT_MAP),
197 /* Set USB3 Port Routing Mask */
198 REG_PCI_WRITE32(XHCI_USB3PRM, BYTM_USB3_PORT_MAP),
199 /*
200 * Disable ports if requested
201 */
202 /* Open per-port disable control override */
203 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
204 REG_PCI_WRITE32(XHCI_USB2PDO, config->usb2_port_disable_mask),
205 REG_PCI_WRITE32(XHCI_USB3PDO, config->usb3_port_disable_mask),
206 /* Close per-port disable control override */
207 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
208 REG_SCRIPT_END
209 };
210
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800211 /* Initialize XHCI controller for boot or resume path */
Kyösti Mälkki9e94dbf2015-01-08 20:03:18 +0200212 if (acpi_is_wakeup_s3())
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800213 reg_script_run_on_dev(dev, xhci_init_resume_script);
214 else
215 reg_script_run_on_dev(dev, xhci_init_boot_script);
216
Kein Yuanc9bf4462014-06-27 09:12:57 -0700217 /* C0 steppings change iCLK/USB PLL VCO settings from 5 to 7 */
218 if (pattrs_get()->stepping == STEP_C0) {
219 uint32_t reg = iosf_ushphy_read(USHPHY_CDN_PLL_CONTROL);
220 reg |= 0x00700000;
221 iosf_ushphy_write(USHPHY_CDN_PLL_CONTROL, reg);
222 }
223
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800224 /* Finalize Initialization */
Aaron Durbin616f3942013-12-10 17:12:44 -0800225 reg_script_run_on_dev(dev, xhci_hc_init);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700226
227 /* Route all ports to XHCI if requested */
228 if (config->usb_route_to_xhci)
229 xhci_route_all(dev);
230}
231
232static struct device_operations xhci_device_ops = {
233 .read_resources = pci_dev_read_resources,
234 .set_resources = pci_dev_set_resources,
235 .enable_resources = pci_dev_enable_resources,
236 .init = xhci_init,
237 .ops_pci = &soc_pci_ops,
238};
239
240static const struct pci_driver baytrail_xhci __pci_driver = {
241 .ops = &xhci_device_ops,
242 .vendor = PCI_VENDOR_ID_INTEL,
243 .device = XHCI_DEVID
244};