1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
4 */
5
6 #include <cpu_func.h>
7 #include <init.h>
8 #include <pci.h>
9 #include <qfw.h>
10 #include <dm/platdata.h>
11 #include <asm/irq.h>
12 #include <asm/post.h>
13 #include <asm/processor.h>
14 #include <asm/arch/device.h>
15 #include <asm/arch/qemu.h>
16 #include <asm/u-boot-x86.h>
17
18 #if CONFIG_IS_ENABLED(QFW_PIO)
19 U_BOOT_DRVINFO(x86_qfw_pio) = {
20 .name = "qfw_pio",
21 };
22 #endif
23
is_i440fx(void)24 static bool is_i440fx(void)
25 {
26 u16 device;
27
28 pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
29
30 return device == PCI_DEVICE_ID_INTEL_82441;
31 }
32
enable_pm_piix(void)33 static void enable_pm_piix(void)
34 {
35 u8 en;
36 u16 cmd;
37
38 /* Set the PM I/O base */
39 pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
40
41 /* Enable access to the PM I/O space */
42 pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
43 cmd |= PCI_COMMAND_IO;
44 pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
45
46 /* PM I/O Space Enable (PMIOSE) */
47 pci_read_config8(PIIX_PM, PMREGMISC, &en);
48 en |= PMIOSE;
49 pci_write_config8(PIIX_PM, PMREGMISC, en);
50 }
51
enable_pm_ich9(void)52 static void enable_pm_ich9(void)
53 {
54 /* Set the PM I/O base */
55 pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
56 }
57
qemu_chipset_init(void)58 void qemu_chipset_init(void)
59 {
60 bool i440fx;
61 u16 xbcs;
62 int pam, i;
63
64 i440fx = is_i440fx();
65
66 /*
67 * i440FX and Q35 chipset have different PAM register offset, but with
68 * the same bitfield layout. Here we determine the offset based on its
69 * PCI device ID.
70 */
71 pam = i440fx ? I440FX_PAM : Q35_PAM;
72
73 /*
74 * Initialize Programmable Attribute Map (PAM) Registers
75 *
76 * Configure legacy segments C/D/E/F to system RAM
77 */
78 for (i = 0; i < PAM_NUM; i++)
79 pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
80
81 if (i440fx) {
82 /*
83 * Enable legacy IDE I/O ports decode
84 *
85 * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
86 * However Linux ata_piix driver does sanity check on these two
87 * registers to see whether legacy ports decode is turned on.
88 * This is to make Linux ata_piix driver happy.
89 */
90 pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
91 pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
92
93 /* Enable I/O APIC */
94 pci_read_config16(PIIX_ISA, XBCS, &xbcs);
95 xbcs |= APIC_EN;
96 pci_write_config16(PIIX_ISA, XBCS, xbcs);
97
98 enable_pm_piix();
99 } else {
100 /* Configure PCIe ECAM base address */
101 pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
102 CONFIG_PCIE_ECAM_BASE | BAR_EN);
103
104 enable_pm_ich9();
105 }
106 }
107
108 #if CONFIG_IS_ENABLED(X86_32BIT_INIT)
arch_cpu_init(void)109 int arch_cpu_init(void)
110 {
111 post_code(POST_CPU_INIT);
112
113 return x86_cpu_init_f();
114 }
115
checkcpu(void)116 int checkcpu(void)
117 {
118 return 0;
119 }
120 #endif
121
arch_early_init_r(void)122 int arch_early_init_r(void)
123 {
124 qemu_chipset_init();
125
126 return 0;
127 }
128
129 #ifdef CONFIG_GENERATE_MP_TABLE
mp_determine_pci_dstirq(int bus,int dev,int func,int pirq)130 int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
131 {
132 u8 irq;
133
134 if (is_i440fx()) {
135 /*
136 * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
137 * connected to I/O APIC INTPIN#16-19. Instead they are routed
138 * to an irq number controled by the PIRQ routing register.
139 */
140 pci_read_config8(PCI_BDF(bus, dev, func),
141 PCI_INTERRUPT_LINE, &irq);
142 } else {
143 /*
144 * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
145 * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
146 */
147 irq = pirq < 8 ? pirq + 16 : pirq + 12;
148 }
149
150 return irq;
151 }
152 #endif
153