diff options
Diffstat (limited to 'arch/x86')
31 files changed, 987 insertions, 486 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8e734fd..3506ba2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -12,11 +12,14 @@ config SYS_VSNPRINTF choice prompt "Mainboard vendor" - default VENDOR_COREBOOT + default VENDOR_EMULATION config VENDOR_COREBOOT bool "coreboot" +config VENDOR_EMULATION + bool "emulation" + config VENDOR_GOOGLE bool "Google" @@ -27,6 +30,7 @@ endchoice # board-specific options below source "board/coreboot/Kconfig" +source "board/emulation/Kconfig" source "board/google/Kconfig" source "board/intel/Kconfig" @@ -34,6 +38,7 @@ source "board/intel/Kconfig" source "arch/x86/cpu/baytrail/Kconfig" source "arch/x86/cpu/coreboot/Kconfig" source "arch/x86/cpu/ivybridge/Kconfig" +source "arch/x86/cpu/qemu/Kconfig" source "arch/x86/cpu/quark/Kconfig" source "arch/x86/cpu/queensbay/Kconfig" @@ -182,147 +187,6 @@ config MARK_GRAPHICS_MEM_WRCOMB memory is set as write-combining cache type. This option enables marking the graphics memory as write-combining. -menu "Display" - -config FRAMEBUFFER_SET_VESA_MODE - prompt "Set framebuffer graphics resolution" - bool - help - Set VESA/native framebuffer mode (needed for bootsplash and graphical framebuffer console) - -choice - prompt "framebuffer graphics resolution" - default FRAMEBUFFER_VESA_MODE_117 - depends on FRAMEBUFFER_SET_VESA_MODE - help - This option sets the resolution used for the coreboot framebuffer (and - bootsplash screen). - -config FRAMEBUFFER_VESA_MODE_100 - bool "640x400 256-color" - -config FRAMEBUFFER_VESA_MODE_101 - bool "640x480 256-color" - -config FRAMEBUFFER_VESA_MODE_102 - bool "800x600 16-color" - -config FRAMEBUFFER_VESA_MODE_103 - bool "800x600 256-color" - -config FRAMEBUFFER_VESA_MODE_104 - bool "1024x768 16-color" - -config FRAMEBUFFER_VESA_MODE_105 - bool "1024x7686 256-color" - -config FRAMEBUFFER_VESA_MODE_106 - bool "1280x1024 16-color" - -config FRAMEBUFFER_VESA_MODE_107 - bool "1280x1024 256-color" - -config FRAMEBUFFER_VESA_MODE_108 - bool "80x60 text" - -config FRAMEBUFFER_VESA_MODE_109 - bool "132x25 text" - -config FRAMEBUFFER_VESA_MODE_10A - bool "132x43 text" - -config FRAMEBUFFER_VESA_MODE_10B - bool "132x50 text" - -config FRAMEBUFFER_VESA_MODE_10C - bool "132x60 text" - -config FRAMEBUFFER_VESA_MODE_10D - bool "320x200 32k-color (1:5:5:5)" - -config FRAMEBUFFER_VESA_MODE_10E - bool "320x200 64k-color (5:6:5)" - -config FRAMEBUFFER_VESA_MODE_10F - bool "320x200 16.8M-color (8:8:8)" - -config FRAMEBUFFER_VESA_MODE_110 - bool "640x480 32k-color (1:5:5:5)" - -config FRAMEBUFFER_VESA_MODE_111 - bool "640x480 64k-color (5:6:5)" - -config FRAMEBUFFER_VESA_MODE_112 - bool "640x480 16.8M-color (8:8:8)" - -config FRAMEBUFFER_VESA_MODE_113 - bool "800x600 32k-color (1:5:5:5)" - -config FRAMEBUFFER_VESA_MODE_114 - bool "800x600 64k-color (5:6:5)" - -config FRAMEBUFFER_VESA_MODE_115 - bool "800x600 16.8M-color (8:8:8)" - -config FRAMEBUFFER_VESA_MODE_116 - bool "1024x768 32k-color (1:5:5:5)" - -config FRAMEBUFFER_VESA_MODE_117 - bool "1024x768 64k-color (5:6:5)" - -config FRAMEBUFFER_VESA_MODE_118 - bool "1024x768 16.8M-color (8:8:8)" - -config FRAMEBUFFER_VESA_MODE_119 - bool "1280x1024 32k-color (1:5:5:5)" - -config FRAMEBUFFER_VESA_MODE_11A - bool "1280x1024 64k-color (5:6:5)" - -config FRAMEBUFFER_VESA_MODE_11B - bool "1280x1024 16.8M-color (8:8:8)" - -config FRAMEBUFFER_VESA_MODE_USER - bool "Manually select VESA mode" - -endchoice - -# Map the config names to an integer (KB). -config FRAMEBUFFER_VESA_MODE - prompt "VESA mode" if FRAMEBUFFER_VESA_MODE_USER - hex - default 0x100 if FRAMEBUFFER_VESA_MODE_100 - default 0x101 if FRAMEBUFFER_VESA_MODE_101 - default 0x102 if FRAMEBUFFER_VESA_MODE_102 - default 0x103 if FRAMEBUFFER_VESA_MODE_103 - default 0x104 if FRAMEBUFFER_VESA_MODE_104 - default 0x105 if FRAMEBUFFER_VESA_MODE_105 - default 0x106 if FRAMEBUFFER_VESA_MODE_106 - default 0x107 if FRAMEBUFFER_VESA_MODE_107 - default 0x108 if FRAMEBUFFER_VESA_MODE_108 - default 0x109 if FRAMEBUFFER_VESA_MODE_109 - default 0x10A if FRAMEBUFFER_VESA_MODE_10A - default 0x10B if FRAMEBUFFER_VESA_MODE_10B - default 0x10C if FRAMEBUFFER_VESA_MODE_10C - default 0x10D if FRAMEBUFFER_VESA_MODE_10D - default 0x10E if FRAMEBUFFER_VESA_MODE_10E - default 0x10F if FRAMEBUFFER_VESA_MODE_10F - default 0x110 if FRAMEBUFFER_VESA_MODE_110 - default 0x111 if FRAMEBUFFER_VESA_MODE_111 - default 0x112 if FRAMEBUFFER_VESA_MODE_112 - default 0x113 if FRAMEBUFFER_VESA_MODE_113 - default 0x114 if FRAMEBUFFER_VESA_MODE_114 - default 0x115 if FRAMEBUFFER_VESA_MODE_115 - default 0x116 if FRAMEBUFFER_VESA_MODE_116 - default 0x117 if FRAMEBUFFER_VESA_MODE_117 - default 0x118 if FRAMEBUFFER_VESA_MODE_118 - default 0x119 if FRAMEBUFFER_VESA_MODE_119 - default 0x11A if FRAMEBUFFER_VESA_MODE_11A - default 0x11B if FRAMEBUFFER_VESA_MODE_11B - default 0x117 if FRAMEBUFFER_VESA_MODE_USER - -endmenu - config HAVE_FSP bool "Add an Firmware Support Package binary" help @@ -356,6 +220,7 @@ config FSP_ADDR config FSP_TEMP_RAM_ADDR hex + depends on HAVE_FSP default 0x2000000 help Stack top address which is used in FspInit after DRAM is ready and diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 043bea2..7ff05e6 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -14,11 +14,12 @@ obj-y += interrupts.o cpu.o call64.o obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SYS_COREBOOT) += coreboot/ +obj-$(CONFIG_QEMU) += qemu/ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ obj-$(CONFIG_INTEL_QUARK) += quark/ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ -obj-y += lapic.o +obj-y += irq.o lapic.o obj-$(CONFIG_SMP) += mp_init.o obj-y += mtrr.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c index 6c291f9..48409de 100644 --- a/arch/x86/cpu/baytrail/pci.c +++ b/arch/x86/cpu/baytrail/pci.c @@ -39,7 +39,7 @@ void board_pci_setup_hose(struct pci_controller *hose) pci_set_region(hose->regions + 3, 0, 0, - gd->ram_size, + gd->ram_size < 0x80000000 ? gd->ram_size : 0x80000000, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); hose->region_count = 4; diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 4cdd0d4..0e9f15f 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -7,16 +7,11 @@ */ #include <common.h> -#include <asm/u-boot-x86.h> -#include <flash.h> +#include <fdtdec.h> #include <netdev.h> -#include <ns16550.h> -#include <asm/msr.h> -#include <asm/cache.h> -#include <asm/cpu.h> #include <asm/io.h> +#include <asm/msr.h> #include <asm/mtrr.h> -#include <asm/arch/tables.h> #include <asm/arch/sysinfo.h> #include <asm/arch/timestamp.h> @@ -53,13 +48,6 @@ int last_stage_init(void) return 0; } -#ifndef CONFIG_SYS_NO_FLASH -ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info) -{ - return 0; -} -#endif - int board_eth_init(bd_t *bis) { return pci_eth_init(bis); @@ -67,7 +55,8 @@ int board_eth_init(bd_t *bis) void board_final_cleanup(void) { - /* Un-cache the ROM so the kernel has one + /* + * Un-cache the ROM so the kernel has one * more MTRR available. * * Coreboot should have assigned this to the @@ -86,21 +75,22 @@ void board_final_cleanup(void) mtrr_close(&state); } - /* Issue SMI to Coreboot to lock down ME and registers */ - printf("Finalizing Coreboot\n"); - outb(0xcb, 0xb2); + if (!fdtdec_get_config_bool(gd->fdt_blob, "u-boot,no-apm-finalize")) { + /* + * Issue SMI to coreboot to lock down ME and registers + * when allowed via device tree + */ + printf("Finalizing coreboot\n"); + outb(0xcb, 0xb2); + } } -void panic_puts(const char *str) +int misc_init_r(void) { - NS16550_t port = (NS16550_t)0x3f8; - - NS16550_init(port, 1); - while (*str) - NS16550_putc(port, *str++); + return 0; } -int misc_init_r(void) +int arch_misc_init(void) { return 0; } diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c new file mode 100644 index 0000000..74b89ad --- /dev/null +++ b/arch/x86/cpu/irq.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/pci.h> +#include <asm/pirq_routing.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct irq_router irq_router; +static struct irq_routing_table *pirq_routing_table; + +bool pirq_check_irq_routed(int link, u8 irq) +{ + u8 pirq; + int base = irq_router.link_base; + + if (irq_router.config == PIRQ_VIA_PCI) + pirq = x86_pci_read_config8(irq_router.bdf, + LINK_N2V(link, base)); + else + pirq = readb(irq_router.ibase + LINK_N2V(link, base)); + + pirq &= 0xf; + + /* IRQ# 0/1/2/8/13 are reserved */ + if (pirq < 3 || pirq == 8 || pirq == 13) + return false; + + return pirq == irq ? true : false; +} + +int pirq_translate_link(int link) +{ + return LINK_V2N(link, irq_router.link_base); +} + +void pirq_assign_irq(int link, u8 irq) +{ + int base = irq_router.link_base; + + /* IRQ# 0/1/2/8/13 are reserved */ + if (irq < 3 || irq == 8 || irq == 13) + return; + + if (irq_router.config == PIRQ_VIA_PCI) + x86_pci_write_config8(irq_router.bdf, + LINK_N2V(link, base), irq); + else + writeb(irq, irq_router.ibase + LINK_N2V(link, base)); +} + +static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus, + u8 device, u8 func, u8 pin, u8 pirq) +{ + struct irq_info *slot = *slotp; + + slot->bus = bus; + slot->devfn = (device << 3) | func; + slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base); + slot->irq[pin - 1].bitmap = irq_router.irq_mask; + (*entries)++; + (*slotp)++; +} + +__weak void cpu_irq_init(void) +{ + return; +} + +static int create_pirq_routing_table(void) +{ + const void *blob = gd->fdt_blob; + struct fdt_pci_addr addr; + int node; + int len, count; + const u32 *cell; + struct irq_routing_table *rt; + struct irq_info *slot; + int irq_entries = 0; + int i; + int ret; + + node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER); + if (node < 0) { + debug("%s: Cannot find irq router node\n", __func__); + return -EINVAL; + } + + ret = fdtdec_get_pci_addr(blob, node, FDT_PCI_SPACE_CONFIG, + "reg", &addr); + if (ret) + return ret; + + /* extract the bdf from fdt_pci_addr */ + irq_router.bdf = addr.phys_hi & 0xffff00; + + ret = fdt_find_string(blob, node, "intel,pirq-config", "pci"); + if (!ret) { + irq_router.config = PIRQ_VIA_PCI; + } else { + ret = fdt_find_string(blob, node, "intel,pirq-config", "ibase"); + if (!ret) + irq_router.config = PIRQ_VIA_IBASE; + else + return -EINVAL; + } + + ret = fdtdec_get_int_array(blob, node, "intel,pirq-link", + &irq_router.link_base, 1); + if (ret) + return ret; + + irq_router.irq_mask = fdtdec_get_int(blob, node, + "intel,pirq-mask", PIRQ_BITMAP); + + if (irq_router.config == PIRQ_VIA_IBASE) { + int ibase_off; + + ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); + if (!ibase_off) + return -EINVAL; + + /* + * Here we assume that the IBASE register has already been + * properly configured by U-Boot before. + * + * By 'valid' we mean: + * 1) a valid memory space carved within system memory space + * assigned to IBASE register block. + * 2) memory range decoding is enabled. + * Hence we don't do any santify test here. + */ + irq_router.ibase = x86_pci_read_config32(irq_router.bdf, + ibase_off); + irq_router.ibase &= ~0xf; + } + + cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); + if (!cell) + return -EINVAL; + + if ((len % sizeof(struct pirq_routing)) == 0) + count = len / sizeof(struct pirq_routing); + else + return -EINVAL; + + rt = malloc(sizeof(struct irq_routing_table)); + if (!rt) + return -ENOMEM; + memset((char *)rt, 0, sizeof(struct irq_routing_table)); + + /* Populate the PIRQ table fields */ + rt->signature = PIRQ_SIGNATURE; + rt->version = PIRQ_VERSION; + rt->rtr_bus = 0; + rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) | + PCI_FUNC(irq_router.bdf); + rt->rtr_vendor = PCI_VENDOR_ID_INTEL; + rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; + + slot = rt->slots; + + /* Now fill in the irq_info entries in the PIRQ table */ + for (i = 0; i < count; i++) { + struct pirq_routing pr; + + pr.bdf = fdt_addr_to_cpu(cell[0]); + pr.pin = fdt_addr_to_cpu(cell[1]); + pr.pirq = fdt_addr_to_cpu(cell[2]); + + debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", + i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), + PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, + 'A' + pr.pirq); + fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf), + PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), + pr.pin, pr.pirq); + cell += sizeof(struct pirq_routing) / sizeof(u32); + } + + rt->size = irq_entries * sizeof(struct irq_info) + 32; + + pirq_routing_table = rt; + + return 0; +} + +void pirq_init(void) +{ + cpu_irq_init(); + + if (create_pirq_routing_table()) { + debug("Failed to create pirq routing table\n"); + } else { + /* Route PIRQ */ + pirq_route_irqs(pirq_routing_table->slots, + get_irq_slot_count(pirq_routing_table)); + } +} + +u32 write_pirq_routing_table(u32 addr) +{ + if (!pirq_routing_table) + return addr; + + return copy_pirq_routing_table(addr, pirq_routing_table); +} diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig new file mode 100644 index 0000000..fb775d7 --- /dev/null +++ b/arch/x86/cpu/qemu/Kconfig @@ -0,0 +1,21 @@ +# +# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +config QEMU + bool + select TSC_CALIBRATION_BYPASS + +if QEMU + +config SYS_CAR_ADDR + hex + default 0xd0000 + +config SYS_CAR_SIZE + hex + default 0x10000 + +endif diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile new file mode 100644 index 0000000..be79723 --- /dev/null +++ b/arch/x86/cpu/qemu/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += car.o dram.o qemu.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/qemu/car.S b/arch/x86/cpu/qemu/car.S new file mode 100644 index 0000000..13b3aea --- /dev/null +++ b/arch/x86/cpu/qemu/car.S @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/post.h> + +.globl car_init +car_init: + /* Save the BIST result */ + movl %eax, %ebp + + post_code(POST_CAR_START) + + /* + * Since we know we are running inside emulator, + * we can do nothing here for CAR initialization. + */ + + /* Restore the BIST result */ + movl %ebp, %eax + + post_code(POST_CAR_CPU_CACHE) + jmp car_init_ret diff --git a/arch/x86/cpu/qemu/dram.c b/arch/x86/cpu/qemu/dram.c new file mode 100644 index 0000000..a88d0d2 --- /dev/null +++ b/arch/x86/cpu/qemu/dram.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/post.h> +#include <asm/arch/qemu.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + u32 ram; + + outb(HIGH_RAM_ADDR, CMOS_ADDR_PORT); + ram = ((u32)inb(CMOS_DATA_PORT)) << 14; + outb(LOW_RAM_ADDR, CMOS_ADDR_PORT); + ram |= ((u32)inb(CMOS_DATA_PORT)) << 6; + ram += 16 * 1024; + + gd->ram_size = ram * 1024; + post_code(POST_DRAM); + + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; +} + +/* + * This function looks for the highest region of memory lower than 4GB which + * has enough space for U-Boot where U-Boot is aligned on a page boundary. + * It overrides the default implementation found elsewhere which simply + * picks the end of ram, wherever that may be. The location of the stack, + * the relocation address, and how far U-Boot is moved by relocation are + * set in the global data structure. + */ +ulong board_get_usable_ram_top(ulong total_size) +{ + return gd->ram_size; +} diff --git a/arch/x86/cpu/qemu/pci.c b/arch/x86/cpu/qemu/pci.c new file mode 100644 index 0000000..1a9140b --- /dev/null +++ b/arch/x86/cpu/qemu/pci.c @@ -0,0 +1,101 @@ +/* + * 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; + +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; + 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); + pam = (device == PCI_DEVICE_ID_INTEL_82441) ? 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 (device == PCI_DEVICE_ID_INTEL_82441) { + /* + * 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); + } + + /* + * 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 = (device == PCI_DEVICE_ID_INTEL_82441) ? 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; +} diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c new file mode 100644 index 0000000..930d2b6 --- /dev/null +++ b/arch/x86/cpu/qemu/qemu.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/irq.h> +#include <asm/post.h> +#include <asm/processor.h> + +int arch_cpu_init(void) +{ + int ret; + + post_code(POST_CPU_INIT); +#ifdef CONFIG_SYS_X86_TSC_TIMER + timer_set_base(rdtsc()); +#endif + + ret = x86_cpu_init_f(); + if (ret) + return ret; + + return 0; +} + +int print_cpuinfo(void) +{ + post_code(POST_CPU_INFO); + return default_print_cpuinfo(); +} + +void reset_cpu(ulong addr) +{ + /* cold reset */ + x86_full_reset(); +} + +int arch_misc_init(void) +{ + pirq_init(); + + return 0; +} diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index e78a271..20cc09e 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -9,6 +9,7 @@ #include <netdev.h> #include <phy.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/pci.h> #include <asm/post.h> #include <asm/processor.h> @@ -147,3 +148,33 @@ int cpu_eth_init(bd_t *bis) else return 0; } + +void cpu_irq_init(void) +{ + struct quark_rcba *rcba; + u32 base; + + base = x86_pci_read_config32(QUARK_LEGACY_BRIDGE, LB_RCBA); + base &= ~MEM_BAR_EN; + rcba = (struct quark_rcba *)base; + + /* + * Route Quark PCI device interrupt pin to PIRQ + * + * Route device#23's INTA/B/C/D to PIRQA/B/C/D + * Route device#20,21's INTA/B/C/D to PIRQE/F/G/H + */ + writew(PIRQC, &rcba->rmu_ir); + writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12), + &rcba->d23_ir); + writew(PIRQD, &rcba->core_ir); + writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12), + &rcba->d20d21_ir); +} + +int arch_misc_init(void) +{ + pirq_init(); + + return 0; +} diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile index 4599a48..d8761fd 100644 --- a/arch/x86/cpu/queensbay/Makefile +++ b/arch/x86/cpu/queensbay/Makefile @@ -5,5 +5,5 @@ # obj-y += fsp_configs.o -obj-y += irq.o tnc.o topcliff.o +obj-y += tnc.o topcliff.o obj-$(CONFIG_PCI) += tnc_pci.o diff --git a/arch/x86/cpu/queensbay/irq.c b/arch/x86/cpu/queensbay/irq.c deleted file mode 100644 index faf9515..0000000 --- a/arch/x86/cpu/queensbay/irq.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <errno.h> -#include <malloc.h> -#include <asm/io.h> -#include <asm/pci.h> -#include <asm/post.h> -#include <asm/processor.h> -#include <asm/pirq_routing.h> -#include <asm/arch/device.h> -#include <asm/arch/tnc.h> -#include <asm/arch/irq.h> - -static struct irq_routing_table *pirq_routing_table; - -bool pirq_check_irq_routed(int link, u8 irq) -{ - u8 pirq; - - pirq = x86_pci_read_config8(TNC_LPC, LINK_N2V(link)); - pirq &= 0xf; - - /* IRQ# 0/1/2/8/13 are reserved */ - if (pirq < 3 || pirq == 8 || pirq == 13) - return false; - - return pirq == irq ? true : false; -} - -int pirq_translate_link(int link) -{ - return LINK_V2N(link); -} - -void pirq_assign_irq(int link, u8 irq) -{ - /* IRQ# 0/1/2/8/13 are reserved */ - if (irq < 3 || irq == 8 || irq == 13) - return; - - x86_pci_write_config8(TNC_LPC, LINK_N2V(link), irq); -} - -static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus, - u8 device, u8 func, u8 pin, u8 pirq) -{ - struct irq_info *slot = *slotp; - - slot->bus = bus; - slot->devfn = (device << 3) | func; - slot->irq[pin - 1].link = LINK_N2V(pirq); - slot->irq[pin - 1].bitmap = PIRQ_BITMAP; - (*entries)++; - (*slotp)++; -} - -/* PCIe port downstream INTx swizzle */ -static inline u8 pin_swizzle(u8 pin, int port) -{ - return (pin + port) % 4; -} - -__weak int board_fill_irq_info(struct irq_info *slot) -{ - return 0; -} - -static int create_pirq_routing_table(void) -{ - struct irq_routing_table *rt; - struct irq_info *slot; - int irq_entries = 0; - pci_dev_t tcf_bdf; - u8 tcf_bus, bus; - int i; - - rt = malloc(sizeof(struct irq_routing_table)); - if (!rt) - return -ENOMEM; - memset((char *)rt, 0, sizeof(struct irq_routing_table)); - - /* Populate the PIRQ table fields */ - rt->signature = PIRQ_SIGNATURE; - rt->version = PIRQ_VERSION; - rt->rtr_bus = 0; - rt->rtr_devfn = (TNC_LPC_DEV << 3) | TNC_LPC_FUNC; - rt->rtr_vendor = PCI_VENDOR_ID_INTEL; - rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; - - slot = rt->slots; - - /* - * Now fill in the irq_info entries in the PIRQ table - * - * We start from internal TunnelCreek PCI devices first, then - * followed by all the 4 PCIe ports downstream devices, including - * the Queensbay platform Topcliff chipset devices. - */ - fill_irq_info(&slot, &irq_entries, 0, TNC_IGD_DEV, - TNC_IGD_FUNC, INTA, PIRQE); - fill_irq_info(&slot, &irq_entries, 0, TNC_SDVO_DEV, - TNC_SDVO_FUNC, INTA, PIRQF); - fill_irq_info(&slot, &irq_entries, 0, TNC_HDA_DEV, - TNC_HDA_FUNC, INTA, PIRQG); - fill_irq_info(&slot, &irq_entries, 0, TNC_PCIE0_DEV, - TNC_PCIE0_FUNC, INTA, PIRQE); - fill_irq_info(&slot, &irq_entries, 0, TNC_PCIE1_DEV, - TNC_PCIE1_FUNC, INTA, PIRQF); - fill_irq_info(&slot, &irq_entries, 0, TNC_PCIE2_DEV, - TNC_PCIE2_FUNC, INTA, PIRQG); - fill_irq_info(&slot, &irq_entries, 0, TNC_PCIE3_DEV, - TNC_PCIE3_FUNC, INTA, PIRQH); - - /* Check which PCIe port the Topcliff chipset is connected to */ - tcf_bdf = pci_find_device(PCI_VENDOR_ID_INTEL, 0x8800, 0); - tcf_bus = PCI_BUS(tcf_bdf); - for (i = 0; i < 4; i++) { - bus = x86_pci_read_config8(PCI_BDF(0, TNC_PCIE0_DEV + i, 0), - PCI_SECONDARY_BUS); - if (bus == tcf_bus) - break; - } - - /* Fill in the Topcliff chipset devices' irq info */ - if (i < 4) { - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_PCIE_PORT_DEV, - TCF_PCIE_PORT_FUNC, INTA, pin_swizzle(PIRQA, i)); - - tcf_bus++; - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_0, - TCF_GBE_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_0, - TCF_GPIO_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_2, - TCF_USB1_OHCI0_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_2, - TCF_USB1_OHCI1_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_2, - TCF_USB1_OHCI2_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_2, - TCF_USB1_EHCI_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_2, - TCF_USB_DEVICE_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_4, - TCF_SDIO0_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_4, - TCF_SDIO1_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_6, - TCF_SATA_FUNC, INTD, pin_swizzle(PIRQD, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_8, - TCF_USB2_OHCI0_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_8, - TCF_USB2_OHCI1_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_8, - TCF_USB2_OHCI2_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_8, - TCF_USB2_EHCI_FUNC, INTA, pin_swizzle(PIRQA, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_10, - TCF_DMA1_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_10, - TCF_UART0_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_10, - TCF_UART1_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_10, - TCF_UART2_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_10, - TCF_UART3_FUNC, INTB, pin_swizzle(PIRQB, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_12, - TCF_DMA2_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_12, - TCF_SPI_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_12, - TCF_I2C_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_12, - TCF_CAN_FUNC, INTC, pin_swizzle(PIRQC, i)); - fill_irq_info(&slot, &irq_entries, tcf_bus, TCF_DEV_12, - TCF_1588_FUNC, INTC, pin_swizzle(PIRQC, i)); - } - - /* Call board-specific routine to fill in add-in card's irq info */ - irq_entries += board_fill_irq_info(slot); - - rt->size = irq_entries * sizeof(struct irq_info) + 32; - - pirq_routing_table = rt; - - return 0; -} - -void pirq_init(void) -{ - struct tnc_rcba *rcba; - u32 base; - - base = x86_pci_read_config32(TNC_LPC, LPC_RCBA); - base &= ~MEM_BAR_EN; - rcba = (struct tnc_rcba *)base; - - /* Make sure all internal PCI devices are using INTA */ - writel(INTA, &rcba->d02ip); - writel(INTA, &rcba->d03ip); - writel(INTA, &rcba->d27ip); - writel(INTA, &rcba->d31ip); - writel(INTA, &rcba->d23ip); - writel(INTA, &rcba->d24ip); - writel(INTA, &rcba->d25ip); - writel(INTA, &rcba->d26ip); - - /* - * Route TunnelCreek PCI device interrupt pin to PIRQ - * - * Since PCIe downstream ports received INTx are routed to PIRQ - * A/B/C/D directly and not configurable, we route internal PCI - * device's INTx to PIRQ E/F/G/H. - */ - writew(PIRQE, &rcba->d02ir); - writew(PIRQF, &rcba->d03ir); - writew(PIRQG, &rcba->d27ir); - writew(PIRQH, &rcba->d31ir); - writew(PIRQE, &rcba->d23ir); - writew(PIRQF, &rcba->d24ir); - writew(PIRQG, &rcba->d25ir); - writew(PIRQH, &rcba->d26ir); - - if (create_pirq_routing_table()) { - debug("Failed to create pirq routing table\n"); - } else { - /* Route PIRQ */ - pirq_route_irqs(pirq_routing_table->slots, - get_irq_slot_count(pirq_routing_table)); - } -} - -u32 write_pirq_routing_table(u32 addr) -{ - return copy_pirq_routing_table(addr, pirq_routing_table); -} diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index b46a7e9..873de7b 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -6,10 +6,11 @@ #include <common.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/pci.h> #include <asm/post.h> #include <asm/arch/device.h> -#include <asm/arch/irq.h> +#include <asm/arch/tnc.h> #include <asm/fsp/fsp_support.h> #include <asm/processor.h> @@ -45,6 +46,42 @@ int arch_cpu_init(void) return 0; } +void cpu_irq_init(void) +{ + struct tnc_rcba *rcba; + u32 base; + + base = x86_pci_read_config32(TNC_LPC, LPC_RCBA); + base &= ~MEM_BAR_EN; + rcba = (struct tnc_rcba *)base; + + /* Make sure all internal PCI devices are using INTA */ + writel(INTA, &rcba->d02ip); + writel(INTA, &rcba->d03ip); + writel(INTA, &rcba->d27ip); + writel(INTA, &rcba->d31ip); + writel(INTA, &rcba->d23ip); + writel(INTA, &rcba->d24ip); + writel(INTA, &rcba->d25ip); + writel(INTA, &rcba->d26ip); + + /* + * Route TunnelCreek PCI device interrupt pin to PIRQ + * + * Since PCIe downstream ports received INTx are routed to PIRQ + * A/B/C/D directly and not configurable, we route internal PCI + * device's INTx to PIRQ E/F/G/H. + */ + writew(PIRQE, &rcba->d02ir); + writew(PIRQF, &rcba->d03ir); + writew(PIRQG, &rcba->d27ir); + writew(PIRQH, &rcba->d31ir); + writew(PIRQE, &rcba->d23ir); + writew(PIRQF, &rcba->d24ir); + writew(PIRQG, &rcba->d25ir); + writew(PIRQH, &rcba->d26ir); +} + int arch_misc_init(void) { pirq_init(); diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index 431bbd8..f86514c 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -2,7 +2,9 @@ dtb-y += chromebook_link.dtb \ chromebox_panther.dtb \ crownbay.dtb \ galileo.dtb \ - minnowmax.dtb + minnowmax.dtb \ + qemu-x86_i440fx.dtb \ + qemu-x86_q35.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index fbdeade..d68efda 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -6,6 +6,8 @@ /dts-v1/; +#include <dt-bindings/interrupt-router/intel-irq.h> + /include/ "skeleton.dtsi" /include/ "serial.dtsi" @@ -135,6 +137,58 @@ }; }; }; + + irq-router@1f,0 { + reg = <0x0000f800 0 0 0 0>; + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,pirq-link = <0x60 8>; + intel,pirq-mask = <0xdee0>; + intel,pirq-routing = < + /* TunnelCreek PCI devices */ + PCI_BDF(0, 2, 0) INTA PIRQE + PCI_BDF(0, 3, 0) INTA PIRQF + PCI_BDF(0, 23, 0) INTA PIRQE + PCI_BDF(0, 24, 0) INTA PIRQF + PCI_BDF(0, 25, 0) INTA PIRQG + PCI_BDF(0, 26, 0) INTA PIRQH + PCI_BDF(0, 27, 0) INTA PIRQG + /* + * Topcliff PCI devices + * + * Note on the Crown Bay board, Topcliff chipset + * is connected to TunnelCreek PCIe port 0, so + * its bus number is 1 for its PCIe port and 2 + * for its PCI devices per U-Boot currnet PCI + * bus enumeration algorithm. + */ + PCI_BDF(1, 0, 0) INTA PIRQA + PCI_BDF(2, 0, 1) INTA PIRQA + PCI_BDF(2, 0, 2) INTA PIRQA + PCI_BDF(2, 2, 0) INTB PIRQB + PCI_BDF(2, 2, 1) INTB PIRQB + PCI_BDF(2, 2, 2) INTB PIRQB + PCI_BDF(2, 2, 3) INTB PIRQB + PCI_BDF(2, 2, 4) INTB PIRQB + PCI_BDF(2, 4, 0) INTC PIRQC + PCI_BDF(2, 4, 1) INTC PIRQC + PCI_BDF(2, 6, 0) INTD PIRQD + PCI_BDF(2, 8, 0) INTA PIRQA + PCI_BDF(2, 8, 1) INTA PIRQA + PCI_BDF(2, 8, 2) INTA PIRQA + PCI_BDF(2, 8, 3) INTA PIRQA + PCI_BDF(2, 10, 0) INTB PIRQB + PCI_BDF(2, 10, 1) INTB PIRQB + PCI_BDF(2, 10, 2) INTB PIRQB + PCI_BDF(2, 10, 3) INTB PIRQB + PCI_BDF(2, 10, 4) INTB PIRQB + PCI_BDF(2, 12, 0) INTC PIRQC + PCI_BDF(2, 12, 1) INTC PIRQC + PCI_BDF(2, 12, 2) INTC PIRQC + PCI_BDF(2, 12, 3) INTC PIRQC + PCI_BDF(2, 12, 4) INTC PIRQC + >; + }; }; }; diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts index 60dbc5f..2ba081e 100644 --- a/arch/x86/dts/galileo.dts +++ b/arch/x86/dts/galileo.dts @@ -7,6 +7,7 @@ /dts-v1/; #include <dt-bindings/mrc/quark.h> +#include <dt-bindings/interrupt-router/intel-irq.h> /include/ "skeleton.dtsi" @@ -67,6 +68,27 @@ clock-frequency = <44236800>; current-speed = <115200>; }; + + irq-router@1f,0 { + reg = <0x0000f800 0 0 0 0>; + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,pirq-link = <0x60 8>; + intel,pirq-mask = <0xdef8>; + intel,pirq-routing = < + PCI_BDF(0, 20, 0) INTA PIRQE + PCI_BDF(0, 20, 1) INTB PIRQF + PCI_BDF(0, 20, 2) INTC PIRQG + PCI_BDF(0, 20, 3) INTD PIRQH + PCI_BDF(0, 20, 4) INTA PIRQE + PCI_BDF(0, 20, 5) INTB PIRQF + PCI_BDF(0, 20, 6) INTC PIRQG + PCI_BDF(0, 20, 7) INTD PIRQH + PCI_BDF(0, 21, 0) INTA PIRQE + PCI_BDF(0, 21, 1) INTB PIRQF + PCI_BDF(0, 21, 2) INTC PIRQG + >; + }; }; gpioa { diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts index 7103bc5..bd21bfb 100644 --- a/arch/x86/dts/minnowmax.dts +++ b/arch/x86/dts/minnowmax.dts @@ -6,6 +6,8 @@ /dts-v1/; +#include <dt-bindings/gpio/x86-gpio.h> + /include/ "skeleton.dtsi" /include/ "serial.dtsi" @@ -22,6 +24,27 @@ silent_console = <0>; }; + pch_pinctrl { + compatible = "intel,x86-pinctrl"; + io-base = <0x4c>; + + pin_usb_host_en0@0 { + gpio-offset = <0x80 8>; + pad-offset = <0x260>; + mode-gpio; + output-value = <1>; + direction = <PIN_OUTPUT>; + }; + + pin_usb_host_en1@0 { + gpio-offset = <0x80 9>; + pad-offset = <0x258>; + mode-gpio; + output-value = <1>; + direction = <PIN_OUTPUT>; + }; + }; + gpioa { compatible = "intel,ich6-gpio"; u-boot,dm-pre-reloc; diff --git a/arch/x86/dts/qemu-x86_i440fx.dts b/arch/x86/dts/qemu-x86_i440fx.dts new file mode 100644 index 0000000..557428a --- /dev/null +++ b/arch/x86/dts/qemu-x86_i440fx.dts @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include <dt-bindings/interrupt-router/intel-irq.h> + +/include/ "skeleton.dtsi" +/include/ "serial.dtsi" + +/ { + model = "QEMU x86 (I440FX)"; + compatible = "qemu,x86"; + + config { + silent_console = <0>; + }; + + chosen { + stdout-path = "/serial"; + }; + + pci { + compatible = "pci-x86"; + #address-cells = <3>; + #size-cells = <2>; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0 0x10000000 + 0x42000000 0x0 0xd0000000 0xd0000000 0 0x10000000 + 0x01000000 0x0 0x2000 0x2000 0 0xe000>; + + irq-router@1,0 { + reg = <0x00000800 0 0 0 0>; + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,pirq-link = <0x60 4>; + intel,pirq-mask = <0x0e40>; + intel,pirq-routing = < + /* PIIX UHCI */ + PCI_BDF(0, 1, 2) INTD PIRQD + /* e1000 NIC */ + PCI_BDF(0, 3, 0) INTA PIRQC + >; + }; + }; + +}; diff --git a/arch/x86/dts/qemu-x86_q35.dts b/arch/x86/dts/qemu-x86_q35.dts new file mode 100644 index 0000000..c259f2a --- /dev/null +++ b/arch/x86/dts/qemu-x86_q35.dts @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include <dt-bindings/interrupt-router/intel-irq.h> + +/* ICH9 IRQ router has discrete PIRQ control registers */ +#undef PIRQE +#undef PIRQF +#undef PIRQG +#undef PIRQH +#define PIRQE 8 +#define PIRQF 9 +#define PIRQG 10 +#define PIRQH 11 + +/include/ "skeleton.dtsi" +/include/ "serial.dtsi" + +/ { + model = "QEMU x86 (Q35)"; + compatible = "qemu,x86"; + + config { + silent_console = <0>; + u-boot,no-apm-finalize; + }; + + chosen { + stdout-path = "/serial"; + }; + + pci { + compatible = "pci-x86"; + #address-cells = <3>; + #size-cells = <2>; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0 0x10000000 + 0x42000000 0x0 0xd0000000 0xd0000000 0 0x10000000 + 0x01000000 0x0 0x2000 0x2000 0 0xe000>; + + irq-router@1f,0 { + reg = <0x0000f800 0 0 0 0>; + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,pirq-link = <0x60 8>; + intel,pirq-mask = <0x0e40>; + intel,pirq-routing = < + /* e1000 NIC */ + PCI_BDF(0, 2, 0) INTA PIRQG + /* ICH9 UHCI */ + PCI_BDF(0, 29, 0) INTA PIRQA + PCI_BDF(0, 29, 1) INTB PIRQB + PCI_BDF(0, 29, 2) INTC PIRQC + /* ICH9 EHCI */ + PCI_BDF(0, 29, 7) INTD PIRQD + /* ICH9 SATA */ + PCI_BDF(0, 31, 2) INTA PIRQA + >; + }; + }; + +}; diff --git a/arch/x86/include/asm/arch-qemu/device.h b/arch/x86/include/asm/arch-qemu/device.h new file mode 100644 index 0000000..75a435e --- /dev/null +++ b/arch/x86/include/asm/arch-qemu/device.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _QEMU_DEVICE_H_ +#define _QEMU_DEVICE_H_ + +#include <pci.h> + +#define QEMU_I440FX PCI_BDF(0, 0, 0) +#define PIIX_ISA PCI_BDF(0, 1, 0) +#define PIIX_IDE PCI_BDF(0, 1, 1) +#define PIIX_USB PCI_BDF(0, 1, 2) +#define I440FX_VGA PCI_BDF(0, 2, 0) + +#define QEMU_Q35 PCI_BDF(0, 0, 0) +#define Q35_VGA PCI_BDF(0, 1, 0) + +#endif /* _QEMU_DEVICE_H_ */ diff --git a/arch/x86/include/asm/arch-qemu/gpio.h b/arch/x86/include/asm/arch-qemu/gpio.h new file mode 100644 index 0000000..ca8cba4 --- /dev/null +++ b/arch/x86/include/asm/arch-qemu/gpio.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _X86_ARCH_GPIO_H_ +#define _X86_ARCH_GPIO_H_ + +/* Where in config space is the register that points to the GPIO registers? */ +#define PCI_CFG_GPIOBASE 0x44 + +#endif /* _X86_ARCH_GPIO_H_ */ diff --git a/arch/x86/include/asm/arch-qemu/qemu.h b/arch/x86/include/asm/arch-qemu/qemu.h new file mode 100644 index 0000000..5cbffff --- /dev/null +++ b/arch/x86/include/asm/arch-qemu/qemu.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ARCH_QEMU_H_ +#define _ARCH_QEMU_H_ + +/* Programmable Attribute Map (PAM) Registers */ +#define I440FX_PAM 0x59 +#define Q35_PAM 0x90 +#define PAM_NUM 7 +#define PAM_RW 0x33 + +/* IDE Timing Register */ +#define IDE0_TIM 0x40 +#define IDE1_TIM 0x42 +#define IDE_DECODE_EN 0x8000 + +/* I/O Ports */ +#define CMOS_ADDR_PORT 0x70 +#define CMOS_DATA_PORT 0x71 + +#define LOW_RAM_ADDR 0x34 +#define HIGH_RAM_ADDR 0x35 + +#endif /* _ARCH_QEMU_H_ */ diff --git a/arch/x86/include/asm/arch-quark/device.h b/arch/x86/include/asm/arch-quark/device.h index 4af3ded..7882f33 100644 --- a/arch/x86/include/asm/arch-quark/device.h +++ b/arch/x86/include/asm/arch-quark/device.h @@ -9,20 +9,60 @@ #include <pci.h> -#define QUARK_HOST_BRIDGE PCI_BDF(0, 0, 0) -#define QUARK_MMC_SDIO PCI_BDF(0, 20, 0) -#define QUARK_UART0 PCI_BDF(0, 20, 1) -#define QUARK_USB_DEVICE PCI_BDF(0, 20, 2) -#define QUARK_USB_EHCI PCI_BDF(0, 20, 3) -#define QUARK_USB_OHCI PCI_BDF(0, 20, 4) -#define QUARK_UART1 PCI_BDF(0, 20, 5) -#define QUARK_EMAC0 PCI_BDF(0, 20, 6) -#define QUARK_EMAC1 PCI_BDF(0, 20, 7) -#define QUARK_SPI0 PCI_BDF(0, 21, 0) -#define QUARK_SPI1 PCI_BDF(0, 21, 1) -#define QUARK_I2C_GPIO PCI_BDF(0, 21, 2) -#define QUARK_PCIE0 PCI_BDF(0, 23, 0) -#define QUARK_PCIE1 PCI_BDF(0, 23, 1) -#define QUARK_LEGACY_BRIDGE PCI_BDF(0, 31, 0) +#define QUARK_HOST_BRIDGE_DEV 0 +#define QUARK_HOST_BRIDGE_FUNC 0 + +#define QUARK_DEV_20 20 +#define QUARK_MMC_SDIO_FUNC 0 +#define QUARK_UART0_FUNC 1 +#define QUARK_USB_DEVICE_FUNC 2 +#define QUARK_USB_EHCI_FUNC 3 +#define QUARK_USB_OHCI_FUNC 4 +#define QUARK_UART1_FUNC 5 +#define QUARK_EMAC0_FUNC 6 +#define QUARK_EMAC1_FUNC 7 + +#define QUARK_DEV_21 21 +#define QUARK_SPI0_FUNC 0 +#define QUARK_SPI1_FUNC 1 +#define QUARK_I2C_GPIO_FUNC 2 + +#define QUARK_DEV_23 23 +#define QUARK_PCIE0_FUNC 0 +#define QUARK_PCIE1_FUNC 1 + +#define QUARK_LGC_BRIDGE_DEV 31 +#define QUARK_LGC_BRIDGE_FUNC 0 + +#define QUARK_HOST_BRIDGE \ + PCI_BDF(0, QUARK_HOST_BRIDGE_DEV, QUARK_HOST_BRIDGE_FUNC) +#define QUARK_MMC_SDIO \ + PCI_BDF(0, QUARK_DEV_20, QUARK_MMC_SDIO_FUNC) +#define QUARK_UART0 \ + PCI_BDF(0, QUARK_DEV_20, QUARK_UART0_FUNC) +#define QUARK_USB_DEVICE \ + PCI_BDF(0, QUARK_DEV_20, QUARK_USB_DEVICE_FUNC) +#define QUARK_USB_EHCI \ + PCI_BDF(0, QUARK_DEV_20, QUARK_USB_EHCI_FUNC) +#define QUARK_USB_OHCI \ + PCI_BDF(0, QUARK_DEV_20, QUARK_USB_OHCI_FUNC) +#define QUARK_UART1 \ + PCI_BDF(0, QUARK_DEV_20, QUARK_UART1_FUNC) +#define QUARK_EMAC0 \ + PCI_BDF(0, QUARK_DEV_20, QUARK_EMAC0_FUNC) +#define QUARK_EMAC1 \ + PCI_BDF(0, QUARK_DEV_20, QUARK_EMAC1_FUNC) +#define QUARK_SPI0 \ + PCI_BDF(0, QUARK_DEV_21, QUARK_SPI0_FUNC) +#define QUARK_SPI1 \ + PCI_BDF(0, QUARK_DEV_21, QUARK_SPI1_FUNC) +#define QUARK_I2C_GPIO \ + PCI_BDF(0, QUARK_DEV_21, QUARK_I2C_GPIO_FUNC) +#define QUARK_PCIE0 \ + PCI_BDF(0, QUARK_DEV_23, QUARK_PCIE0_FUNC) +#define QUARK_PCIE1 \ + PCI_BDF(0, QUARK_DEV_23, QUARK_PCIE1_FUNC) +#define QUARK_LEGACY_BRIDGE \ + PCI_BDF(0, QUARK_LGC_BRIDGE_DEV, QUARK_LGC_BRIDGE_FUNC) #endif /* _QUARK_DEVICE_H_ */ diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index 6dd02fd..c997928 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -76,4 +76,19 @@ #define LB_BC 0xd8 #define LB_RCBA 0xf0 +#ifndef __ASSEMBLY__ + +/* Root Complex Register Block */ +struct quark_rcba { + u32 rctl; + u32 esd; + u32 rsvd1[3150]; + u16 rmu_ir; + u16 d23_ir; + u16 core_ir; + u16 d20d21_ir; +}; + +#endif /* __ASSEMBLY__ */ + #endif /* _QUARK_H_ */ diff --git a/arch/x86/include/asm/arch-queensbay/irq.h b/arch/x86/include/asm/arch-queensbay/irq.h deleted file mode 100644 index e7f8616..0000000 --- a/arch/x86/include/asm/arch-queensbay/irq.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _ARCH_IRQ_H_ -#define _ARCH_IRQ_H_ - -enum pci_int_pin { - INTX, - INTA, - INTB, - INTC, - INTD -}; - -enum pirq_pin { - PIRQA, - PIRQB, - PIRQC, - PIRQD, - PIRQE, - PIRQF, - PIRQG, - PIRQH -}; - -/* PIRQ link number and value conversion */ -#define LINK_V2N(link) (link - 0x60) -#define LINK_N2V(link) (link + 0x60) - -#define PIRQ_BITMAP 0xdee0 - -struct irq_info; - -/** - * board_fill_irq_info() - Board-specific irq_info fill routine - * - * This fills the irq_info table for any board-specific add-in cards. - * - * @slot: pointer to the struct irq_info that is to be filled in - * @return: number of entries were written to the struct irq_info - */ -int board_fill_irq_info(struct irq_info *slot); - -/** - * pirq_init() - Initialize platform PIRQ routing - * - * This initializes the PIRQ routing on the platform and configures all PCI - * devices' interrupt line register to a working IRQ number on the 8259 PIC. - */ -void pirq_init(void); - -#endif /* _ARCH_IRQ_H_ */ diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h index 1099427..ed85b08 100644 --- a/arch/x86/include/asm/gpio.h +++ b/arch/x86/include/asm/gpio.h @@ -147,6 +147,7 @@ struct pch_gpio_map { } set3; }; +int gpio_ich6_pinctrl_init(void); void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio); void ich_gpio_set_gpio_map(const struct pch_gpio_map *map); diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h new file mode 100644 index 0000000..4de5512 --- /dev/null +++ b/arch/x86/include/asm/irq.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ARCH_IRQ_H_ +#define _ARCH_IRQ_H_ + +#include <dt-bindings/interrupt-router/intel-irq.h> + +/** + * Intel interrupt router configuration mechanism + * + * There are two known ways of Intel interrupt router configuration mechanism + * so far. On most cases, the IRQ routing configuraiton is controlled by PCI + * configuraiton registers on the legacy bridge, normally PCI BDF(0, 31, 0). + * On some newer platforms like BayTrail and Braswell, the IRQ routing is now + * in the IBASE register block where IBASE is memory-mapped. + */ +enum pirq_config { + PIRQ_VIA_PCI, + PIRQ_VIA_IBASE +}; + +/** + * Intel interrupt router control block + * + * Its members' value will be filled in based on device tree's input. + * + * @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE + * @link_base: link value base number + * @irq_mask: IRQ mask reprenting the 16 IRQs in 8259, bit N is 1 means + * IRQ N is available to be routed + * @lb_bdf: irq router's PCI bus/device/function number encoding + * @ibase: IBASE register block base address + */ +struct irq_router { + int config; + u32 link_base; + u16 irq_mask; + u32 bdf; + u32 ibase; +}; + +struct pirq_routing { + int bdf; + int pin; + int pirq; +}; + +/* PIRQ link number and value conversion */ +#define LINK_V2N(link, base) (link - base) +#define LINK_N2V(link, base) (link + base) + +#define PIRQ_BITMAP 0xdef8 + +/** + * cpu_irq_init() - Initialize CPU IRQ routing + * + * This initializes some platform-specific registers related to IRQ routing, + * like configuring internal PCI devices to use which PCI interrupt pin, + * and which PCI interrupt pin is mapped to which PIRQ line. Note on some + * platforms, such IRQ routing might be hard-coded thus cannot configure. + */ +void cpu_irq_init(void); + +/** + * pirq_init() - Initialize platform PIRQ routing + * + * This initializes the PIRQ routing on the platform and configures all PCI + * devices' interrupt line register to a working IRQ number on the 8259 PIC. + */ +void pirq_init(void); + +#endif /* _ARCH_IRQ_H_ */ diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index be103c0..d1d21ed 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -16,7 +16,6 @@ void init_gd(gd_t *id, u64 *gdt_addr); void setup_gdt(gd_t *id, u64 *gdt_addr); int init_cache(void); int cleanup_before_linux(void); -void panic_puts(const char *str); /* cpu/.../timer.c */ void timer_isr(void *); diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 5f96da1..5809235 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -279,7 +279,7 @@ u64 fsp_get_usable_highmem_top(const void *hob_list) res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_SYS_MEM) { phys_start = res_desc->phys_start; - /* Need memory above 1MB to be collected here */ + /* Need memory above 4GB to be collected here */ if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) top += (u32)(res_desc->len); } |