Home | History | Annotate | Download | only in qemu
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2015, Bin Meng <bmeng.cn (at) gmail.com>
      4  */
      5 
      6 #include <common.h>
      7 #include <pci.h>
      8 #include <qfw.h>
      9 #include <asm/irq.h>
     10 #include <asm/post.h>
     11 #include <asm/processor.h>
     12 #include <asm/arch/device.h>
     13 #include <asm/arch/qemu.h>
     14 
     15 static bool i440fx;
     16 
     17 #ifdef CONFIG_QFW
     18 
     19 /* on x86, the qfw registers are all IO ports */
     20 #define FW_CONTROL_PORT	0x510
     21 #define FW_DATA_PORT		0x511
     22 #define FW_DMA_PORT_LOW	0x514
     23 #define FW_DMA_PORT_HIGH	0x518
     24 
     25 static void qemu_x86_fwcfg_read_entry_pio(uint16_t entry,
     26 		uint32_t size, void *address)
     27 {
     28 	uint32_t i = 0;
     29 	uint8_t *data = address;
     30 
     31 	/*
     32 	 * writting FW_CFG_INVALID will cause read operation to resume at
     33 	 * last offset, otherwise read will start at offset 0
     34 	 *
     35 	 * Note: on platform where the control register is IO port, the
     36 	 * endianness is little endian.
     37 	 */
     38 	if (entry != FW_CFG_INVALID)
     39 		outw(cpu_to_le16(entry), FW_CONTROL_PORT);
     40 
     41 	/* the endianness of data register is string-preserving */
     42 	while (size--)
     43 		data[i++] = inb(FW_DATA_PORT);
     44 }
     45 
     46 static void qemu_x86_fwcfg_read_entry_dma(struct fw_cfg_dma_access *dma)
     47 {
     48 	/* the DMA address register is big endian */
     49 	outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
     50 
     51 	while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR)
     52 		__asm__ __volatile__ ("pause");
     53 }
     54 
     55 static struct fw_cfg_arch_ops fwcfg_x86_ops = {
     56 	.arch_read_pio = qemu_x86_fwcfg_read_entry_pio,
     57 	.arch_read_dma = qemu_x86_fwcfg_read_entry_dma
     58 };
     59 #endif
     60 
     61 static void enable_pm_piix(void)
     62 {
     63 	u8 en;
     64 	u16 cmd;
     65 
     66 	/* Set the PM I/O base */
     67 	pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
     68 
     69 	/* Enable access to the PM I/O space */
     70 	pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
     71 	cmd |= PCI_COMMAND_IO;
     72 	pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
     73 
     74 	/* PM I/O Space Enable (PMIOSE) */
     75 	pci_read_config8(PIIX_PM, PMREGMISC, &en);
     76 	en |= PMIOSE;
     77 	pci_write_config8(PIIX_PM, PMREGMISC, en);
     78 }
     79 
     80 static void enable_pm_ich9(void)
     81 {
     82 	/* Set the PM I/O base */
     83 	pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
     84 }
     85 
     86 static void qemu_chipset_init(void)
     87 {
     88 	u16 device, xbcs;
     89 	int pam, i;
     90 
     91 	/*
     92 	 * i440FX and Q35 chipset have different PAM register offset, but with
     93 	 * the same bitfield layout. Here we determine the offset based on its
     94 	 * PCI device ID.
     95 	 */
     96 	pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
     97 	i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
     98 	pam = i440fx ? I440FX_PAM : Q35_PAM;
     99 
    100 	/*
    101 	 * Initialize Programmable Attribute Map (PAM) Registers
    102 	 *
    103 	 * Configure legacy segments C/D/E/F to system RAM
    104 	 */
    105 	for (i = 0; i < PAM_NUM; i++)
    106 		pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
    107 
    108 	if (i440fx) {
    109 		/*
    110 		 * Enable legacy IDE I/O ports decode
    111 		 *
    112 		 * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
    113 		 * However Linux ata_piix driver does sanity check on these two
    114 		 * registers to see whether legacy ports decode is turned on.
    115 		 * This is to make Linux ata_piix driver happy.
    116 		 */
    117 		pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
    118 		pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
    119 
    120 		/* Enable I/O APIC */
    121 		pci_read_config16(PIIX_ISA, XBCS, &xbcs);
    122 		xbcs |= APIC_EN;
    123 		pci_write_config16(PIIX_ISA, XBCS, xbcs);
    124 
    125 		enable_pm_piix();
    126 	} else {
    127 		/* Configure PCIe ECAM base address */
    128 		pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
    129 				   CONFIG_PCIE_ECAM_BASE | BAR_EN);
    130 
    131 		enable_pm_ich9();
    132 	}
    133 
    134 #ifdef CONFIG_QFW
    135 	qemu_fwcfg_init(&fwcfg_x86_ops);
    136 #endif
    137 }
    138 
    139 #if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT)
    140 int arch_cpu_init(void)
    141 {
    142 	post_code(POST_CPU_INIT);
    143 
    144 	return x86_cpu_init_f();
    145 }
    146 
    147 int checkcpu(void)
    148 {
    149 	return 0;
    150 }
    151 
    152 int print_cpuinfo(void)
    153 {
    154 	post_code(POST_CPU_INFO);
    155 	return default_print_cpuinfo();
    156 }
    157 #endif
    158 
    159 void reset_cpu(ulong addr)
    160 {
    161 	/* cold reset */
    162 	x86_full_reset();
    163 }
    164 
    165 int arch_early_init_r(void)
    166 {
    167 	qemu_chipset_init();
    168 
    169 	return 0;
    170 }
    171 
    172 #ifdef CONFIG_GENERATE_MP_TABLE
    173 int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
    174 {
    175 	u8 irq;
    176 
    177 	if (i440fx) {
    178 		/*
    179 		 * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
    180 		 * connected to I/O APIC INTPIN#16-19. Instead they are routed
    181 		 * to an irq number controled by the PIRQ routing register.
    182 		 */
    183 		pci_read_config8(PCI_BDF(bus, dev, func),
    184 				 PCI_INTERRUPT_LINE, &irq);
    185 	} else {
    186 		/*
    187 		 * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
    188 		 * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
    189 		 */
    190 		irq = pirq < 8 ? pirq + 16 : pirq + 12;
    191 	}
    192 
    193 	return irq;
    194 }
    195 #endif
    196