diff options
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r-- | arch/x86/cpu/interrupts.c | 2 | ||||
-rw-r--r-- | arch/x86/cpu/pci.c | 45 | ||||
-rw-r--r-- | arch/x86/cpu/qemu/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/cpu/qemu/pci.c | 138 | ||||
-rw-r--r-- | arch/x86/cpu/qemu/qemu.c | 82 | ||||
-rw-r--r-- | arch/x86/cpu/queensbay/tnc.c | 26 |
6 files changed, 103 insertions, 191 deletions
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index addd26e..b00ddc0 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -252,7 +252,7 @@ int interrupt_init(void) /* Just in case... */ disable_interrupts(); -#ifdef CONFIG_SYS_PCAT_INTERRUPTS +#ifdef CONFIG_I8259_PIC /* Initialize the master/slave i8259 pic */ i8259_init(); #endif diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index d2ec45a..7a31260 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -19,51 +19,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct pci_controller x86_hose; - -int pci_early_init_hose(struct pci_controller **hosep) -{ - struct pci_controller *hose; - - hose = calloc(1, sizeof(struct pci_controller)); - if (!hose) - return -ENOMEM; - - board_pci_setup_hose(hose); - pci_setup_type1(hose); - hose->last_busno = pci_hose_scan(hose); - gd->hose = hose; - *hosep = hose; - - return 0; -} - -__weak int board_pci_pre_scan(struct pci_controller *hose) -{ - return 0; -} - -__weak int board_pci_post_scan(struct pci_controller *hose) -{ - return 0; -} - -void pci_init_board(void) -{ - struct pci_controller *hose = &x86_hose; - - /* Stop using the early hose */ - gd->hose = NULL; - - board_pci_setup_hose(hose); - pci_setup_type1(hose); - pci_register_hose(hose); - - board_pci_pre_scan(hose); - hose->last_busno = pci_hose_scan(hose); - board_pci_post_scan(hose); -} - static struct pci_controller *get_hose(void) { if (gd->hose) diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index 1c00d1d..3f3958a 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -9,4 +9,3 @@ obj-y += car.o dram.o endif obj-y += qemu.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o -obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/qemu/pci.c b/arch/x86/cpu/qemu/pci.c deleted file mode 100644 index 2e94456..0000000 --- a/arch/x86/cpu/qemu/pci.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <pci_rom.h> -#include <asm/pci.h> -#include <asm/arch/device.h> -#include <asm/arch/qemu.h> - -DECLARE_GLOBAL_DATA_PTR; - -static bool i440fx; - -void board_pci_setup_hose(struct pci_controller *hose) -{ - hose->first_busno = 0; - hose->last_busno = 0; - - /* PCI memory space */ - pci_set_region(hose->regions + 0, - CONFIG_PCI_MEM_BUS, - CONFIG_PCI_MEM_PHYS, - CONFIG_PCI_MEM_SIZE, - PCI_REGION_MEM); - - /* PCI IO space */ - pci_set_region(hose->regions + 1, - CONFIG_PCI_IO_BUS, - CONFIG_PCI_IO_PHYS, - CONFIG_PCI_IO_SIZE, - PCI_REGION_IO); - - pci_set_region(hose->regions + 2, - CONFIG_PCI_PREF_BUS, - CONFIG_PCI_PREF_PHYS, - CONFIG_PCI_PREF_SIZE, - PCI_REGION_PREFETCH); - - pci_set_region(hose->regions + 3, - 0, - 0, - gd->ram_size, - PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); - - hose->region_count = 4; -} - -int board_pci_post_scan(struct pci_controller *hose) -{ - int ret = 0; - u16 device, xbcs; - int pam, i; - pci_dev_t vga; - ulong start; - - /* - * i440FX and Q35 chipset have different PAM register offset, but with - * the same bitfield layout. Here we determine the offset based on its - * PCI device ID. - */ - device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); - i440fx = (device == PCI_DEVICE_ID_INTEL_82441); - pam = i440fx ? I440FX_PAM : Q35_PAM; - - /* - * Initialize Programmable Attribute Map (PAM) Registers - * - * Configure legacy segments C/D/E/F to system RAM - */ - for (i = 0; i < PAM_NUM; i++) - x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW); - - if (i440fx) { - /* - * Enable legacy IDE I/O ports decode - * - * Note: QEMU always decode legacy IDE I/O port on PIIX chipset. - * However Linux ata_piix driver does sanity check on these two - * registers to see whether legacy ports decode is turned on. - * This is to make Linux ata_piix driver happy. - */ - x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); - x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); - - /* Enable I/O APIC */ - xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); - xbcs |= APIC_EN; - x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); - } else { - /* Configure PCIe ECAM base address */ - x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, - CONFIG_PCIE_ECAM_BASE | BAR_EN); - } - - /* - * QEMU emulated graphic card shows in the PCI configuration space with - * PCI vendor id and device id as an artificial pair 0x1234:0x1111. - * It is on PCI bus 0, function 0, but device number is not consistent - * for the two x86 targets it supports. For i440FX and PIIX chipset - * board, it shows as device 2, while for Q35 and ICH9 chipset board, - * it shows as device 1. - */ - vga = i440fx ? I440FX_VGA : Q35_VGA; - start = get_timer(0); - ret = pci_run_vga_bios(vga, NULL, PCI_ROM_USE_NATIVE); - debug("BIOS ran in %lums\n", get_timer(start)); - - return ret; -} - -#ifdef CONFIG_GENERATE_MP_TABLE -int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) -{ - u8 irq; - - if (i440fx) { - /* - * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not - * connected to I/O APIC INTPIN#16-19. Instead they are routed - * to an irq number controled by the PIRQ routing register. - */ - irq = x86_pci_read_config8(PCI_BDF(bus, dev, func), - PCI_INTERRUPT_LINE); - } else { - /* - * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7. - * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11]. - */ - irq = pirq < 8 ? pirq + 16 : pirq + 12; - } - - return irq; -} -#endif diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index 7c03e02..84fb082 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -6,8 +6,58 @@ #include <common.h> #include <asm/irq.h> +#include <asm/pci.h> #include <asm/post.h> #include <asm/processor.h> +#include <asm/arch/device.h> +#include <asm/arch/qemu.h> + +static bool i440fx; + +static void qemu_chipset_init(void) +{ + u16 device, xbcs; + int pam, i; + + /* + * i440FX and Q35 chipset have different PAM register offset, but with + * the same bitfield layout. Here we determine the offset based on its + * PCI device ID. + */ + device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); + i440fx = (device == PCI_DEVICE_ID_INTEL_82441); + pam = i440fx ? I440FX_PAM : Q35_PAM; + + /* + * Initialize Programmable Attribute Map (PAM) Registers + * + * Configure legacy segments C/D/E/F to system RAM + */ + for (i = 0; i < PAM_NUM; i++) + x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW); + + if (i440fx) { + /* + * Enable legacy IDE I/O ports decode + * + * Note: QEMU always decode legacy IDE I/O port on PIIX chipset. + * However Linux ata_piix driver does sanity check on these two + * registers to see whether legacy ports decode is turned on. + * This is to make Linux ata_piix driver happy. + */ + x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); + x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); + + /* Enable I/O APIC */ + xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); + xbcs |= APIC_EN; + x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); + } else { + /* Configure PCIe ECAM base address */ + x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, + CONFIG_PCIE_ECAM_BASE | BAR_EN); + } +} int arch_cpu_init(void) { @@ -39,7 +89,39 @@ void reset_cpu(ulong addr) x86_full_reset(); } +int arch_early_init_r(void) +{ + qemu_chipset_init(); + + return 0; +} + int arch_misc_init(void) { return pirq_init(); } + +#ifdef CONFIG_GENERATE_MP_TABLE +int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) +{ + u8 irq; + + if (i440fx) { + /* + * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not + * connected to I/O APIC INTPIN#16-19. Instead they are routed + * to an irq number controled by the PIRQ routing register. + */ + irq = x86_pci_read_config8(PCI_BDF(bus, dev, func), + PCI_INTERRUPT_LINE); + } else { + /* + * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7. + * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11]. + */ + irq = pirq < 8 ? pirq + 16 : pirq + 12; + } + + return irq; +} +#endif diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 0c02a44..933d189 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -25,12 +25,26 @@ static void unprotect_spi_flash(void) static void __maybe_unused disable_igd(void) { - u32 gc; - - gc = x86_pci_read_config32(TNC_IGD, IGD_GC); - gc &= ~GMS_MASK; - gc |= VGA_DISABLE; - x86_pci_write_config32(TNC_IGD, IGD_GC, gc); + /* + * According to Atom E6xx datasheet, setting VGA Disable (bit17) + * of Graphics Controller register (offset 0x50) prevents IGD + * (D2:F0) from reporting itself as a VGA display controller + * class in the PCI configuration space, and should also prevent + * it from responding to VGA legacy memory range and I/O addresses. + * + * However test result shows that with just VGA Disable bit set and + * a PCIe graphics card connected to one of the PCIe controllers on + * the E6xx, accessing the VGA legacy space still causes system hang. + * After a number of attempts, it turns out besides VGA Disable bit, + * the SDVO (D3:F0) device should be disabled to make it work. + * + * To simplify, use the Function Disable register (offset 0xc4) + * to disable both IGD (D2:F0) and SDVO (D3:F0) devices. Now these + * two devices will be completely disabled (invisible in the PCI + * configuration space) unless a system reset is performed. + */ + x86_pci_write_config32(TNC_IGD, IGD_FD, FUNC_DISABLE); + x86_pci_write_config32(TNC_SDVO, IGD_FD, FUNC_DISABLE); } int arch_cpu_init(void) |