xref: /openbmc/u-boot/arch/x86/cpu/qemu/qemu.c (revision a3b15a055662ea4a8db6b8f70aa870b541e0cda9)
1a65b25d1SBin Meng /*
2a65b25d1SBin Meng  * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
3a65b25d1SBin Meng  *
4a65b25d1SBin Meng  * SPDX-License-Identifier:	GPL-2.0+
5a65b25d1SBin Meng  */
6a65b25d1SBin Meng 
7a65b25d1SBin Meng #include <common.h>
85c564226SBin Meng #include <asm/irq.h>
948748595SBin Meng #include <asm/pci.h>
10a65b25d1SBin Meng #include <asm/post.h>
11a65b25d1SBin Meng #include <asm/processor.h>
1248748595SBin Meng #include <asm/arch/device.h>
1348748595SBin Meng #include <asm/arch/qemu.h>
14f60df20aSMiao Yan #include <asm/fw_cfg.h>
1548748595SBin Meng 
1648748595SBin Meng static bool i440fx;
1748748595SBin Meng 
18*a3b15a05SMiao Yan static void enable_pm_piix(void)
19*a3b15a05SMiao Yan {
20*a3b15a05SMiao Yan 	u8 en;
21*a3b15a05SMiao Yan 	u16 cmd;
22*a3b15a05SMiao Yan 
23*a3b15a05SMiao Yan 	/* Set the PM I/O base */
24*a3b15a05SMiao Yan 	x86_pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
25*a3b15a05SMiao Yan 
26*a3b15a05SMiao Yan 	/* Enable access to the PM I/O space */
27*a3b15a05SMiao Yan 	cmd = x86_pci_read_config16(PIIX_PM, PCI_COMMAND);
28*a3b15a05SMiao Yan 	cmd |= PCI_COMMAND_IO;
29*a3b15a05SMiao Yan 	x86_pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
30*a3b15a05SMiao Yan 
31*a3b15a05SMiao Yan 	/* PM I/O Space Enable (PMIOSE) */
32*a3b15a05SMiao Yan 	en = x86_pci_read_config8(PIIX_PM, PMREGMISC);
33*a3b15a05SMiao Yan 	en |= PMIOSE;
34*a3b15a05SMiao Yan 	x86_pci_write_config8(PIIX_PM, PMREGMISC, en);
35*a3b15a05SMiao Yan }
36*a3b15a05SMiao Yan 
37*a3b15a05SMiao Yan static void enable_pm_ich9(void)
38*a3b15a05SMiao Yan {
39*a3b15a05SMiao Yan 	/* Set the PM I/O base */
40*a3b15a05SMiao Yan 	x86_pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
41*a3b15a05SMiao Yan }
42*a3b15a05SMiao Yan 
4348748595SBin Meng static void qemu_chipset_init(void)
4448748595SBin Meng {
4548748595SBin Meng 	u16 device, xbcs;
4648748595SBin Meng 	int pam, i;
4748748595SBin Meng 
4848748595SBin Meng 	/*
4948748595SBin Meng 	 * i440FX and Q35 chipset have different PAM register offset, but with
5048748595SBin Meng 	 * the same bitfield layout. Here we determine the offset based on its
5148748595SBin Meng 	 * PCI device ID.
5248748595SBin Meng 	 */
5348748595SBin Meng 	device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID);
5448748595SBin Meng 	i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
5548748595SBin Meng 	pam = i440fx ? I440FX_PAM : Q35_PAM;
5648748595SBin Meng 
5748748595SBin Meng 	/*
5848748595SBin Meng 	 * Initialize Programmable Attribute Map (PAM) Registers
5948748595SBin Meng 	 *
6048748595SBin Meng 	 * Configure legacy segments C/D/E/F to system RAM
6148748595SBin Meng 	 */
6248748595SBin Meng 	for (i = 0; i < PAM_NUM; i++)
6348748595SBin Meng 		x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
6448748595SBin Meng 
6548748595SBin Meng 	if (i440fx) {
6648748595SBin Meng 		/*
6748748595SBin Meng 		 * Enable legacy IDE I/O ports decode
6848748595SBin Meng 		 *
6948748595SBin Meng 		 * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
7048748595SBin Meng 		 * However Linux ata_piix driver does sanity check on these two
7148748595SBin Meng 		 * registers to see whether legacy ports decode is turned on.
7248748595SBin Meng 		 * This is to make Linux ata_piix driver happy.
7348748595SBin Meng 		 */
7448748595SBin Meng 		x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
7548748595SBin Meng 		x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
7648748595SBin Meng 
7748748595SBin Meng 		/* Enable I/O APIC */
7848748595SBin Meng 		xbcs = x86_pci_read_config16(PIIX_ISA, XBCS);
7948748595SBin Meng 		xbcs |= APIC_EN;
8048748595SBin Meng 		x86_pci_write_config16(PIIX_ISA, XBCS, xbcs);
81*a3b15a05SMiao Yan 
82*a3b15a05SMiao Yan 		enable_pm_piix();
8348748595SBin Meng 	} else {
8448748595SBin Meng 		/* Configure PCIe ECAM base address */
8548748595SBin Meng 		x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
8648748595SBin Meng 				       CONFIG_PCIE_ECAM_BASE | BAR_EN);
87*a3b15a05SMiao Yan 
88*a3b15a05SMiao Yan 		enable_pm_ich9();
8948748595SBin Meng 	}
90f60df20aSMiao Yan 
91f60df20aSMiao Yan 	qemu_fwcfg_init();
9248748595SBin Meng }
93a65b25d1SBin Meng 
94a65b25d1SBin Meng int arch_cpu_init(void)
95a65b25d1SBin Meng {
96a65b25d1SBin Meng 	int ret;
97a65b25d1SBin Meng 
98a65b25d1SBin Meng 	post_code(POST_CPU_INIT);
99a65b25d1SBin Meng 
100a65b25d1SBin Meng 	ret = x86_cpu_init_f();
101a65b25d1SBin Meng 	if (ret)
102a65b25d1SBin Meng 		return ret;
103a65b25d1SBin Meng 
104a65b25d1SBin Meng 	return 0;
105a65b25d1SBin Meng }
106a65b25d1SBin Meng 
107eeae5100SSimon Glass #ifndef CONFIG_EFI_STUB
108a65b25d1SBin Meng int print_cpuinfo(void)
109a65b25d1SBin Meng {
110a65b25d1SBin Meng 	post_code(POST_CPU_INFO);
111a65b25d1SBin Meng 	return default_print_cpuinfo();
112a65b25d1SBin Meng }
113eeae5100SSimon Glass #endif
114a65b25d1SBin Meng 
115a65b25d1SBin Meng void reset_cpu(ulong addr)
116a65b25d1SBin Meng {
117a65b25d1SBin Meng 	/* cold reset */
118a65b25d1SBin Meng 	x86_full_reset();
119a65b25d1SBin Meng }
1205c564226SBin Meng 
12148748595SBin Meng int arch_early_init_r(void)
12248748595SBin Meng {
12348748595SBin Meng 	qemu_chipset_init();
12448748595SBin Meng 
12548748595SBin Meng 	return 0;
12648748595SBin Meng }
12748748595SBin Meng 
12848748595SBin Meng #ifdef CONFIG_GENERATE_MP_TABLE
12948748595SBin Meng int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
13048748595SBin Meng {
13148748595SBin Meng 	u8 irq;
13248748595SBin Meng 
13348748595SBin Meng 	if (i440fx) {
13448748595SBin Meng 		/*
13548748595SBin Meng 		 * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
13648748595SBin Meng 		 * connected to I/O APIC INTPIN#16-19. Instead they are routed
13748748595SBin Meng 		 * to an irq number controled by the PIRQ routing register.
13848748595SBin Meng 		 */
13948748595SBin Meng 		irq = x86_pci_read_config8(PCI_BDF(bus, dev, func),
14048748595SBin Meng 					   PCI_INTERRUPT_LINE);
14148748595SBin Meng 	} else {
14248748595SBin Meng 		/*
14348748595SBin Meng 		 * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
14448748595SBin Meng 		 * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
14548748595SBin Meng 		 */
14648748595SBin Meng 		irq = pirq < 8 ? pirq + 16 : pirq + 12;
14748748595SBin Meng 	}
14848748595SBin Meng 
14948748595SBin Meng 	return irq;
15048748595SBin Meng }
15148748595SBin Meng #endif
152