xref: /openbmc/u-boot/arch/x86/cpu/qemu/qemu.c (revision fcf5c04193b48c3f5e2d337a85d28c4026f90ac3)
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>
86039200cSBin Meng #include <pci.h>
9dd6f3abbSTom Rini #include <qemu_fw_cfg.h>
105c564226SBin Meng #include <asm/irq.h>
11a65b25d1SBin Meng #include <asm/post.h>
12a65b25d1SBin Meng #include <asm/processor.h>
1348748595SBin Meng #include <asm/arch/device.h>
1448748595SBin Meng #include <asm/arch/qemu.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 */
246039200cSBin Meng 	pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
25a3b15a05SMiao Yan 
26a3b15a05SMiao Yan 	/* Enable access to the PM I/O space */
276039200cSBin Meng 	pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
28a3b15a05SMiao Yan 	cmd |= PCI_COMMAND_IO;
296039200cSBin Meng 	pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
30a3b15a05SMiao Yan 
31a3b15a05SMiao Yan 	/* PM I/O Space Enable (PMIOSE) */
326039200cSBin Meng 	pci_read_config8(PIIX_PM, PMREGMISC, &en);
33a3b15a05SMiao Yan 	en |= PMIOSE;
346039200cSBin 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 */
406039200cSBin 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 	 */
536039200cSBin 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++)
636039200cSBin 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 		 */
746039200cSBin Meng 		pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
756039200cSBin Meng 		pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
7648748595SBin Meng 
7748748595SBin Meng 		/* Enable I/O APIC */
786039200cSBin Meng 		pci_read_config16(PIIX_ISA, XBCS, &xbcs);
7948748595SBin Meng 		xbcs |= APIC_EN;
806039200cSBin 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 */
856039200cSBin 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 
91*fcf5c041SMiao Yan #ifdef CONFIG_QFW
92f60df20aSMiao Yan 	qemu_fwcfg_init();
93*fcf5c041SMiao Yan #endif
9448748595SBin Meng }
95a65b25d1SBin Meng 
96a65b25d1SBin Meng int arch_cpu_init(void)
97a65b25d1SBin Meng {
98a65b25d1SBin Meng 	int ret;
99a65b25d1SBin Meng 
100a65b25d1SBin Meng 	post_code(POST_CPU_INIT);
101a65b25d1SBin Meng 
102a65b25d1SBin Meng 	ret = x86_cpu_init_f();
103a65b25d1SBin Meng 	if (ret)
104a65b25d1SBin Meng 		return ret;
105a65b25d1SBin Meng 
106a65b25d1SBin Meng 	return 0;
107a65b25d1SBin Meng }
108a65b25d1SBin Meng 
109eeae5100SSimon Glass #ifndef CONFIG_EFI_STUB
110a65b25d1SBin Meng int print_cpuinfo(void)
111a65b25d1SBin Meng {
112a65b25d1SBin Meng 	post_code(POST_CPU_INFO);
113a65b25d1SBin Meng 	return default_print_cpuinfo();
114a65b25d1SBin Meng }
115eeae5100SSimon Glass #endif
116a65b25d1SBin Meng 
117a65b25d1SBin Meng void reset_cpu(ulong addr)
118a65b25d1SBin Meng {
119a65b25d1SBin Meng 	/* cold reset */
120a65b25d1SBin Meng 	x86_full_reset();
121a65b25d1SBin Meng }
1225c564226SBin Meng 
12348748595SBin Meng int arch_early_init_r(void)
12448748595SBin Meng {
12548748595SBin Meng 	qemu_chipset_init();
12648748595SBin Meng 
12748748595SBin Meng 	return 0;
12848748595SBin Meng }
12948748595SBin Meng 
13048748595SBin Meng #ifdef CONFIG_GENERATE_MP_TABLE
13148748595SBin Meng int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
13248748595SBin Meng {
13348748595SBin Meng 	u8 irq;
13448748595SBin Meng 
13548748595SBin Meng 	if (i440fx) {
13648748595SBin Meng 		/*
13748748595SBin Meng 		 * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
13848748595SBin Meng 		 * connected to I/O APIC INTPIN#16-19. Instead they are routed
13948748595SBin Meng 		 * to an irq number controled by the PIRQ routing register.
14048748595SBin Meng 		 */
1416039200cSBin Meng 		pci_read_config8(PCI_BDF(bus, dev, func),
1426039200cSBin Meng 				 PCI_INTERRUPT_LINE, &irq);
14348748595SBin Meng 	} else {
14448748595SBin Meng 		/*
14548748595SBin Meng 		 * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
14648748595SBin Meng 		 * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
14748748595SBin Meng 		 */
14848748595SBin Meng 		irq = pirq < 8 ? pirq + 16 : pirq + 12;
14948748595SBin Meng 	}
15048748595SBin Meng 
15148748595SBin Meng 	return irq;
15248748595SBin Meng }
15348748595SBin Meng #endif
154