xref: /aosp_15_r20/external/coreboot/util/uio_usbdebug/drivers/usb/pci_ehci.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/pci_ehci.h>
4 
pci_find_next_capability(pci_devfn_t dev,unsigned cap,unsigned last)5 static unsigned pci_find_next_capability(pci_devfn_t dev, unsigned cap, unsigned last)
6 {
7 	unsigned pos = 0;
8 	u16 status;
9 	unsigned reps = 48;
10 
11 	status = pci_read_config16(dev, PCI_STATUS);
12 	if (!(status & PCI_STATUS_CAP_LIST))
13 		return 0;
14 
15 	u8 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
16 	switch (hdr_type & 0x7f) {
17 	case PCI_HEADER_TYPE_NORMAL:
18 	case PCI_HEADER_TYPE_BRIDGE:
19 		pos = PCI_CAPABILITY_LIST;
20 		break;
21 	case PCI_HEADER_TYPE_CARDBUS:
22 		pos = PCI_CB_CAPABILITY_LIST;
23 		break;
24 	default:
25 		return 0;
26 	}
27 
28 	pos = pci_read_config8(dev, pos);
29 	while (reps-- && (pos >= 0x40)) { /* Loop through the linked list. */
30 		unsigned this_cap;
31 
32 		pos &= ~3;
33 		this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
34 		if (this_cap == 0xff)
35 			break;
36 
37 		if (!last && (this_cap == cap))
38 			return pos;
39 
40 		if (last == pos)
41 			last = 0;
42 
43 		pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
44 	}
45 	return 0;
46 }
47 
pci_find_capability(pci_devfn_t dev,unsigned cap)48 static unsigned pci_find_capability(pci_devfn_t dev, unsigned cap)
49 {
50 	return pci_find_next_capability(dev, cap, 0);
51 }
52 
53 extern void *ehci_bar;
ehci_debug_hw_enable(unsigned int * base,unsigned int * dbg_offset)54 int ehci_debug_hw_enable(unsigned int *base, unsigned int *dbg_offset)
55 {
56 	pci_devfn_t dbg_dev = pci_ehci_dbg_dev(CONFIG_USBDEBUG_HCD_INDEX);
57 	pci_ehci_dbg_enable(dbg_dev, CONFIG_EHCI_BAR);
58 	pci_devfn_t dev = dbg_dev;
59 
60 	u8 pos = pci_find_capability(dev, PCI_CAP_ID_EHCI_DEBUG);
61 	if (!pos)
62 		return -1;
63 
64 	u32 cap = pci_read_config32(dev, pos);
65 
66 	/* FIXME: We should remove static EHCI_BAR_INDEX. */
67 	u8 dbg_bar = 0x10 + 4 * ((cap >> 29) - 1);
68 	if (dbg_bar != EHCI_BAR_INDEX)
69 		return -1;
70 
71 	*base = (u32)ehci_bar;
72 	*dbg_offset = (cap>>16) & 0x1ffc;
73 	return 0;
74 }
75 
ehci_debug_select_port(unsigned int port)76 void ehci_debug_select_port(unsigned int port)
77 {
78 	pci_devfn_t dbg_dev = pci_ehci_dbg_dev(CONFIG_USBDEBUG_HCD_INDEX);
79 	pci_ehci_dbg_set_port(dbg_dev, port);
80 }
81