/ src / device / pci_early.c
pci_early.c
  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  
  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  
 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  
 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  
 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  
 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  
 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   */
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  
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  }