blob: e846ccd44aa53c16f7e47317c3a8bb17c4adfc65 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Bin Meng2229c4c2015-05-07 21:34:08 +08002/*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
Bin Meng2229c4c2015-05-07 21:34:08 +08004 */
5
Simon Glass1fa70f82019-11-14 12:57:34 -07006#include <cpu_func.h>
Simon Glass97589732020-05-10 11:40:02 -06007#include <init.h>
Bin Meng5fecada2016-02-01 01:40:56 -08008#include <pci.h>
Miao Yan92106272016-05-22 19:37:17 -07009#include <qfw.h>
Asherah Connor4ffa95d2021-03-19 18:21:40 +110010#include <dm/platdata.h>
Bin Mengef37e7b2015-06-03 09:20:06 +080011#include <asm/irq.h>
Bin Meng2229c4c2015-05-07 21:34:08 +080012#include <asm/post.h>
13#include <asm/processor.h>
Bin Menge456f2b2015-11-06 02:04:49 -080014#include <asm/arch/device.h>
15#include <asm/arch/qemu.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060016#include <asm/u-boot-x86.h>
Bin Menge456f2b2015-11-06 02:04:49 -080017
Asherah Connor4ffa95d2021-03-19 18:21:40 +110018#if CONFIG_IS_ENABLED(QFW_PIO)
19U_BOOT_DRVINFO(x86_qfw_pio) = {
20 .name = "qfw_pio",
Miao Yan8a153832016-05-22 19:37:15 -070021};
22#endif
23
Simon Glass54545e62025-03-15 14:25:26 +000024static 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
Miao Yan35603ff2016-01-20 01:57:05 -080033static void enable_pm_piix(void)
34{
35 u8 en;
36 u16 cmd;
37
38 /* Set the PM I/O base */
Bin Meng5fecada2016-02-01 01:40:56 -080039 pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
Miao Yan35603ff2016-01-20 01:57:05 -080040
41 /* Enable access to the PM I/O space */
Bin Meng5fecada2016-02-01 01:40:56 -080042 pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
Miao Yan35603ff2016-01-20 01:57:05 -080043 cmd |= PCI_COMMAND_IO;
Bin Meng5fecada2016-02-01 01:40:56 -080044 pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
Miao Yan35603ff2016-01-20 01:57:05 -080045
46 /* PM I/O Space Enable (PMIOSE) */
Bin Meng5fecada2016-02-01 01:40:56 -080047 pci_read_config8(PIIX_PM, PMREGMISC, &en);
Miao Yan35603ff2016-01-20 01:57:05 -080048 en |= PMIOSE;
Bin Meng5fecada2016-02-01 01:40:56 -080049 pci_write_config8(PIIX_PM, PMREGMISC, en);
Miao Yan35603ff2016-01-20 01:57:05 -080050}
51
52static void enable_pm_ich9(void)
53{
54 /* Set the PM I/O base */
Bin Meng5fecada2016-02-01 01:40:56 -080055 pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
Miao Yan35603ff2016-01-20 01:57:05 -080056}
57
Simon Glass7dc0a452023-07-30 11:16:01 -060058void qemu_chipset_init(void)
Bin Menge456f2b2015-11-06 02:04:49 -080059{
Simon Glass54545e62025-03-15 14:25:26 +000060 bool i440fx;
61 u16 xbcs;
Bin Menge456f2b2015-11-06 02:04:49 -080062 int pam, i;
63
Simon Glass54545e62025-03-15 14:25:26 +000064 i440fx = is_i440fx();
65
Bin Menge456f2b2015-11-06 02:04:49 -080066 /*
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 */
Bin Menge456f2b2015-11-06 02:04:49 -080071 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++)
Bin Meng5fecada2016-02-01 01:40:56 -080079 pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
Bin Menge456f2b2015-11-06 02:04:49 -080080
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 */
Bin Meng5fecada2016-02-01 01:40:56 -080090 pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
91 pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
Bin Menge456f2b2015-11-06 02:04:49 -080092
93 /* Enable I/O APIC */
Bin Meng5fecada2016-02-01 01:40:56 -080094 pci_read_config16(PIIX_ISA, XBCS, &xbcs);
Bin Menge456f2b2015-11-06 02:04:49 -080095 xbcs |= APIC_EN;
Bin Meng5fecada2016-02-01 01:40:56 -080096 pci_write_config16(PIIX_ISA, XBCS, xbcs);
Miao Yan35603ff2016-01-20 01:57:05 -080097
98 enable_pm_piix();
Bin Menge456f2b2015-11-06 02:04:49 -080099 } else {
100 /* Configure PCIe ECAM base address */
Bin Meng5fecada2016-02-01 01:40:56 -0800101 pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
102 CONFIG_PCIE_ECAM_BASE | BAR_EN);
Miao Yan35603ff2016-01-20 01:57:05 -0800103
104 enable_pm_ich9();
Bin Menge456f2b2015-11-06 02:04:49 -0800105 }
106}
Bin Meng2229c4c2015-05-07 21:34:08 +0800107
Troy Kiskyc321bb22023-03-13 14:31:33 -0700108#if CONFIG_IS_ENABLED(X86_32BIT_INIT)
Bin Meng2229c4c2015-05-07 21:34:08 +0800109int arch_cpu_init(void)
110{
Bin Meng2229c4c2015-05-07 21:34:08 +0800111 post_code(POST_CPU_INIT);
Bin Meng2229c4c2015-05-07 21:34:08 +0800112
Masahiro Yamada17103212016-09-06 22:17:36 +0900113 return x86_cpu_init_f();
Bin Meng2229c4c2015-05-07 21:34:08 +0800114}
Simon Glassee7c36f2017-03-28 10:27:30 -0600115
116int checkcpu(void)
117{
118 return 0;
119}
Simon Glass752f9762015-08-04 12:34:03 -0600120#endif
Bin Meng2229c4c2015-05-07 21:34:08 +0800121
Bin Menge456f2b2015-11-06 02:04:49 -0800122int arch_early_init_r(void)
123{
124 qemu_chipset_init();
125
126 return 0;
127}
128
Bin Menge456f2b2015-11-06 02:04:49 -0800129#ifdef CONFIG_GENERATE_MP_TABLE
130int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
131{
132 u8 irq;
133
Simon Glass54545e62025-03-15 14:25:26 +0000134 if (is_i440fx()) {
Bin Menge456f2b2015-11-06 02:04:49 -0800135 /*
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 */
Bin Meng5fecada2016-02-01 01:40:56 -0800140 pci_read_config8(PCI_BDF(bus, dev, func),
141 PCI_INTERRUPT_LINE, &irq);
Bin Menge456f2b2015-11-06 02:04:49 -0800142 } 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