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 8e734fdfb4e..3506ba2946b 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 043bea258c4..7ff05e66284 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 6c291f9ee9c..48409de5c4d 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 4cdd0d40353..0e9f15fef68 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 00000000000..74b89ad2ff6 --- /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 00000000000..fb775d7d283 --- /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 00000000000..be79723a67b --- /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 00000000000..13b3aea3ff0 --- /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 00000000000..a88d0d26547 --- /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 00000000000..1a9140b46e0 --- /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 00000000000..930d2b6c9d1 --- /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 e78a271c509..20cc09e113d 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 4599a4896df..d8761fdfbd2 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 faf951544f3..00000000000 --- 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 b46a7e996f8..873de7be9dd 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 431bbd8a0d6..f86514ce839 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 fbdeade0474..d68efda8dfd 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 60dbc5f8a30..2ba081e9dc2 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 7103bc50777..bd21bfb0b4f 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 00000000000..557428a459c --- /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 00000000000..c259f2a3d29 --- /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 00000000000..75a435e67b9 --- /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 00000000000..ca8cba4f97c --- /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 00000000000..5cbfffffee5 --- /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 4af3dedc957..7882f339f0a 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 6dd02fd31ed..c9979280b62 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 e7f861623e3..00000000000 --- 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 10994273881..ed85b08ce7f 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 00000000000..4de5512ce13 --- /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 be103c055c1..d1d21ed6606 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 5f96da120ea..5809235b10a 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);  			} | 
