blob: 353840a2ca50c20e374efee0f15f6f2c9852ed50 [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>
6#include <device/pci.h>
7#include <device/pci_ids.h>
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -06008#include <drivers/usb/acpi/chip.h>
Duncan Lauriebf713b02018-05-07 15:33:18 -07009#include <intelblocks/acpi.h>
Subrata Banika554b0c2017-02-16 16:08:49 +053010#include <intelblocks/xhci.h>
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060011#include <soc/pci_devs.h>
12
13#define XHCI_USB2 2
14#define XHCI_USB3 3
15
16/* Current Connect Status */
17#define XHCI_STATUS_CCS (1 << 0)
18
19static bool is_usb_port_connected(const struct xhci_usb_info *info,
20 unsigned int port_type, unsigned int port_id)
21{
22 uintptr_t port_sts_reg;
23 uint32_t port_status;
24 const struct resource *res;
25
26 /* Support only USB2 or USB3 ports */
27 if (!(port_type == XHCI_USB2 || port_type == XHCI_USB3))
28 return false;
29
30 /* Mark out of bound port id as not connected */
31 if ((port_type == XHCI_USB2 && port_id >= info->num_usb2_ports) ||
32 (port_type == XHCI_USB3 && port_id >= info->num_usb3_ports))
33 return false;
34
35 /* Calculate port status register address and read the status */
Angel Ponsc1bfbe02021-11-03 13:18:53 +010036 res = probe_resource(PCH_DEV_XHCI, PCI_BASE_ADDRESS_0);
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060037 /* If the memory BAR is not allocated for XHCI, leave the devices enabled */
38 if (!res)
39 return true;
40
41 if (port_type == XHCI_USB2)
42 port_sts_reg = (uintptr_t)res->base +
43 info->usb2_port_status_reg + port_id * 0x10;
44 else
45 port_sts_reg = (uintptr_t)res->base +
46 info->usb3_port_status_reg + port_id * 0x10;
47 port_status = read32((void *)port_sts_reg);
48
49 /* Ensure that the status is not all 1s */
50 if (port_status == 0xffffffff)
51 return false;
52
53 return !!(port_status & XHCI_STATUS_CCS);
54}
55
56void usb_xhci_disable_unused(bool (*ext_usb_xhci_en_cb)(unsigned int port_type,
57 unsigned int port_id))
58{
59 struct device *xhci, *hub = NULL, *port = NULL;
Tim Wawrzynczak56fcfb52020-11-10 13:39:37 -070060 const struct xhci_usb_info *info = soc_get_xhci_usb_info(PCH_DEVFN_XHCI);
Karthikeyan Ramasubramanianef0c2262019-06-06 15:35:11 -060061 struct drivers_usb_acpi_config *config;
62 bool enable;
63
64 xhci = pcidev_path_on_root(PCH_DEVFN_XHCI);
65 if (!xhci) {
66 printk(BIOS_ERR, "%s: Could not locate XHCI device in DT\n", __func__);
67 return;
68 }
69
70 while ((hub = dev_bus_each_child(xhci->link_list, hub)) != NULL) {
71 while ((port = dev_bus_each_child(hub->link_list, port)) != NULL) {
72 enable = true;
73 config = config_of(port);
74 if (config->type == UPC_TYPE_INTERNAL) {
75 /* Probe the connect status of internal ports */
76 enable = is_usb_port_connected(info, port->path.usb.port_type,
77 port->path.usb.port_id);
78 } else if (ext_usb_xhci_en_cb) {
79 /* Check the mainboard for the status of external ports */
80 enable = ext_usb_xhci_en_cb(port->path.usb.port_type,
81 port->path.usb.port_id);
82 }
83
84 if (!enable) {
85 printk(BIOS_INFO, "%s: Disabling USB Type%d Id%d\n",
86 __func__, port->path.usb.port_type,
87 port->path.usb.port_id);
88 port->enabled = 0;
89 }
90 }
91 }
92}
Subrata Banika554b0c2017-02-16 16:08:49 +053093
Aaron Durbin64031672018-04-21 14:45:32 -060094__weak void soc_xhci_init(struct device *dev) { /* no-op */ }
Subrata Banika554b0c2017-02-16 16:08:49 +053095
96static struct device_operations usb_xhci_ops = {
Elyes HAOUAS1d191272018-11-27 12:23:48 +010097 .read_resources = pci_dev_read_resources,
98 .set_resources = pci_dev_set_resources,
99 .enable_resources = pci_dev_enable_resources,
Subrata Banika554b0c2017-02-16 16:08:49 +0530100 .init = soc_xhci_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530101 .ops_pci = &pci_dev_ops_pci,
Nico Hubera89c82e2017-09-14 15:40:28 +0200102 .scan_bus = scan_static_bus,
Julius Wernercd49cce2019-03-05 16:53:33 -0800103#if CONFIG(HAVE_ACPI_TABLES)
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100104 .acpi_name = soc_acpi_name,
Subrata Banik98376b82018-05-22 16:18:16 +0530105#endif
Subrata Banika554b0c2017-02-16 16:08:49 +0530106};
107
108static const unsigned short pci_device_ids[] = {
Felix Singer43b7f412022-03-07 04:34:52 +0100109 PCI_DID_INTEL_APL_XHCI,
110 PCI_DID_INTEL_CNL_LP_XHCI,
111 PCI_DID_INTEL_GLK_XHCI,
112 PCI_DID_INTEL_SPT_LP_XHCI,
113 PCI_DID_INTEL_SPT_H_XHCI,
114 PCI_DID_INTEL_LWB_XHCI,
115 PCI_DID_INTEL_LWB_XHCI_SUPER,
116 PCI_DID_INTEL_UPT_H_XHCI,
117 PCI_DID_INTEL_CNP_H_XHCI,
118 PCI_DID_INTEL_ICP_LP_XHCI,
119 PCI_DID_INTEL_CMP_LP_XHCI,
120 PCI_DID_INTEL_CMP_H_XHCI,
121 PCI_DID_INTEL_TGP_LP_XHCI,
122 PCI_DID_INTEL_TGP_H_XHCI,
123 PCI_DID_INTEL_MCC_XHCI,
124 PCI_DID_INTEL_JSP_XHCI,
125 PCI_DID_INTEL_ADP_P_XHCI,
126 PCI_DID_INTEL_ADP_S_XHCI,
127 PCI_DID_INTEL_ADP_M_XHCI,
Subrata Banika554b0c2017-02-16 16:08:49 +0530128 0
129};
130
131static const struct pci_driver pch_usb_xhci __pci_driver = {
132 .ops = &usb_xhci_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100133 .vendor = PCI_VID_INTEL,
Subrata Banika554b0c2017-02-16 16:08:49 +0530134 .devices = pci_device_ids,
135};