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