blob: 8d076c2fa25c9a49db17c763a1971228890ea283 [file] [log] [blame]
Duncan Laurief81a91a2013-11-01 13:32:53 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080020#include <arch/acpi.h>
Duncan Laurief81a91a2013-11-01 13:32:53 -070021#include <console/console.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pci_ids.h>
25#include <stdint.h>
26#include <reg_script.h>
27
28#include <baytrail/iomap.h>
29#include <baytrail/iosf.h>
30#include <baytrail/pci_devs.h>
31#include <baytrail/pmc.h>
32#include <baytrail/ramstage.h>
33#include <baytrail/xhci.h>
34
35#include "chip.h"
36
37struct reg_script usb3_phy_script[] = {
38 /* USB3PHYInit() */
39 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_PLL_CONTROL,
40 ~0x00700000, 0x00500000),
41 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_VCO_START_CAL_POINT,
42 ~0x001f0000, 0x000A0000),
43 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CCDRLF,
44 ~0x0000000f, 0x0000000b),
45 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_PEAKING_AMP_CONFIG_DIAG,
46 ~0x000000f0, 0x000000f0),
47 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_OFFSET_COR_CONFIG_DIAG,
48 ~0x000001c0, 0x00000000),
49 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_VGA_GAIN_CONFIG_DIAG,
50 ~0x00000070, 0x00000020),
51 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_REE_DAC_CONTROL,
52 ~0x00000002, 0x00000002),
53 REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_U1_POWER_STATE_DEF,
54 ~0x00000000, 0x00040000),
55 REG_SCRIPT_END
56};
57
58const struct reg_script xhci_init_script[] = {
59 /* CommonXhciHcInit() */
60 /* BAR + 0x0c[31:16] = 0x0200 */
61 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0x0000ffff, 0x02000000),
62 /* BAR + 0x0c[7:0] = 0x0a */
63 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0xffffff00, 0x0000000a),
64 /* BAR + 0x8094[23,21,14]=111b */
65 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8094, 0x00a04000),
66 /* BAR + 0x8110[20,11,8,2]=1100b */
67 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8110, ~0x00000104, 0x00100800),
68 /* BAR + 0x8144[8,7,6]=111b */
69 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8144, 0x000001c0),
70 /* BAR + 0x8154[21,13,3]=010b */
71 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8154, ~0x00200008, 0x80002000),
72 /* BAR + 0x816c[19:0]=1110x100000000111100b */
73 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x816c, 0xfff08000, 0x000e0030),
74 /* BAR + 0x8188[26,24]=11b */
75 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8188, 0x05000000),
76 /* BAR + 0x8174=0x1000c0a*/
77 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8174, 0xfe000000, 0x01000c0a),
78 /* BAR + 0x854c[29]=0b */
79 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x854c, ~0x20000000, 0),
80 /* BAR + 0x8178[12:0]=0b */
81 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8178, ~0xffffe000, 0),
82 /* BAR + 0x8164[7:0]=0xff */
83 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8164, 0x000000ff),
84 /* BAR + 0x0010[10,9,5]=110b */
85 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0010, ~0x00000020, 0x00000600),
86 /* BAR + 0x8058[20,16,8]=110b */
Duncan Lauriea90a59f52013-11-04 11:22:27 -080087 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8058, ~0x00000100, 0x00110000),
Duncan Laurief81a91a2013-11-01 13:32:53 -070088 /* BAR + 0x8060[25]=1b */
89 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8060, 0x02000000),
Duncan Laurief81a91a2013-11-01 13:32:53 -070090 /* BAR + 0x80f0[20]=0b */
91 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80f0, ~0x00100000, 0),
92 /* BAR + 0x8008[19]=1b (to enable LPM) */
93 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8008, 0x00080000),
94 /* BAR + 0x80fc[25]=1b */
95 REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x80fc, 0x02000000),
96 /* 0x40/0x44 are written as bytes to avoid touching bit31 */
97 /* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */
98 REG_PCI_RMW8(0x41, ~0x06, 0x01),
99 /* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */
100 REG_PCI_RMW8(0x42, 0x3c, 0x04),
101 /* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */
102 REG_PCI_RMW8(0x44, 0x00, 0x8f),
103 REG_PCI_RMW8(0x45, ~0xcf, 0xc6),
104 REG_PCI_RMW8(0x46, ~0x0f, 0x0f),
105 /* BAR + 0x8140 = 0xff00f03c */
106 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8140, 0, 0xff00f03c),
107 REG_SCRIPT_END
108};
109
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800110const struct reg_script xhci_init_boot_script[] = {
111 /* Setup USB3 phy */
112 REG_SCRIPT_NEXT(usb3_phy_script),
113 /* Initialize host controller */
114 REG_SCRIPT_NEXT(xhci_init_script),
115 /* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */
116 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x00010200, 0x01000040),
117 /* BAR + 0x80e0 toggle bit 24=0 */
118 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01000000, 0),
119 REG_SCRIPT_END
120};
121
122const struct reg_script xhci_init_resume_script[] = {
123 /* Setup USB3 phy */
124 REG_SCRIPT_NEXT(usb3_phy_script),
125 /* Initialize host controller */
126 REG_SCRIPT_NEXT(xhci_init_script),
127 /* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */
128 REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01010200, 0x00000040),
129 REG_SCRIPT_END
130};
131
Duncan Laurief81a91a2013-11-01 13:32:53 -0700132const struct reg_script xhci_clock_gating_script[] = {
133 /* ConfigureXhciClockGating() */
134 /* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */
Duncan Lauriea90a59f52013-11-04 11:22:27 -0800135 REG_PCI_RMW16(0x40, ~0x0600, 0x0100),
Duncan Laurief81a91a2013-11-01 13:32:53 -0700136 REG_PCI_RMW8(0x42, ~0x38, 0x04),
137 /* D20:F0:44[5:3]=001b */
138 REG_PCI_RMW16(0x44, ~0x0030, 0x0008),
139 /* D20:F0:A0[19:18]=01b */
140 REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000),
141 /* D20:F0:A4[15:0]=0x00 */
142 REG_PCI_WRITE16(0xa4, 0x0000),
143 /* D20:F0:B0[21:17,14:13]=0000000b */
144 REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000),
145 /* D20:F0:50[31:0]=0x0bce6e5f */
146 REG_PCI_WRITE32(0x50, 0x0bce6e5f),
147 REG_SCRIPT_END
148};
149
150/* Warm Reset a USB3 port */
151static void xhci_reset_port_usb3(device_t dev, int port)
152{
153 struct reg_script reset_port_usb3_script[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700154 /* Issue Warm Port Rest to the port */
155 REG_RES_OR32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
156 XHCI_USB3_PORTSC_WPR),
157 /* Wait up to 100ms for it to complete */
158 REG_RES_POLL32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
159 XHCI_USB3_PORTSC_WRC, XHCI_USB3_PORTSC_WRC,
160 XHCI_RESET_TIMEOUT),
161 /* Clear change status bits, do not set PED */
162 REG_RES_RMW32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
163 ~XHCI_USB3_PORTSC_PED, XHCI_USB3_PORTSC_CHST),
164 REG_SCRIPT_END
165 };
Aaron Durbin616f3942013-12-10 17:12:44 -0800166 reg_script_run_on_dev(dev, reset_port_usb3_script);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700167}
168
169/* Prepare ports to be routed to EHCI or XHCI */
170static void xhci_route_all(device_t dev)
171{
Aaron Durbin616f3942013-12-10 17:12:44 -0800172 static const struct reg_script xhci_route_all_script[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700173 /* USB3 SuperSpeed Enable */
174 REG_PCI_WRITE32(XHCI_USB3PR, BYTM_USB3_PORT_MAP),
175 /* USB2 Port Route to XHCI */
176 REG_PCI_WRITE32(XHCI_USB2PR, BYTM_USB2_PORT_MAP),
177 REG_SCRIPT_END
178 };
179 u32 port_disabled;
180 int port;
181
182 printk(BIOS_INFO, "USB: Route ports to XHCI controller\n");
183
184 /* Route ports to XHCI controller */
Aaron Durbin616f3942013-12-10 17:12:44 -0800185 reg_script_run_on_dev(dev, xhci_route_all_script);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700186
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800187 if (acpi_slp_type == 3)
188 return;
189
Duncan Laurief81a91a2013-11-01 13:32:53 -0700190 /* Reset enabled USB3 ports */
191 port_disabled = pci_read_config32(dev, XHCI_USB3PDO);
192 for (port = 0; port < BYTM_USB3_PORT_COUNT; port++) {
193 if (port_disabled & (1 << port))
194 continue;
195 xhci_reset_port_usb3(dev, port);
196 }
197}
198
199static void xhci_init(device_t dev)
200{
201 struct soc_intel_baytrail_config *config = dev->chip_info;
202 struct reg_script xhci_hc_init[] = {
Duncan Laurief81a91a2013-11-01 13:32:53 -0700203 /* Initialize clock gating */
204 REG_SCRIPT_NEXT(xhci_clock_gating_script),
Duncan Lauriea90a59f52013-11-04 11:22:27 -0800205 /* Finalize XHCC1 and XHCC2 */
206 REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000),
207 REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000),
Duncan Laurief81a91a2013-11-01 13:32:53 -0700208 /* Set USB2 Port Routing Mask */
209 REG_PCI_WRITE32(XHCI_USB2PRM, BYTM_USB2_PORT_MAP),
210 /* Set USB3 Port Routing Mask */
211 REG_PCI_WRITE32(XHCI_USB3PRM, BYTM_USB3_PORT_MAP),
212 /*
213 * Disable ports if requested
214 */
215 /* Open per-port disable control override */
216 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
217 REG_PCI_WRITE32(XHCI_USB2PDO, config->usb2_port_disable_mask),
218 REG_PCI_WRITE32(XHCI_USB3PDO, config->usb3_port_disable_mask),
219 /* Close per-port disable control override */
220 REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
221 REG_SCRIPT_END
222 };
223
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800224 /* Initialize XHCI controller for boot or resume path */
225 if (acpi_slp_type == 3)
226 reg_script_run_on_dev(dev, xhci_init_resume_script);
227 else
228 reg_script_run_on_dev(dev, xhci_init_boot_script);
229
230 /* Finalize Initialization */
Aaron Durbin616f3942013-12-10 17:12:44 -0800231 reg_script_run_on_dev(dev, xhci_hc_init);
Duncan Laurief81a91a2013-11-01 13:32:53 -0700232
233 /* Route all ports to XHCI if requested */
234 if (config->usb_route_to_xhci)
235 xhci_route_all(dev);
236}
237
238static struct device_operations xhci_device_ops = {
239 .read_resources = pci_dev_read_resources,
240 .set_resources = pci_dev_set_resources,
241 .enable_resources = pci_dev_enable_resources,
242 .init = xhci_init,
243 .ops_pci = &soc_pci_ops,
244};
245
246static const struct pci_driver baytrail_xhci __pci_driver = {
247 .ops = &xhci_device_ops,
248 .vendor = PCI_VENDOR_ID_INTEL,
249 .device = XHCI_DEVID
250};