blob: 03ed578e2735c3e40f4a093e9021963b28aff2e0 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Subrata Banika554b0c2017-02-16 16:08:49 +05302
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi_device.h>
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -06004#include <console/console.h>
Subrata Banika554b0c2017-02-16 16:08:49 +05305#include <device/device.h>
Elyes Haouasc4fbeac2022-12-04 16:06:02 +01006#include <device/mmio.h>
Subrata Banika554b0c2017-02-16 16:08:49 +05307#include <device/pci.h>
8#include <device/pci_ids.h>
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -06009#include <drivers/usb/acpi/chip.h>
Duncan Lauriebf713b02018-05-07 15:33:18 -070010#include <intelblocks/acpi.h>
Subrata Banika554b0c2017-02-16 16:08:49 +053011#include <intelblocks/xhci.h>
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060012#include <soc/pci_devs.h>
13
14#define XHCI_USB2 2
15#define XHCI_USB3 3
16
Subrata Banike3a4a132022-04-11 17:45:33 +053017#define XHCI_USBCMD 0x80
18#define USBCMD_HCRST (1 << 1)
19
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060020/* Current Connect Status */
21#define XHCI_STATUS_CCS (1 << 0)
22
Subrata Banike3a4a132022-04-11 17:45:33 +053023static uint8_t *xhci_mem_base(void)
24{
25 uint32_t mem_base = pci_read_config32(PCH_DEV_XHCI, PCI_BASE_ADDRESS_0);
26
27 /* Check if the controller is disabled or not present */
28 if (mem_base == 0 || mem_base == 0xffffffff)
29 return 0;
30
Arthur Heymans58955be2022-11-04 20:36:01 +010031 return (uint8_t *)(uintptr_t)(mem_base & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
Subrata Banike3a4a132022-04-11 17:45:33 +053032}
33
34void xhci_host_reset(void)
35{
36 uint8_t *xhci_base = xhci_mem_base();
37 if (!xhci_base)
38 return;
39
40 setbits8(xhci_base + XHCI_USBCMD, USBCMD_HCRST);
41}
42
43#if ENV_RAMSTAGE
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060044static bool is_usb_port_connected(const struct xhci_usb_info *info,
45 unsigned int port_type, unsigned int port_id)
46{
47 uintptr_t port_sts_reg;
48 uint32_t port_status;
49 const struct resource *res;
50
51 /* Support only USB2 or USB3 ports */
52 if (!(port_type == XHCI_USB2 || port_type == XHCI_USB3))
53 return false;
54
55 /* Mark out of bound port id as not connected */
56 if ((port_type == XHCI_USB2 && port_id >= info->num_usb2_ports) ||
57 (port_type == XHCI_USB3 && port_id >= info->num_usb3_ports))
58 return false;
59
60 /* Calculate port status register address and read the status */
Angel Ponsc1bfbe02021-11-03 13:18:53 +010061 res = probe_resource(PCH_DEV_XHCI, PCI_BASE_ADDRESS_0);
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060062 /* If the memory BAR is not allocated for XHCI, leave the devices enabled */
63 if (!res)
64 return true;
65
66 if (port_type == XHCI_USB2)
67 port_sts_reg = (uintptr_t)res->base +
68 info->usb2_port_status_reg + port_id * 0x10;
69 else
70 port_sts_reg = (uintptr_t)res->base +
71 info->usb3_port_status_reg + port_id * 0x10;
Elyes Haouasc4fbeac2022-12-04 16:06:02 +010072 port_status = read32p(port_sts_reg);
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060073
74 /* Ensure that the status is not all 1s */
75 if (port_status == 0xffffffff)
76 return false;
77
78 return !!(port_status & XHCI_STATUS_CCS);
79}
80
81void usb_xhci_disable_unused(bool (*ext_usb_xhci_en_cb)(unsigned int port_type,
82 unsigned int port_id))
83{
84 struct device *xhci, *hub = NULL, *port = NULL;
Tim Wawrzynczak56fcfb52020-11-10 13:39:37 -070085 const struct xhci_usb_info *info = soc_get_xhci_usb_info(PCH_DEVFN_XHCI);
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060086 struct drivers_usb_acpi_config *config;
87 bool enable;
88
89 xhci = pcidev_path_on_root(PCH_DEVFN_XHCI);
90 if (!xhci) {
91 printk(BIOS_ERR, "%s: Could not locate XHCI device in DT\n", __func__);
92 return;
93 }
94
Arthur Heymans7fcd4d52023-08-24 15:12:19 +020095 while ((hub = dev_bus_each_child(xhci->downstream, hub)) != NULL) {
96 while ((port = dev_bus_each_child(hub->downstream, port)) != NULL) {
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060097 enable = true;
98 config = config_of(port);
99 if (config->type == UPC_TYPE_INTERNAL) {
100 /* Probe the connect status of internal ports */
101 enable = is_usb_port_connected(info, port->path.usb.port_type,
102 port->path.usb.port_id);
103 } else if (ext_usb_xhci_en_cb) {
104 /* Check the mainboard for the status of external ports */
105 enable = ext_usb_xhci_en_cb(port->path.usb.port_type,
106 port->path.usb.port_id);
107 }
108
109 if (!enable) {
110 printk(BIOS_INFO, "%s: Disabling USB Type%d Id%d\n",
111 __func__, port->path.usb.port_type,
112 port->path.usb.port_id);
113 port->enabled = 0;
114 }
115 }
116 }
117}
Subrata Banika554b0c2017-02-16 16:08:49 +0530118
Aaron Durbin64031672018-04-21 14:45:32 -0600119__weak void soc_xhci_init(struct device *dev) { /* no-op */ }
Subrata Banika554b0c2017-02-16 16:08:49 +0530120
Nico Huber57686192022-08-06 19:11:55 +0200121struct device_operations usb_xhci_ops = {
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100122 .read_resources = pci_dev_read_resources,
123 .set_resources = pci_dev_set_resources,
124 .enable_resources = pci_dev_enable_resources,
Subrata Banika554b0c2017-02-16 16:08:49 +0530125 .init = soc_xhci_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530126 .ops_pci = &pci_dev_ops_pci,
Nico Hubera89c82e2017-09-14 15:40:28 +0200127 .scan_bus = scan_static_bus,
Julius Wernercd49cce2019-03-05 16:53:33 -0800128#if CONFIG(HAVE_ACPI_TABLES)
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100129 .acpi_name = soc_acpi_name,
Subrata Banik98376b82018-05-22 16:18:16 +0530130#endif
Subrata Banika554b0c2017-02-16 16:08:49 +0530131};
132
133static const unsigned short pci_device_ids[] = {
Appukuttan V K50c8f2e2024-01-11 18:05:11 +0530134 PCI_DID_INTEL_LNL_XHCI,
Wonkyu Kim9f401072020-11-13 15:16:32 -0800135 PCI_DID_INTEL_MTL_XHCI,
Felix Singer43b7f412022-03-07 04:34:52 +0100136 PCI_DID_INTEL_APL_XHCI,
137 PCI_DID_INTEL_CNL_LP_XHCI,
138 PCI_DID_INTEL_GLK_XHCI,
Felix Singer43b7f412022-03-07 04:34:52 +0100139 PCI_DID_INTEL_LWB_XHCI,
140 PCI_DID_INTEL_LWB_XHCI_SUPER,
Felix Singer43b7f412022-03-07 04:34:52 +0100141 PCI_DID_INTEL_CNP_H_XHCI,
142 PCI_DID_INTEL_ICP_LP_XHCI,
143 PCI_DID_INTEL_CMP_LP_XHCI,
144 PCI_DID_INTEL_CMP_H_XHCI,
145 PCI_DID_INTEL_TGP_LP_XHCI,
146 PCI_DID_INTEL_TGP_H_XHCI,
147 PCI_DID_INTEL_MCC_XHCI,
148 PCI_DID_INTEL_JSP_XHCI,
149 PCI_DID_INTEL_ADP_P_XHCI,
150 PCI_DID_INTEL_ADP_S_XHCI,
151 PCI_DID_INTEL_ADP_M_XHCI,
Jeremy Soller14d69d02023-05-17 14:52:03 -0600152 PCI_DID_INTEL_RPP_S_XHCI,
Subrata Banika554b0c2017-02-16 16:08:49 +0530153 0
154};
155
156static const struct pci_driver pch_usb_xhci __pci_driver = {
157 .ops = &usb_xhci_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100158 .vendor = PCI_VID_INTEL,
Subrata Banika554b0c2017-02-16 16:08:49 +0530159 .devices = pci_device_ids,
160};
Subrata Banike3a4a132022-04-11 17:45:33 +0530161#endif