1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/pci.h>
4 #include <device/pci_ops.h>
5 #include <delay.h>
6
pci_s_assert_secondary_reset(pci_devfn_t p2p_bridge)7 void pci_s_assert_secondary_reset(pci_devfn_t p2p_bridge)
8 {
9 u16 reg16;
10 reg16 = pci_s_read_config16(p2p_bridge, PCI_BRIDGE_CONTROL);
11 reg16 |= PCI_BRIDGE_CTL_BUS_RESET;
12 pci_s_write_config16(p2p_bridge, PCI_BRIDGE_CONTROL, reg16);
13 }
14
pci_s_deassert_secondary_reset(pci_devfn_t p2p_bridge)15 void pci_s_deassert_secondary_reset(pci_devfn_t p2p_bridge)
16 {
17 u16 reg16;
18 reg16 = pci_s_read_config16(p2p_bridge, PCI_BRIDGE_CONTROL);
19 reg16 &= ~PCI_BRIDGE_CTL_BUS_RESET;
20 pci_s_write_config16(p2p_bridge, PCI_BRIDGE_CONTROL, reg16);
21 }
22
pci_s_bridge_set_secondary(pci_devfn_t p2p_bridge,u8 secondary)23 void pci_s_bridge_set_secondary(pci_devfn_t p2p_bridge, u8 secondary)
24 {
25 /* Disable config transaction forwarding. */
26 pci_s_write_config8(p2p_bridge, PCI_SECONDARY_BUS, 0x00);
27 pci_s_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, 0x00);
28 /* Enable config transaction forwarding. */
29 pci_s_write_config8(p2p_bridge, PCI_SECONDARY_BUS, secondary);
30 pci_s_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, secondary);
31 }
32
pci_s_bridge_set_mmio(pci_devfn_t p2p_bridge,u32 base,u32 size)33 static void pci_s_bridge_set_mmio(pci_devfn_t p2p_bridge, u32 base, u32 size)
34 {
35 u16 reg16;
36
37 /* Disable MMIO window behind the bridge. */
38 reg16 = pci_s_read_config16(p2p_bridge, PCI_COMMAND);
39 reg16 &= ~PCI_COMMAND_MEMORY;
40 pci_s_write_config16(p2p_bridge, PCI_COMMAND, reg16);
41 pci_s_write_config32(p2p_bridge, PCI_MEMORY_BASE, 0x10);
42
43 if (!size)
44 return;
45
46 /* Enable MMIO window behind the bridge. */
47 pci_s_write_config32(p2p_bridge, PCI_MEMORY_BASE,
48 ((base + size - 1) & 0xfff00000) | ((base >> 16) & 0xfff0));
49
50 reg16 = pci_s_read_config16(p2p_bridge, PCI_COMMAND);
51 reg16 |= PCI_COMMAND_MEMORY;
52 pci_s_write_config16(p2p_bridge, PCI_COMMAND, reg16);
53 }
54
pci_s_early_mmio_window(pci_devfn_t p2p_bridge,u32 mmio_base,u32 mmio_size)55 static void pci_s_early_mmio_window(pci_devfn_t p2p_bridge, u32 mmio_base, u32 mmio_size)
56 {
57 int timeout, ret = -1;
58
59 /* Secondary bus number is mostly irrelevant as we disable
60 * configuration transactions right after the probe.
61 */
62 u8 secondary = 15;
63 u8 dev = 0;
64
65 /* Enable configuration and MMIO over bridge. */
66 pci_s_assert_secondary_reset(p2p_bridge);
67 pci_s_deassert_secondary_reset(p2p_bridge);
68 pci_s_bridge_set_secondary(p2p_bridge, secondary);
69 pci_s_bridge_set_mmio(p2p_bridge, mmio_base, mmio_size);
70
71 for (timeout = 20000; timeout; timeout--) {
72 pci_devfn_t dbg_dev = PCI_DEV(secondary, dev, 0);
73 u32 id = pci_s_read_config32(dbg_dev, PCI_VENDOR_ID);
74 if (id != 0 && id != 0xffffffff && id != 0xffff0001)
75 break;
76 udelay(10);
77 }
78
79 if (timeout != 0)
80 ret = pci_early_device_probe(secondary, dev, mmio_base);
81
82 /* Disable MMIO window if we found no suitable device. */
83 if (ret)
84 pci_s_bridge_set_mmio(p2p_bridge, 0, 0);
85
86 /* Resource allocator will reconfigure bridges and secondary bus
87 * number may change. Thus early device cannot reliably use config
88 * transactions from here on, so we may as well disable them.
89 */
90 pci_s_bridge_set_secondary(p2p_bridge, 0);
91 }
92
pci_early_bridge_init(void)93 void pci_early_bridge_init(void)
94 {
95 /* No PCI-to-PCI bridges are enabled yet, so the one we try to
96 * configure must have its primary on bus 0.
97 */
98 pci_devfn_t p2p_bridge = PCI_DEV(0, CONFIG_EARLY_PCI_BRIDGE_DEVICE,
99 CONFIG_EARLY_PCI_BRIDGE_FUNCTION);
100
101 pci_s_early_mmio_window(p2p_bridge, CONFIG_EARLY_PCI_MMIO_BASE, 0x4000);
102 }
103
104 /* FIXME: A lot of issues using the following, please avoid.
105 * Assumes 256 PCI buses, scans them all even when PCI bridges are still
106 * disabled. Probes all functions even if 0 is not present.
107 */
pci_locate_device(unsigned int pci_id,pci_devfn_t dev)108 pci_devfn_t pci_locate_device(unsigned int pci_id, pci_devfn_t dev)
109 {
110 for (; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0, 0, 1)) {
111 unsigned int id;
112 id = pci_s_read_config32(dev, 0);
113 if (id == pci_id)
114 return dev;
115 }
116 return PCI_DEV_INVALID;
117 }
118
pci_locate_device_on_bus(unsigned int pci_id,unsigned int bus)119 pci_devfn_t pci_locate_device_on_bus(unsigned int pci_id, unsigned int bus)
120 {
121 pci_devfn_t dev, last;
122
123 dev = PCI_DEV(bus, 0, 0);
124 last = PCI_DEV(bus, 31, 7);
125
126 for (; dev <= last; dev += PCI_DEV(0, 0, 1)) {
127 unsigned int id;
128 id = pci_s_read_config32(dev, 0);
129 if (id == pci_id)
130 return dev;
131 }
132 return PCI_DEV_INVALID;
133 }
134