blob: 8370b960e7384d574a64ba3e87546e23e7e9f779 [file] [log] [blame]
Kevin O'Connor0525d292008-07-04 06:18:30 -04001// Initialize PCI devices (on emulators)
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2006 Fabrice Bellard
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor0525d292008-07-04 06:18:30 -04007
8#include "util.h" // dprintf
Kevin O'Connorbe19cdc2008-11-09 15:33:47 -05009#include "pci.h" // pci_config_readl
Kevin O'Connor2ed2f582008-11-08 15:53:36 -050010#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
11#include "pci_regs.h" // PCI_COMMAND
Kevin O'Connor4bc49972012-05-13 22:58:08 -040012#include "ioport.h" // PORT_ATA1_CMD_BASE
13#include "config.h" // CONFIG_*
Isaku Yamahata72a590e2012-11-28 10:17:33 +010014#include "memmap.h" // add_e820
Kevin O'Connorf85e4bc2013-02-19 01:33:45 -050015#include "paravirt.h" // RamSize
Kevin O'Connora88c1972013-06-08 21:51:46 -040016#include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR
17#include "list.h" // struct hlist_node
Isaku Yamahata72a590e2012-11-28 10:17:33 +010018
19/* PM Timer ticks per second (HZ) */
20#define PM_TIMER_FREQUENCY 3579545
Kevin O'Connor0525d292008-07-04 06:18:30 -040021
Alexey Korolev5fa24b52012-04-18 17:31:58 +120022#define PCI_DEVICE_MEM_MIN 0x1000
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020023#define PCI_BRIDGE_IO_MIN 0x1000
24#define PCI_BRIDGE_MEM_MIN 0x100000
Isaku Yamahataaf0963d2010-06-22 17:57:53 +090025
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020026enum pci_region_type {
27 PCI_REGION_TYPE_IO,
28 PCI_REGION_TYPE_MEM,
29 PCI_REGION_TYPE_PREFMEM,
30 PCI_REGION_TYPE_COUNT,
31};
32
33static const char *region_type_name[] = {
34 [ PCI_REGION_TYPE_IO ] = "io",
35 [ PCI_REGION_TYPE_MEM ] = "mem",
36 [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
37};
38
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +020039u64 pcimem_start = BUILD_PCIMEM_START;
40u64 pcimem_end = BUILD_PCIMEM_END;
41u64 pcimem64_start = BUILD_PCIMEM64_START;
42u64 pcimem64_end = BUILD_PCIMEM64_END;
43
Alexey Korolevfa51bcd2012-04-18 17:21:19 +120044struct pci_region_entry {
45 struct pci_device *dev;
46 int bar;
Alexey Korolev030288f2012-04-19 17:44:55 +120047 u64 size;
48 u64 align;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +120049 int is64;
50 enum pci_region_type type;
Kevin O'Connora88c1972013-06-08 21:51:46 -040051 struct hlist_node node;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +120052};
53
Alexey Korolev35a770f2012-04-19 17:47:19 +120054struct pci_region {
Alexey Korolev35a770f2012-04-19 17:47:19 +120055 /* pci region assignments */
56 u64 base;
Kevin O'Connora88c1972013-06-08 21:51:46 -040057 struct hlist_head list;
Alexey Korolev35a770f2012-04-19 17:47:19 +120058};
59
Kevin O'Connorb725dcb2011-10-15 11:53:38 -040060struct pci_bus {
Alexey Korolev35a770f2012-04-19 17:47:19 +120061 struct pci_region r[PCI_REGION_TYPE_COUNT];
Kevin O'Connor2c4c2112011-10-15 11:42:48 -040062 struct pci_device *bus_dev;
Kevin O'Connorb725dcb2011-10-15 11:53:38 -040063};
Gerd Hoffmann82b39b22011-07-11 09:20:28 +020064
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040065static u32 pci_bar(struct pci_device *pci, int region_num)
Isaku Yamahataa65821d2010-06-22 17:57:50 +090066{
67 if (region_num != PCI_ROM_SLOT) {
68 return PCI_BASE_ADDRESS_0 + region_num * 4;
69 }
Isaku Yamahata5d0de152010-06-22 17:57:51 +090070
71#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040072 u8 type = pci->header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
Isaku Yamahata5d0de152010-06-22 17:57:51 +090073 return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
Isaku Yamahataa65821d2010-06-22 17:57:50 +090074}
75
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -040076static void
Alexey Korolev030288f2012-04-19 17:44:55 +120077pci_set_io_region_addr(struct pci_device *pci, int bar, u64 addr, int is64)
Kevin O'Connor0525d292008-07-04 06:18:30 -040078{
Alexey Korolev030288f2012-04-19 17:44:55 +120079 u32 ofs = pci_bar(pci, bar);
80 pci_config_writel(pci->bdf, ofs, addr);
81 if (is64)
82 pci_config_writel(pci->bdf, ofs + 4, addr >> 32);
Isaku Yamahatab9e47212010-06-22 17:57:47 +090083}
84
Kevin O'Connor5bab7e62011-10-01 11:33:31 -040085
86/****************************************************************
87 * Misc. device init
88 ****************************************************************/
89
90/* host irqs corresponding to PCI irqs A-D */
91const u8 pci_irqs[4] = {
92 10, 10, 11, 11
93};
94
Alex Williamsondbb7a662013-02-21 09:12:23 -070095static int dummy_pci_slot_get_irq(struct pci_device *pci, int pin)
96{
97 dprintf(1, "pci_slot_get_irq called with unknown routing\n");
98
99 return 0xff; /* PCI defined "unknown" or "no connection" for x86 */
100}
101
102static int (*pci_slot_get_irq)(struct pci_device *pci, int pin) =
103 dummy_pci_slot_get_irq;
Alex Williamsonb9490402013-02-15 14:11:41 -0700104
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400105// Return the global irq number corresponding to a host bus device irq pin.
Alex Williamsonb9490402013-02-15 14:11:41 -0700106static int piix_pci_slot_get_irq(struct pci_device *pci, int pin)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400107{
Gerd Hoffmann0c8f58d2012-05-04 17:33:36 +0200108 int slot_addend = 0;
109
110 while (pci->parent != NULL) {
111 slot_addend += pci_bdf_to_dev(pci->bdf);
112 pci = pci->parent;
113 }
114 slot_addend += pci_bdf_to_dev(pci->bdf) - 1;
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400115 return pci_irqs[(pin - 1 + slot_addend) & 3];
Kevin O'Connor0525d292008-07-04 06:18:30 -0400116}
117
Alex Williamsonb9490402013-02-15 14:11:41 -0700118static int mch_pci_slot_get_irq(struct pci_device *pci, int pin)
119{
120 int irq, slot, pin_addend = 0;
121
122 while (pci->parent != NULL) {
123 pin_addend += pci_bdf_to_dev(pci->bdf);
124 pci = pci->parent;
125 }
126 slot = pci_bdf_to_dev(pci->bdf);
127
128 switch (slot) {
129 /* Slots 0-24 rotate slot:pin mapping similar to piix above, but
130 with a different starting index - see q35-acpi-dsdt.dsl */
131 case 0 ... 24:
132 irq = pci_irqs[(pin - 1 + pin_addend + slot) & 3];
133 break;
134 /* Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H) */
135 case 25 ... 31:
136 irq = pci_irqs[(pin - 1 + pin_addend) & 3];
137 break;
138 }
139
140 return irq;
141}
142
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400143/* PIIX3/PIIX4 PCI to ISA bridge */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500144static void piix_isa_bridge_setup(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400145{
146 int i, irq;
147 u8 elcr[2];
148
149 elcr[0] = 0x00;
150 elcr[1] = 0x00;
151 for (i = 0; i < 4; i++) {
152 irq = pci_irqs[i];
153 /* set to trigger level */
154 elcr[irq >> 3] |= (1 << (irq & 7));
155 /* activate irq remapping in PIIX */
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400156 pci_config_writeb(pci->bdf, 0x60 + i, irq);
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400157 }
158 outb(elcr[0], 0x4d0);
159 outb(elcr[1], 0x4d1);
160 dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
161}
162
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100163/* ICH9 LPC PCI to ISA bridge */
164/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500165void mch_isa_bridge_setup(struct pci_device *dev, void *arg)
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100166{
167 u16 bdf = dev->bdf;
168 int i, irq;
169 u8 elcr[2];
170
171 elcr[0] = 0x00;
172 elcr[1] = 0x00;
173
174 for (i = 0; i < 4; i++) {
175 irq = pci_irqs[i];
176 /* set to trigger level */
177 elcr[irq >> 3] |= (1 << (irq & 7));
178
179 /* activate irq remapping in LPC */
180
181 /* PIRQ[A-D] routing */
Alex Williamson555a2132013-02-15 14:11:35 -0700182 pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i, irq);
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100183 /* PIRQ[E-H] routing */
Alex Williamson555a2132013-02-15 14:11:35 -0700184 pci_config_writeb(bdf, ICH9_LPC_PIRQE_ROUT + i, irq);
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100185 }
186 outb(elcr[0], ICH9_LPC_PORT_ELCR1);
187 outb(elcr[1], ICH9_LPC_PORT_ELCR2);
188 dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]);
189
190 /* pm io base */
191 pci_config_writel(bdf, ICH9_LPC_PMBASE,
192 PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE);
193
194 /* acpi enable, SCI: IRQ9 000b = irq9*/
195 pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
196
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500197 pmtimer_setup(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100198}
199
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500200static void storage_ide_setup(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400201{
202 /* IDE: we map it as in ISA mode */
Alexey Korolev030288f2012-04-19 17:44:55 +1200203 pci_set_io_region_addr(pci, 0, PORT_ATA1_CMD_BASE, 0);
204 pci_set_io_region_addr(pci, 1, PORT_ATA1_CTRL_BASE, 0);
205 pci_set_io_region_addr(pci, 2, PORT_ATA2_CMD_BASE, 0);
206 pci_set_io_region_addr(pci, 3, PORT_ATA2_CTRL_BASE, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400207}
208
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400209/* PIIX3/PIIX4 IDE */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500210static void piix_ide_setup(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400211{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400212 u16 bdf = pci->bdf;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400213 pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
214 pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400215}
216
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500217static void pic_ibm_setup(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400218{
219 /* PIC, IBM, MPIC & MPIC2 */
Alexey Korolev030288f2012-04-19 17:44:55 +1200220 pci_set_io_region_addr(pci, 0, 0x80800000 + 0x00040000, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400221}
222
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500223static void apple_macio_setup(struct pci_device *pci, void *arg)
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400224{
225 /* macio bridge */
Alexey Korolev030288f2012-04-19 17:44:55 +1200226 pci_set_io_region_addr(pci, 0, 0x80800000, 0);
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400227}
228
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400229/* PIIX4 Power Management device (for ACPI) */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500230static void piix4_pm_setup(struct pci_device *pci, void *arg)
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400231{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400232 u16 bdf = pci->bdf;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400233 // acpi sci is hardwired to 9
234 pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
235
236 pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
237 pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
238 pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
239 pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
Gerd Hoffmann455a7c82012-09-06 08:01:00 +0200240
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500241 pmtimer_setup(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400242}
243
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100244/* ICH9 SMBUS */
245/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500246void ich9_smbus_setup(struct pci_device *dev, void *arg)
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100247{
248 u16 bdf = dev->bdf;
249 /* map smbus into io space */
250 pci_config_writel(bdf, ICH9_SMB_SMB_BASE,
251 PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO);
252
253 /* enable SMBus */
254 pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
255}
256
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400257static const struct pci_device_id pci_device_tbl[] = {
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500258 /* PIIX3/PIIX4 PCI to ISA bridge */
259 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500260 piix_isa_bridge_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500261 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500262 piix_isa_bridge_setup),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100263 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500264 mch_isa_bridge_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500265
266 /* STORAGE IDE */
267 PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500268 PCI_CLASS_STORAGE_IDE, piix_ide_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500269 PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500270 PCI_CLASS_STORAGE_IDE, piix_ide_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500271 PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500272 storage_ide_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500273
274 /* PIC, IBM, MIPC & MPIC2 */
275 PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500276 pic_ibm_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500277 PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500278 pic_ibm_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500279
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400280 /* PIIX4 Power Management device (for ACPI) */
281 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500282 piix4_pm_setup),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100283 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500284 ich9_smbus_setup),
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400285
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500286 /* 0xff00 */
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500287 PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup),
288 PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup),
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500289
Kevin O'Connor0d6b8d52010-07-10 13:12:37 -0400290 PCI_DEVICE_END,
291};
292
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400293static void pci_bios_init_device(struct pci_device *pci)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400294{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400295 u16 bdf = pci->bdf;
Kevin O'Connor99e37c42011-10-01 10:47:21 -0400296 dprintf(1, "PCI: init bdf=%02x:%02x.%x id=%04x:%04x\n"
297 , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400298 , pci->vendor, pci->device);
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400299
Kevin O'Connor0525d292008-07-04 06:18:30 -0400300 /* map the interrupt */
Kevin O'Connor0ce21382011-10-01 14:52:35 -0400301 int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
302 if (pin != 0)
Gerd Hoffmann0c8f58d2012-05-04 17:33:36 +0200303 pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
Kevin O'Connor0525d292008-07-04 06:18:30 -0400304
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400305 pci_init_device(pci_device_tbl, pci, NULL);
Kevin O'Connor31dcfb02012-11-20 20:29:26 -0500306
307 /* enable memory mappings */
Isaku Yamahatad146ab82012-11-28 10:17:32 +0100308 pci_config_maskw(bdf, PCI_COMMAND, 0,
309 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR);
Kevin O'Connor0525d292008-07-04 06:18:30 -0400310}
311
Kevin O'Connor3f2288f2011-10-15 12:02:14 -0400312static void pci_bios_init_devices(void)
Isaku Yamahataaf0963d2010-06-22 17:57:53 +0900313{
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400314 struct pci_device *pci;
315 foreachpci(pci) {
Kevin O'Connor278b19f2011-06-21 22:41:15 -0400316 pci_bios_init_device(pci);
Isaku Yamahataaf0963d2010-06-22 17:57:53 +0900317 }
318}
319
Alex Williamson7adfd712013-03-20 10:58:47 -0600320static void pci_enable_default_vga(void)
321{
322 struct pci_device *pci;
323
324 foreachpci(pci) {
325 if (is_pci_vga(pci)) {
326 dprintf(1, "PCI: Using %02x:%02x.%x for primary VGA\n",
327 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
328 pci_bdf_to_fn(pci->bdf));
329 return;
330 }
331 }
332
333 pci = pci_find_class(PCI_CLASS_DISPLAY_VGA);
334 if (!pci) {
335 dprintf(1, "PCI: No VGA devices found\n");
336 return;
337 }
338
339 dprintf(1, "PCI: Enabling %02x:%02x.%x for primary VGA\n",
340 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
341 pci_bdf_to_fn(pci->bdf));
342
343 pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
344 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
345
346 while (pci->parent) {
347 pci = pci->parent;
348
349 dprintf(1, "PCI: Setting VGA enable on bridge %02x:%02x.%x\n",
350 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
351 pci_bdf_to_fn(pci->bdf));
352
353 pci_config_maskw(pci->bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_VGA);
354 pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
355 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
356 }
357}
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400358
359/****************************************************************
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500360 * Platform device initialization
361 ****************************************************************/
362
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500363void i440fx_mem_addr_setup(struct pci_device *dev, void *arg)
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500364{
365 if (RamSize <= 0x80000000)
366 pcimem_start = 0x80000000;
367 else if (RamSize <= 0xc0000000)
368 pcimem_start = 0xc0000000;
Alex Williamsonb9490402013-02-15 14:11:41 -0700369
370 pci_slot_get_irq = piix_pci_slot_get_irq;
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500371}
372
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500373void mch_mem_addr_setup(struct pci_device *dev, void *arg)
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100374{
375 u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
376 u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE;
377
378 /* setup mmconfig */
379 u16 bdf = dev->bdf;
380 u32 upper = addr >> 32;
381 u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
382 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
383 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
384 pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
385 add_e820(addr, size, E820_RESERVED);
386
387 /* setup pci i/o window (above mmconfig) */
388 pcimem_start = addr + size;
Alex Williamsonb9490402013-02-15 14:11:41 -0700389
390 pci_slot_get_irq = mch_pci_slot_get_irq;
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100391}
392
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500393static const struct pci_device_id pci_platform_tbl[] = {
394 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500395 i440fx_mem_addr_setup),
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100396 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH,
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500397 mch_mem_addr_setup),
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500398 PCI_DEVICE_END
399};
400
401static void pci_bios_init_platform(void)
402{
403 struct pci_device *pci;
404 foreachpci(pci) {
405 pci_init_device(pci_platform_tbl, pci, NULL);
406 }
407}
408
409
410/****************************************************************
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400411 * Bus initialization
412 ****************************************************************/
413
Isaku Yamahataf4416662010-06-22 17:57:52 +0900414static void
415pci_bios_init_bus_rec(int bus, u8 *pci_bus)
416{
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400417 int bdf;
Isaku Yamahataf4416662010-06-22 17:57:52 +0900418 u16 class;
419
420 dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
421
422 /* prevent accidental access to unintended devices */
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400423 foreachbdf(bdf, bus) {
Isaku Yamahataf4416662010-06-22 17:57:52 +0900424 class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
425 if (class == PCI_CLASS_BRIDGE_PCI) {
426 pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
427 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
428 }
429 }
430
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400431 foreachbdf(bdf, bus) {
Isaku Yamahataf4416662010-06-22 17:57:52 +0900432 class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
433 if (class != PCI_CLASS_BRIDGE_PCI) {
434 continue;
435 }
436 dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
437
438 u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
439 if (pribus != bus) {
440 dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
441 pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
442 } else {
443 dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
444 }
445
446 u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
447 (*pci_bus)++;
448 if (*pci_bus != secbus) {
449 dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
450 secbus, *pci_bus);
451 secbus = *pci_bus;
452 pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
453 } else {
454 dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
455 }
456
457 /* set to max for access to all subordinate buses.
458 later set it to accurate value */
459 u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
460 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
461
462 pci_bios_init_bus_rec(secbus, pci_bus);
463
464 if (subbus != *pci_bus) {
465 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
466 subbus, *pci_bus);
467 subbus = *pci_bus;
468 } else {
469 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
470 }
471 pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
472 }
473}
474
475static void
476pci_bios_init_bus(void)
477{
478 u8 pci_bus = 0;
479 pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200480}
481
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400482
483/****************************************************************
484 * Bus sizing
485 ****************************************************************/
486
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400487static void
Alexey Korolev030288f2012-04-19 17:44:55 +1200488pci_bios_get_bar(struct pci_device *pci, int bar,
489 int *ptype, u64 *psize, int *pis64)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200490{
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400491 u32 ofs = pci_bar(pci, bar);
492 u16 bdf = pci->bdf;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200493 u32 old = pci_config_readl(bdf, ofs);
Alexey Korolev030288f2012-04-19 17:44:55 +1200494 int is64 = 0, type = PCI_REGION_TYPE_MEM;
495 u64 mask;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200496
497 if (bar == PCI_ROM_SLOT) {
498 mask = PCI_ROM_ADDRESS_MASK;
499 pci_config_writel(bdf, ofs, mask);
500 } else {
Alexey Korolev030288f2012-04-19 17:44:55 +1200501 if (old & PCI_BASE_ADDRESS_SPACE_IO) {
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200502 mask = PCI_BASE_ADDRESS_IO_MASK;
Alexey Korolev030288f2012-04-19 17:44:55 +1200503 type = PCI_REGION_TYPE_IO;
504 } else {
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200505 mask = PCI_BASE_ADDRESS_MEM_MASK;
Alexey Korolev030288f2012-04-19 17:44:55 +1200506 if (old & PCI_BASE_ADDRESS_MEM_PREFETCH)
507 type = PCI_REGION_TYPE_PREFMEM;
508 is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
509 == PCI_BASE_ADDRESS_MEM_TYPE_64);
510 }
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200511 pci_config_writel(bdf, ofs, ~0);
512 }
Alexey Korolev030288f2012-04-19 17:44:55 +1200513 u64 val = pci_config_readl(bdf, ofs);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200514 pci_config_writel(bdf, ofs, old);
Alexey Korolev030288f2012-04-19 17:44:55 +1200515 if (is64) {
516 u32 hold = pci_config_readl(bdf, ofs + 4);
517 pci_config_writel(bdf, ofs + 4, ~0);
518 u32 high = pci_config_readl(bdf, ofs + 4);
519 pci_config_writel(bdf, ofs + 4, hold);
520 val |= ((u64)high << 32);
521 mask |= ((u64)0xffffffff << 32);
522 *psize = (~(val & mask)) + 1;
523 } else {
524 *psize = ((~(val & mask)) + 1) & 0xffffffff;
525 }
526 *ptype = type;
527 *pis64 = is64;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200528}
529
Alexey Korolevac0cd582012-04-19 17:48:54 +1200530static int pci_bios_bridge_region_is64(struct pci_region *r,
531 struct pci_device *pci, int type)
532{
533 if (type != PCI_REGION_TYPE_PREFMEM)
534 return 0;
535 u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
536 if (!pmem) {
537 pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0);
538 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
539 pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0);
540 }
541 if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64)
542 return 0;
Kevin O'Connora88c1972013-06-08 21:51:46 -0400543 struct pci_region_entry *entry;
544 hlist_for_each_entry(entry, &r->list, node) {
Alexey Korolevac0cd582012-04-19 17:48:54 +1200545 if (!entry->is64)
546 return 0;
Alexey Korolevac0cd582012-04-19 17:48:54 +1200547 }
548 return 1;
549}
550
Alexey Korolev37c111f2012-04-26 16:51:05 +1200551static u64 pci_region_align(struct pci_region *r)
552{
Kevin O'Connora88c1972013-06-08 21:51:46 -0400553 struct pci_region_entry *entry;
554 hlist_for_each_entry(entry, &r->list, node) {
555 // The first entry in the sorted list has the largest alignment
556 return entry->align;
557 }
558 return 1;
Alexey Korolev37c111f2012-04-26 16:51:05 +1200559}
560
561static u64 pci_region_sum(struct pci_region *r)
562{
Alexey Korolev37c111f2012-04-26 16:51:05 +1200563 u64 sum = 0;
Kevin O'Connora88c1972013-06-08 21:51:46 -0400564 struct pci_region_entry *entry;
565 hlist_for_each_entry(entry, &r->list, node) {
Alexey Korolev37c111f2012-04-26 16:51:05 +1200566 sum += entry->size;
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400567 }
568 return sum;
Alexey Korolev37c111f2012-04-26 16:51:05 +1200569}
570
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200571static void pci_region_migrate_64bit_entries(struct pci_region *from,
572 struct pci_region *to)
573{
Kevin O'Connor030a58a2013-06-13 21:24:14 -0400574 struct hlist_node *n, **last = &to->list.first;
Kevin O'Connora88c1972013-06-08 21:51:46 -0400575 struct pci_region_entry *entry;
Kevin O'Connor030a58a2013-06-13 21:24:14 -0400576 hlist_for_each_entry_safe(entry, n, &from->list, node) {
Kevin O'Connora88c1972013-06-08 21:51:46 -0400577 if (!entry->is64)
Kevin O'Connord630d142012-04-26 22:20:56 -0400578 continue;
Kevin O'Connord630d142012-04-26 22:20:56 -0400579 // Move from source list to destination list.
Kevin O'Connora88c1972013-06-08 21:51:46 -0400580 hlist_del(&entry->node);
581 hlist_add(&entry->node, last);
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200582 }
583}
584
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200585static struct pci_region_entry *
586pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
Alexey Korolev030288f2012-04-19 17:44:55 +1200587 int bar, u64 size, u64 align, int type, int is64)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200588{
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200589 struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
590 if (!entry) {
591 warn_noalloc();
592 return NULL;
593 }
594 memset(entry, 0, sizeof(*entry));
595 entry->dev = dev;
596 entry->bar = bar;
597 entry->size = size;
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400598 entry->align = align;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200599 entry->is64 = is64;
600 entry->type = type;
601 // Insert into list in sorted order.
Kevin O'Connora88c1972013-06-08 21:51:46 -0400602 struct hlist_node **pprev;
603 struct pci_region_entry *pos;
Kevin O'Connor030a58a2013-06-13 21:24:14 -0400604 hlist_for_each_entry_pprev(pos, pprev, &bus->r[type].list, node) {
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400605 if (pos->align < align || (pos->align == align && pos->size < size))
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200606 break;
607 }
Kevin O'Connora88c1972013-06-08 21:51:46 -0400608 hlist_add(&entry->node, pprev);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200609 return entry;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200610}
611
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200612static int pci_bios_check_devices(struct pci_bus *busses)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200613{
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400614 dprintf(1, "PCI: check devices\n");
615
616 // Calculate resources needed for regular (non-bus) devices.
617 struct pci_device *pci;
618 foreachpci(pci) {
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200619 if (pci->class == PCI_CLASS_BRIDGE_PCI)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400620 busses[pci->secondary_bus].bus_dev = pci;
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200621
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400622 struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)];
623 int i;
624 for (i = 0; i < PCI_NUM_REGIONS; i++) {
Alexey Korolev1a9f47f2012-04-19 17:40:13 +1200625 if ((pci->class == PCI_CLASS_BRIDGE_PCI) &&
626 (i >= PCI_BRIDGE_NUM_REGIONS && i < PCI_ROM_SLOT))
627 continue;
Alexey Korolev030288f2012-04-19 17:44:55 +1200628 int type, is64;
629 u64 size;
630 pci_bios_get_bar(pci, i, &type, &size, &is64);
631 if (size == 0)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400632 continue;
633
Alexey Korolev5fa24b52012-04-18 17:31:58 +1200634 if (type != PCI_REGION_TYPE_IO && size < PCI_DEVICE_MEM_MIN)
635 size = PCI_DEVICE_MEM_MIN;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200636 struct pci_region_entry *entry = pci_region_create_entry(
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400637 bus, pci, i, size, size, type, is64);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200638 if (!entry)
639 return -1;
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400640
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200641 if (is64)
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400642 i++;
643 }
644 }
645
646 // Propagate required bus resources to parent busses.
647 int secondary_bus;
648 for (secondary_bus=MaxPCIBus; secondary_bus>0; secondary_bus--) {
649 struct pci_bus *s = &busses[secondary_bus];
650 if (!s->bus_dev)
651 continue;
652 struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
Kevin O'Connorcbbdcf22011-10-01 13:13:29 -0400653 int type;
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200654 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
Alexey Korolev030288f2012-04-19 17:44:55 +1200655 u64 align = (type == PCI_REGION_TYPE_IO) ?
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200656 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
Alexey Korolev37c111f2012-04-26 16:51:05 +1200657 if (pci_region_align(&s->r[type]) > align)
658 align = pci_region_align(&s->r[type]);
659 u64 sum = pci_region_sum(&s->r[type]);
660 u64 size = ALIGN(sum, align);
Alexey Korolevac0cd582012-04-19 17:48:54 +1200661 int is64 = pci_bios_bridge_region_is64(&s->r[type],
662 s->bus_dev, type);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200663 // entry->bar is -1 if the entry represents a bridge region
664 struct pci_region_entry *entry = pci_region_create_entry(
Alexey Korolevac0cd582012-04-19 17:48:54 +1200665 parent, s->bus_dev, -1, size, align, type, is64);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200666 if (!entry)
667 return -1;
Alexey Korolev030288f2012-04-19 17:44:55 +1200668 dprintf(1, "PCI: secondary bus %d size %08llx type %s\n",
Alexey Korolevf3c2b062012-04-18 17:26:43 +1200669 entry->dev->secondary_bus, size,
670 region_type_name[entry->type]);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200671 }
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400672 }
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200673 return 0;
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400674}
675
Kevin O'Connore5d71ca2012-04-26 22:04:34 -0400676
677/****************************************************************
678 * BAR assignment
679 ****************************************************************/
680
Kevin O'Connora8dcc5b2011-10-01 12:08:57 -0400681// Setup region bases (given the regions' size and alignment)
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200682static int pci_bios_init_root_regions(struct pci_bus *bus)
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400683{
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400684 bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
685
Alexey Korolev37c111f2012-04-26 16:51:05 +1200686 struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
687 struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
688
689 if (pci_region_align(r_start) < pci_region_align(r_end)) {
Kevin O'Connor3d1bc9d2012-04-01 12:30:32 -0400690 // Swap regions to improve alignment.
Alexey Korolev37c111f2012-04-26 16:51:05 +1200691 r_end = r_start;
692 r_start = &bus->r[PCI_REGION_TYPE_PREFMEM];
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400693 }
Alexey Korolev37c111f2012-04-26 16:51:05 +1200694 u64 sum = pci_region_sum(r_end);
695 u64 align = pci_region_align(r_end);
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +0200696 r_end->base = ALIGN_DOWN((pcimem_end - sum), align);
Alexey Korolev37c111f2012-04-26 16:51:05 +1200697 sum = pci_region_sum(r_start);
698 align = pci_region_align(r_start);
699 r_start->base = ALIGN_DOWN((r_end->base - sum), align);
700
Gerd Hoffmanne55c4e82012-06-07 10:34:32 +0200701 if ((r_start->base < pcimem_start) ||
702 (r_start->base > pcimem_end))
Kevin O'Connora8dcc5b2011-10-01 12:08:57 -0400703 // Memory range requested is larger than available.
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200704 return -1;
705 return 0;
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400706}
707
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400708#define PCI_IO_SHIFT 8
709#define PCI_MEMORY_SHIFT 16
710#define PCI_PREF_MEMORY_SHIFT 16
711
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200712static void
Alexey Korolev35a770f2012-04-19 17:47:19 +1200713pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr)
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200714{
715 u16 bdf = entry->dev->bdf;
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200716 if (entry->bar >= 0) {
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200717 dprintf(1, "PCI: map device bdf=%02x:%02x.%x"
Alexey Korolev030288f2012-04-19 17:44:55 +1200718 " bar %d, addr %08llx, size %08llx [%s]\n",
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200719 pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
720 entry->bar, addr, entry->size, region_type_name[entry->type]);
721
Alexey Korolev030288f2012-04-19 17:44:55 +1200722 pci_set_io_region_addr(entry->dev, entry->bar, addr, entry->is64);
Alexey Korolev3a297162012-04-18 17:22:29 +1200723 return;
724 }
725
Alexey Korolev030288f2012-04-19 17:44:55 +1200726 u64 limit = addr + entry->size - 1;
Alexey Korolev3a297162012-04-18 17:22:29 +1200727 if (entry->type == PCI_REGION_TYPE_IO) {
728 pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT);
729 pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
730 pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
731 pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
732 }
733 if (entry->type == PCI_REGION_TYPE_MEM) {
734 pci_config_writew(bdf, PCI_MEMORY_BASE, addr >> PCI_MEMORY_SHIFT);
735 pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> PCI_MEMORY_SHIFT);
736 }
737 if (entry->type == PCI_REGION_TYPE_PREFMEM) {
738 pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, addr >> PCI_PREF_MEMORY_SHIFT);
739 pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> PCI_PREF_MEMORY_SHIFT);
Alexey Korolev030288f2012-04-19 17:44:55 +1200740 pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, addr >> 32);
741 pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit >> 32);
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200742 }
743}
744
Alexey Korolev35a770f2012-04-19 17:47:19 +1200745static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
746{
Kevin O'Connor030a58a2013-06-13 21:24:14 -0400747 struct hlist_node *n;
Kevin O'Connora88c1972013-06-08 21:51:46 -0400748 struct pci_region_entry *entry;
Kevin O'Connor030a58a2013-06-13 21:24:14 -0400749 hlist_for_each_entry_safe(entry, n, &r->list, node) {
Alexey Korolev35a770f2012-04-19 17:47:19 +1200750 u64 addr = r->base;
751 r->base += entry->size;
752 if (entry->bar == -1)
753 // Update bus base address if entry is a bridge region
754 busses[entry->dev->secondary_bus].r[entry->type].base = addr;
755 pci_region_map_one_entry(entry, addr);
Kevin O'Connora88c1972013-06-08 21:51:46 -0400756 hlist_del(&entry->node);
Alexey Korolev35a770f2012-04-19 17:47:19 +1200757 free(entry);
Alexey Korolev35a770f2012-04-19 17:47:19 +1200758 }
759}
760
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400761static void pci_bios_map_devices(struct pci_bus *busses)
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200762{
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200763 if (pci_bios_init_root_regions(busses)) {
764 struct pci_region r64_mem, r64_pref;
Kevin O'Connora88c1972013-06-08 21:51:46 -0400765 r64_mem.list.first = NULL;
766 r64_pref.list.first = NULL;
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200767 pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
768 &r64_mem);
769 pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
770 &r64_pref);
771
772 if (pci_bios_init_root_regions(busses))
773 panic("PCI: out of 32bit address space\n");
774
Gerd Hoffmann5283b2e2012-06-12 09:27:15 +0200775 u64 sum_mem = pci_region_sum(&r64_mem);
776 u64 sum_pref = pci_region_sum(&r64_pref);
777 u64 align_mem = pci_region_align(&r64_mem);
778 u64 align_pref = pci_region_align(&r64_pref);
779
780 r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem);
781 r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref);
782 pcimem64_start = r64_mem.base;
783 pcimem64_end = r64_pref.base + sum_pref;
784
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200785 pci_region_map_entries(busses, &r64_mem);
786 pci_region_map_entries(busses, &r64_pref);
Gerd Hoffmann5283b2e2012-06-12 09:27:15 +0200787 } else {
788 // no bars mapped high -> drop 64bit window (see dsdt)
789 pcimem64_start = 0;
Alexey Koroleve5e5f962012-04-26 17:01:59 +1200790 }
Kevin O'Connor2c4c2112011-10-15 11:42:48 -0400791 // Map regions on each device.
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200792 int bus;
793 for (bus = 0; bus<=MaxPCIBus; bus++) {
794 int type;
Alexey Korolev35a770f2012-04-19 17:47:19 +1200795 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++)
796 pci_region_map_entries(busses, &busses[bus].r[type]);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200797 }
798}
799
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200800
Kevin O'Connor5bab7e62011-10-01 11:33:31 -0400801/****************************************************************
802 * Main setup code
803 ****************************************************************/
Isaku Yamahataf4416662010-06-22 17:57:52 +0900804
Kevin O'Connor0525d292008-07-04 06:18:30 -0400805void
Kevin O'Connor40f5b5a2009-09-13 10:46:57 -0400806pci_setup(void)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400807{
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500808 if (!CONFIG_QEMU)
Kevin O'Connor0525d292008-07-04 06:18:30 -0400809 return;
810
Kevin O'Connor40f5b5a2009-09-13 10:46:57 -0400811 dprintf(3, "pci setup\n");
812
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200813 dprintf(1, "=== PCI bus & bridge init ===\n");
Jan Kiszka58e6b3f2011-09-21 08:16:21 +0200814 if (pci_probe_host() != 0) {
815 return;
816 }
Isaku Yamahataf4416662010-06-22 17:57:52 +0900817 pci_bios_init_bus();
818
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200819 dprintf(1, "=== PCI device probing ===\n");
Jan Kiszka58e6b3f2011-09-21 08:16:21 +0200820 pci_probe_devices();
Kevin O'Connor37956dd2011-06-21 22:22:58 -0400821
Kevin O'Connorb1c35f22012-11-26 11:05:32 -0500822 pcimem_start = RamSize;
823 pci_bios_init_platform();
824
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200825 dprintf(1, "=== PCI new allocation pass #1 ===\n");
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400826 struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1));
Kevin O'Connor28a20e12011-10-15 11:07:30 -0400827 if (!busses) {
828 warn_noalloc();
829 return;
830 }
831 memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
Alexey Korolevfa51bcd2012-04-18 17:21:19 +1200832 if (pci_bios_check_devices(busses))
833 return;
834
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200835 dprintf(1, "=== PCI new allocation pass #2 ===\n");
Kevin O'Connorb725dcb2011-10-15 11:53:38 -0400836 pci_bios_map_devices(busses);
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200837
Kevin O'Connor3f2288f2011-10-15 12:02:14 -0400838 pci_bios_init_devices();
Gerd Hoffmann8e301472011-08-09 17:22:42 +0200839
Gerd Hoffmann82b39b22011-07-11 09:20:28 +0200840 free(busses);
Alex Williamson7adfd712013-03-20 10:58:47 -0600841
842 pci_enable_default_vga();
Kevin O'Connor0525d292008-07-04 06:18:30 -0400843}