soc/intel/common/block: Move common uart function to block/uart
[coreboot.git] / src / device / pci_early.c
blob6baebe0c280c824a7466444f55d8866bb01ddd88
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2011 Google Inc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #define __SIMPLE_DEVICE__
18 #include <arch/io.h>
19 #include <device/pci.h>
20 #include <device/pci_def.h>
21 #include <delay.h>
23 #ifdef __PRE_RAM__
24 unsigned pci_find_next_capability(pci_devfn_t dev, unsigned cap, unsigned last)
26 unsigned pos = 0;
27 u16 status;
28 unsigned reps = 48;
30 status = pci_read_config16(dev, PCI_STATUS);
31 if (!(status & PCI_STATUS_CAP_LIST))
32 return 0;
34 u8 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
35 switch (hdr_type & 0x7f) {
36 case PCI_HEADER_TYPE_NORMAL:
37 case PCI_HEADER_TYPE_BRIDGE:
38 pos = PCI_CAPABILITY_LIST;
39 break;
40 case PCI_HEADER_TYPE_CARDBUS:
41 pos = PCI_CB_CAPABILITY_LIST;
42 break;
43 default:
44 return 0;
47 pos = pci_read_config8(dev, pos);
48 while (reps-- && (pos >= 0x40)) { /* Loop through the linked list. */
49 int this_cap;
51 pos &= ~3;
52 this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
53 if (this_cap == 0xff)
54 break;
56 if (!last && (this_cap == cap))
57 return pos;
59 if (last == pos)
60 last = 0;
62 pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
64 return 0;
67 unsigned pci_find_capability(pci_devfn_t dev, unsigned cap)
69 return pci_find_next_capability(dev, cap, 0);
71 #endif /* __PRE_RAM__ */
74 #if IS_ENABLED(CONFIG_EARLY_PCI_BRIDGE)
76 static void pci_bridge_reset_secondary(device_t p2p_bridge)
78 u16 reg16;
80 /* First we reset the secondary bus. */
81 reg16 = pci_read_config16(p2p_bridge, PCI_BRIDGE_CONTROL);
82 reg16 |= (1 << 6); /* SRESET */
83 pci_write_config16(p2p_bridge, PCI_BRIDGE_CONTROL, reg16);
85 /* Assume we don't have to wait here forever */
87 /* Read back and clear reset bit. */
88 reg16 = pci_read_config16(p2p_bridge, PCI_BRIDGE_CONTROL);
89 reg16 &= ~(1 << 6); /* SRESET */
90 pci_write_config16(p2p_bridge, PCI_BRIDGE_CONTROL, reg16);
93 static void pci_bridge_set_secondary(device_t p2p_bridge, u8 secondary)
95 /* Disable config transaction forwarding. */
96 pci_write_config8(p2p_bridge, PCI_SECONDARY_BUS, 0x00);
97 pci_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, 0x00);
98 /* Enable config transaction forwarding. */
99 pci_write_config8(p2p_bridge, PCI_SECONDARY_BUS, secondary);
100 pci_write_config8(p2p_bridge, PCI_SUBORDINATE_BUS, secondary);
103 static void pci_bridge_set_mmio(device_t p2p_bridge, u32 base, u32 size)
105 u16 reg16;
107 /* Disable MMIO window behind the bridge. */
108 reg16 = pci_read_config16(p2p_bridge, PCI_COMMAND);
109 reg16 &= ~PCI_COMMAND_MEMORY;
110 pci_write_config16(p2p_bridge, PCI_COMMAND, reg16);
111 pci_write_config32(p2p_bridge, PCI_MEMORY_BASE, 0x10);
113 if (!size)
114 return;
116 /* Enable MMIO window behind the bridge. */
117 pci_write_config32(p2p_bridge, PCI_MEMORY_BASE,
118 ((base + size - 1) & 0xfff00000) | ((base >> 16) & 0xfff0));
120 reg16 = pci_read_config16(p2p_bridge, PCI_COMMAND);
121 reg16 |= PCI_COMMAND_MEMORY;
122 pci_write_config16(p2p_bridge, PCI_COMMAND, reg16);
125 void pci_early_bridge_init(void)
127 int timeout, ret = -1;
129 /* No PCI-to-PCI bridges are enabled yet, so the one we try to
130 * configure must have its primary on bus 0.
132 pci_devfn_t p2p_bridge = PCI_DEV(0, CONFIG_EARLY_PCI_BRIDGE_DEVICE,
133 CONFIG_EARLY_PCI_BRIDGE_FUNCTION);
135 /* Secondary bus number is mostly irrelevant as we disable
136 * configuration transactions right after the probe.
138 u8 secondary = 15;
139 u8 dev = 0;
140 u32 mmio_base = CONFIG_EARLY_PCI_MMIO_BASE;
142 /* Enable configuration and MMIO over bridge. */
143 pci_bridge_reset_secondary(p2p_bridge);
144 pci_bridge_set_secondary(p2p_bridge, secondary);
145 pci_bridge_set_mmio(p2p_bridge, mmio_base, 0x4000);
147 for (timeout = 20000; timeout; timeout--) {
148 u32 id = pci_read_config32(PCI_DEV(secondary, dev, 0), PCI_VENDOR_ID);
149 if (id != 0 && id != 0xffffffff && id != 0xffff0001)
150 break;
151 udelay(10);
154 if (timeout != 0)
155 ret = pci_early_device_probe(secondary, dev, mmio_base);
157 /* Disable MMIO window if we found no suitable device. */
158 if (ret)
159 pci_bridge_set_mmio(p2p_bridge, 0, 0);
161 /* Resource allocator will reconfigure bridges and secondary bus
162 * number may change. Thus early device cannot reliably use config
163 * transactions from here on, so we may as well disable them.
165 pci_bridge_set_secondary(p2p_bridge, 0);
167 #endif /* CONFIG_EARLY_PCI_BRIDGE */