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__
19 #include <device/pci.h>
20 #include <device/pci_def.h>
24 unsigned pci_find_next_capability(pci_devfn_t dev
, unsigned cap
, unsigned last
)
30 status
= pci_read_config16(dev
, PCI_STATUS
);
31 if (!(status
& PCI_STATUS_CAP_LIST
))
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
;
40 case PCI_HEADER_TYPE_CARDBUS
:
41 pos
= PCI_CB_CAPABILITY_LIST
;
47 pos
= pci_read_config8(dev
, pos
);
48 while (reps
-- && (pos
>= 0x40)) { /* Loop through the linked list. */
52 this_cap
= pci_read_config8(dev
, pos
+ PCI_CAP_LIST_ID
);
56 if (!last
&& (this_cap
== cap
))
62 pos
= pci_read_config8(dev
, pos
+ PCI_CAP_LIST_NEXT
);
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
)
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
)
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);
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.
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)
155 ret
= pci_early_device_probe(secondary
, dev
, mmio_base
);
157 /* Disable MMIO window if we found no suitable device. */
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 */