xref: /openbmc/u-boot/arch/x86/cpu/qemu/qemu.c (revision 487485956b1f980e8147283069a7af920f25a52c)
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>
9*48748595SBin Meng #include <asm/pci.h>
10a65b25d1SBin Meng #include <asm/post.h>
11a65b25d1SBin Meng #include <asm/processor.h>
12*48748595SBin Meng #include <asm/arch/device.h>
13*48748595SBin Meng #include <asm/arch/qemu.h>
14*48748595SBin Meng 
15*48748595SBin Meng static bool i440fx;
16*48748595SBin Meng 
17*48748595SBin Meng static void qemu_chipset_init(void)
18*48748595SBin Meng {
19*48748595SBin Meng 	u16 device, xbcs;
20*48748595SBin Meng 	int pam, i;
21*48748595SBin Meng 
22*48748595SBin Meng 	/*
23*48748595SBin Meng 	 * i440FX and Q35 chipset have different PAM register offset, but with
24*48748595SBin Meng 	 * the same bitfield layout. Here we determine the offset based on its
25*48748595SBin Meng 	 * PCI device ID.
26*48748595SBin Meng 	 */
27*48748595SBin Meng 	device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID);
28*48748595SBin Meng 	i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
29*48748595SBin Meng 	pam = i440fx ? I440FX_PAM : Q35_PAM;
30*48748595SBin Meng 
31*48748595SBin Meng 	/*
32*48748595SBin Meng 	 * Initialize Programmable Attribute Map (PAM) Registers
33*48748595SBin Meng 	 *
34*48748595SBin Meng 	 * Configure legacy segments C/D/E/F to system RAM
35*48748595SBin Meng 	 */
36*48748595SBin Meng 	for (i = 0; i < PAM_NUM; i++)
37*48748595SBin Meng 		x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
38*48748595SBin Meng 
39*48748595SBin Meng 	if (i440fx) {
40*48748595SBin Meng 		/*
41*48748595SBin Meng 		 * Enable legacy IDE I/O ports decode
42*48748595SBin Meng 		 *
43*48748595SBin Meng 		 * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
44*48748595SBin Meng 		 * However Linux ata_piix driver does sanity check on these two
45*48748595SBin Meng 		 * registers to see whether legacy ports decode is turned on.
46*48748595SBin Meng 		 * This is to make Linux ata_piix driver happy.
47*48748595SBin Meng 		 */
48*48748595SBin Meng 		x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
49*48748595SBin Meng 		x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
50*48748595SBin Meng 
51*48748595SBin Meng 		/* Enable I/O APIC */
52*48748595SBin Meng 		xbcs = x86_pci_read_config16(PIIX_ISA, XBCS);
53*48748595SBin Meng 		xbcs |= APIC_EN;
54*48748595SBin Meng 		x86_pci_write_config16(PIIX_ISA, XBCS, xbcs);
55*48748595SBin Meng 	} else {
56*48748595SBin Meng 		/* Configure PCIe ECAM base address */
57*48748595SBin Meng 		x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
58*48748595SBin Meng 				       CONFIG_PCIE_ECAM_BASE | BAR_EN);
59*48748595SBin Meng 	}
60*48748595SBin Meng }
61a65b25d1SBin Meng 
62a65b25d1SBin Meng int arch_cpu_init(void)
63a65b25d1SBin Meng {
64a65b25d1SBin Meng 	int ret;
65a65b25d1SBin Meng 
66a65b25d1SBin Meng 	post_code(POST_CPU_INIT);
67a65b25d1SBin Meng #ifdef CONFIG_SYS_X86_TSC_TIMER
68a65b25d1SBin Meng 	timer_set_base(rdtsc());
69a65b25d1SBin Meng #endif
70a65b25d1SBin Meng 
71a65b25d1SBin Meng 	ret = x86_cpu_init_f();
72a65b25d1SBin Meng 	if (ret)
73a65b25d1SBin Meng 		return ret;
74a65b25d1SBin Meng 
75a65b25d1SBin Meng 	return 0;
76a65b25d1SBin Meng }
77a65b25d1SBin Meng 
78eeae5100SSimon Glass #ifndef CONFIG_EFI_STUB
79a65b25d1SBin Meng int print_cpuinfo(void)
80a65b25d1SBin Meng {
81a65b25d1SBin Meng 	post_code(POST_CPU_INFO);
82a65b25d1SBin Meng 	return default_print_cpuinfo();
83a65b25d1SBin Meng }
84eeae5100SSimon Glass #endif
85a65b25d1SBin Meng 
86a65b25d1SBin Meng void reset_cpu(ulong addr)
87a65b25d1SBin Meng {
88a65b25d1SBin Meng 	/* cold reset */
89a65b25d1SBin Meng 	x86_full_reset();
90a65b25d1SBin Meng }
915c564226SBin Meng 
92*48748595SBin Meng int arch_early_init_r(void)
93*48748595SBin Meng {
94*48748595SBin Meng 	qemu_chipset_init();
95*48748595SBin Meng 
96*48748595SBin Meng 	return 0;
97*48748595SBin Meng }
98*48748595SBin Meng 
995c564226SBin Meng int arch_misc_init(void)
1005c564226SBin Meng {
1017e4be120SSimon Glass 	return pirq_init();
1025c564226SBin Meng }
103*48748595SBin Meng 
104*48748595SBin Meng #ifdef CONFIG_GENERATE_MP_TABLE
105*48748595SBin Meng int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
106*48748595SBin Meng {
107*48748595SBin Meng 	u8 irq;
108*48748595SBin Meng 
109*48748595SBin Meng 	if (i440fx) {
110*48748595SBin Meng 		/*
111*48748595SBin Meng 		 * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
112*48748595SBin Meng 		 * connected to I/O APIC INTPIN#16-19. Instead they are routed
113*48748595SBin Meng 		 * to an irq number controled by the PIRQ routing register.
114*48748595SBin Meng 		 */
115*48748595SBin Meng 		irq = x86_pci_read_config8(PCI_BDF(bus, dev, func),
116*48748595SBin Meng 					   PCI_INTERRUPT_LINE);
117*48748595SBin Meng 	} else {
118*48748595SBin Meng 		/*
119*48748595SBin Meng 		 * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
120*48748595SBin Meng 		 * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
121*48748595SBin Meng 		 */
122*48748595SBin Meng 		irq = pirq < 8 ? pirq + 16 : pirq + 12;
123*48748595SBin Meng 	}
124*48748595SBin Meng 
125*48748595SBin Meng 	return irq;
126*48748595SBin Meng }
127*48748595SBin Meng #endif
128