]>
Commit | Line | Data |
---|---|---|
a65b25d1 BM |
1 | /* |
2 | * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <pci.h> | |
9c4f5412 | 9 | #include <pci_rom.h> |
cc7debc7 | 10 | #include <asm/pci.h> |
0fcb7acf | 11 | #include <asm/arch/device.h> |
cc7debc7 | 12 | #include <asm/arch/qemu.h> |
a65b25d1 BM |
13 | |
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
a8ebf283 BM |
16 | static bool i440fx; |
17 | ||
a65b25d1 BM |
18 | void board_pci_setup_hose(struct pci_controller *hose) |
19 | { | |
20 | hose->first_busno = 0; | |
21 | hose->last_busno = 0; | |
22 | ||
23 | /* PCI memory space */ | |
24 | pci_set_region(hose->regions + 0, | |
25 | CONFIG_PCI_MEM_BUS, | |
26 | CONFIG_PCI_MEM_PHYS, | |
27 | CONFIG_PCI_MEM_SIZE, | |
28 | PCI_REGION_MEM); | |
29 | ||
30 | /* PCI IO space */ | |
31 | pci_set_region(hose->regions + 1, | |
32 | CONFIG_PCI_IO_BUS, | |
33 | CONFIG_PCI_IO_PHYS, | |
34 | CONFIG_PCI_IO_SIZE, | |
35 | PCI_REGION_IO); | |
36 | ||
37 | pci_set_region(hose->regions + 2, | |
38 | CONFIG_PCI_PREF_BUS, | |
39 | CONFIG_PCI_PREF_PHYS, | |
40 | CONFIG_PCI_PREF_SIZE, | |
41 | PCI_REGION_PREFETCH); | |
42 | ||
43 | pci_set_region(hose->regions + 3, | |
44 | 0, | |
45 | 0, | |
46 | gd->ram_size, | |
47 | PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); | |
48 | ||
49 | hose->region_count = 4; | |
50 | } | |
51 | ||
52 | int board_pci_post_scan(struct pci_controller *hose) | |
53 | { | |
9c4f5412 | 54 | int ret = 0; |
e7cd070d | 55 | u16 device, xbcs; |
cc7debc7 | 56 | int pam, i; |
4be2f42b BM |
57 | pci_dev_t vga; |
58 | ulong start; | |
9c4f5412 | 59 | |
cc7debc7 BM |
60 | /* |
61 | * i440FX and Q35 chipset have different PAM register offset, but with | |
62 | * the same bitfield layout. Here we determine the offset based on its | |
63 | * PCI device ID. | |
64 | */ | |
65 | device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); | |
a8ebf283 BM |
66 | i440fx = (device == PCI_DEVICE_ID_INTEL_82441); |
67 | pam = i440fx ? I440FX_PAM : Q35_PAM; | |
cc7debc7 BM |
68 | |
69 | /* | |
70 | * Initialize Programmable Attribute Map (PAM) Registers | |
71 | * | |
72 | * Configure legacy segments C/D/E/F to system RAM | |
73 | */ | |
74 | for (i = 0; i < PAM_NUM; i++) | |
75 | x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW); | |
76 | ||
a8ebf283 | 77 | if (i440fx) { |
0fcb7acf BM |
78 | /* |
79 | * Enable legacy IDE I/O ports decode | |
80 | * | |
81 | * Note: QEMU always decode legacy IDE I/O port on PIIX chipset. | |
82 | * However Linux ata_piix driver does sanity check on these two | |
83 | * registers to see whether legacy ports decode is turned on. | |
84 | * This is to make Linux ata_piix driver happy. | |
85 | */ | |
86 | x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); | |
87 | x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); | |
e7cd070d BM |
88 | |
89 | /* Enable I/O APIC */ | |
90 | xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); | |
91 | xbcs |= APIC_EN; | |
92 | x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); | |
0fcb7acf BM |
93 | } |
94 | ||
4be2f42b BM |
95 | /* |
96 | * QEMU emulated graphic card shows in the PCI configuration space with | |
97 | * PCI vendor id and device id as an artificial pair 0x1234:0x1111. | |
98 | * It is on PCI bus 0, function 0, but device number is not consistent | |
99 | * for the two x86 targets it supports. For i440FX and PIIX chipset | |
100 | * board, it shows as device 2, while for Q35 and ICH9 chipset board, | |
101 | * it shows as device 1. | |
102 | */ | |
a8ebf283 | 103 | vga = i440fx ? I440FX_VGA : Q35_VGA; |
4be2f42b BM |
104 | start = get_timer(0); |
105 | ret = pci_run_vga_bios(vga, NULL, PCI_ROM_USE_NATIVE); | |
106 | debug("BIOS ran in %lums\n", get_timer(start)); | |
107 | ||
9c4f5412 | 108 | return ret; |
a65b25d1 | 109 | } |
a8ebf283 BM |
110 | |
111 | #ifdef CONFIG_GENERATE_MP_TABLE | |
112 | int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) | |
113 | { | |
114 | u8 irq; | |
115 | ||
116 | if (i440fx) { | |
117 | /* | |
118 | * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not | |
119 | * connected to I/O APIC INTPIN#16-19. Instead they are routed | |
120 | * to an irq number controled by the PIRQ routing register. | |
121 | */ | |
122 | irq = x86_pci_read_config8(PCI_BDF(bus, dev, func), | |
123 | PCI_INTERRUPT_LINE); | |
124 | } else { | |
125 | /* | |
126 | * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7. | |
127 | * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11]. | |
128 | */ | |
129 | irq = pirq < 8 ? pirq + 16 : pirq + 12; | |
130 | } | |
131 | ||
132 | return irq; | |
133 | } | |
134 | #endif |