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