blob: 86278f9222ffcbeff61ade550bfbbd60b1cb3a3e [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Kyösti Mälkki2161c1d2014-02-11 19:56:57 +02002
Kyösti Mälkki2161c1d2014-02-11 19:56:57 +02003#include <device/pci.h>
Kyösti Mälkki5b141162019-01-23 16:02:28 +02004#include <device/pci_ops.h>
Kyösti Mälkki4c686f22014-02-14 12:45:09 +02005#include <delay.h>
6
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +03007void pci_s_assert_secondary_reset(pci_devfn_t p2p_bridge)
Kyösti Mälkki4c686f22014-02-14 12:45:09 +02008{
9 u16 reg16;
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030010 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);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020013}
14
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030015void 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
23void pci_s_bridge_set_secondary(pci_devfn_t p2p_bridge, u8 secondary)
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020024{
25 /* Disable config transaction forwarding. */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030026 pci_s_write_config8(p2p_bridge, PCI_SECONDARY_BUS, 0x00);
27 pci_s_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, 0x00);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020028 /* Enable config transaction forwarding. */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030029 pci_s_write_config8(p2p_bridge, PCI_SECONDARY_BUS, secondary);
30 pci_s_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, secondary);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020031}
32
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030033static void pci_s_bridge_set_mmio(pci_devfn_t p2p_bridge, u32 base, u32 size)
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020034{
35 u16 reg16;
36
37 /* Disable MMIO window behind the bridge. */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030038 reg16 = pci_s_read_config16(p2p_bridge, PCI_COMMAND);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020039 reg16 &= ~PCI_COMMAND_MEMORY;
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030040 pci_s_write_config16(p2p_bridge, PCI_COMMAND, reg16);
41 pci_s_write_config32(p2p_bridge, PCI_MEMORY_BASE, 0x10);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020042
43 if (!size)
44 return;
45
46 /* Enable MMIO window behind the bridge. */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030047 pci_s_write_config32(p2p_bridge, PCI_MEMORY_BASE,
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020048 ((base + size - 1) & 0xfff00000) | ((base >> 16) & 0xfff0));
49
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030050 reg16 = pci_s_read_config16(p2p_bridge, PCI_COMMAND);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020051 reg16 |= PCI_COMMAND_MEMORY;
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030052 pci_s_write_config16(p2p_bridge, PCI_COMMAND, reg16);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020053}
54
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030055static void pci_s_early_mmio_window(pci_devfn_t p2p_bridge, u32 mmio_base, u32 mmio_size)
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020056{
57 int timeout, ret = -1;
58
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020059 /* 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;
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020064
65 /* Enable configuration and MMIO over bridge. */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030066 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);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020070
71 for (timeout = 20000; timeout; timeout--) {
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030072 pci_devfn_t dbg_dev = PCI_DEV(secondary, dev, 0);
73 u32 id = pci_s_read_config32(dbg_dev, PCI_VENDOR_ID);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020074 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)
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030084 pci_s_bridge_set_mmio(p2p_bridge, 0, 0);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020085
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 */
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +030090 pci_s_bridge_set_secondary(p2p_bridge, 0);
Kyösti Mälkki4c686f22014-02-14 12:45:09 +020091}
Kyösti Mälkki3521e262018-12-26 19:33:28 +020092
93void 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
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +0300101 pci_s_early_mmio_window(p2p_bridge, CONFIG_EARLY_PCI_MMIO_BASE, 0x4000);
Kyösti Mälkki3521e262018-12-26 19:33:28 +0200102}
Kyösti Mälkki8a41f4b2019-02-08 18:14:34 +0200103
104/* FIXME: A lot of issues using the following, please avoid.
Martin Roth0949e732021-10-01 14:28:22 -0600105 * Assumes 256 PCI buses, scans them all even when PCI bridges are still
Kyösti Mälkki8a41f4b2019-02-08 18:14:34 +0200106 * disabled. Probes all functions even if 0 is not present.
107 */
108pci_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;
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +0300112 id = pci_s_read_config32(dev, 0);
Kyösti Mälkki8a41f4b2019-02-08 18:14:34 +0200113 if (id == pci_id)
114 return dev;
115 }
116 return PCI_DEV_INVALID;
117}
118
119pci_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;
Kyösti Mälkkia0b366d2019-09-26 22:33:51 +0300128 id = pci_s_read_config32(dev, 0);
Kyösti Mälkki8a41f4b2019-02-08 18:14:34 +0200129 if (id == pci_id)
130 return dev;
131 }
132 return PCI_DEV_INVALID;
133}