xref: /openbmc/u-boot/arch/x86/cpu/qemu/qemu.c (revision 6039200c65e645c81032e0fe20f036f83bbc1c46)
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>
8*6039200cSBin Meng #include <pci.h>
95c564226SBin Meng #include <asm/irq.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 
18a3b15a05SMiao Yan static void enable_pm_piix(void)
19a3b15a05SMiao Yan {
20a3b15a05SMiao Yan 	u8 en;
21a3b15a05SMiao Yan 	u16 cmd;
22a3b15a05SMiao Yan 
23a3b15a05SMiao Yan 	/* Set the PM I/O base */
24*6039200cSBin Meng 	pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
25a3b15a05SMiao Yan 
26a3b15a05SMiao Yan 	/* Enable access to the PM I/O space */
27*6039200cSBin Meng 	pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
28a3b15a05SMiao Yan 	cmd |= PCI_COMMAND_IO;
29*6039200cSBin Meng 	pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
30a3b15a05SMiao Yan 
31a3b15a05SMiao Yan 	/* PM I/O Space Enable (PMIOSE) */
32*6039200cSBin Meng 	pci_read_config8(PIIX_PM, PMREGMISC, &en);
33a3b15a05SMiao Yan 	en |= PMIOSE;
34*6039200cSBin Meng 	pci_write_config8(PIIX_PM, PMREGMISC, en);
35a3b15a05SMiao Yan }
36a3b15a05SMiao Yan 
37a3b15a05SMiao Yan static void enable_pm_ich9(void)
38a3b15a05SMiao Yan {
39a3b15a05SMiao Yan 	/* Set the PM I/O base */
40*6039200cSBin Meng 	pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
41a3b15a05SMiao Yan }
42a3b15a05SMiao 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 	 */
53*6039200cSBin Meng 	pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
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++)
63*6039200cSBin Meng 		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 		 */
74*6039200cSBin Meng 		pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
75*6039200cSBin Meng 		pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
7648748595SBin Meng 
7748748595SBin Meng 		/* Enable I/O APIC */
78*6039200cSBin Meng 		pci_read_config16(PIIX_ISA, XBCS, &xbcs);
7948748595SBin Meng 		xbcs |= APIC_EN;
80*6039200cSBin Meng 		pci_write_config16(PIIX_ISA, XBCS, xbcs);
81a3b15a05SMiao Yan 
82a3b15a05SMiao Yan 		enable_pm_piix();
8348748595SBin Meng 	} else {
8448748595SBin Meng 		/* Configure PCIe ECAM base address */
85*6039200cSBin Meng 		pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
8648748595SBin Meng 				   CONFIG_PCIE_ECAM_BASE | BAR_EN);
87a3b15a05SMiao Yan 
88a3b15a05SMiao 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 		 */
139*6039200cSBin Meng 		pci_read_config8(PCI_BDF(bus, dev, func),
140*6039200cSBin Meng 				 PCI_INTERRUPT_LINE, &irq);
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