From acc2482fd8079a062c051cfaac16054f527acab4 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 14 May 2018 11:32:17 +0200 Subject: [PATCH 01/22] x86: tsc: add support for reading CPU freq from cpuid Starting with cpuid level 0x16 (Skylake-based processors) it is possible to get CPU base freq via cpuid. This fixes booting on a skylake based system. Signed-off-by: Christian Gmeiner Reviewed-by: Bin Meng [bmeng: fixed wrong indention of labels] Signed-off-by: Bin Meng --- drivers/timer/tsc_timer.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index c7fefd2..cf86999 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -21,6 +21,17 @@ DECLARE_GLOBAL_DATA_PTR; +static unsigned long cpu_mhz_from_cpuid(void) +{ + if (gd->arch.x86_vendor != X86_VENDOR_INTEL) + return 0; + + if (cpuid_eax(0) < 0x16) + return 0; + + return cpuid_eax(0x16); +} + /* * According to Intel 64 and IA-32 System Programming Guide, * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be @@ -343,13 +354,21 @@ static void tsc_timer_ensure_setup(void) if (!gd->arch.clock_rate) { unsigned long fast_calibrate; + fast_calibrate = cpu_mhz_from_cpuid(); + if (fast_calibrate) + goto done; + fast_calibrate = cpu_mhz_from_msr(); - if (!fast_calibrate) { - fast_calibrate = quick_pit_calibrate(); - if (!fast_calibrate) - panic("TSC frequency is ZERO"); - } + if (fast_calibrate) + goto done; + + fast_calibrate = quick_pit_calibrate(); + if (fast_calibrate) + goto done; + + panic("TSC frequency is ZERO"); +done: gd->arch.clock_rate = fast_calibrate * 1000000; } } From 919c1c1204225fa9b2e52690b915af18c0b0f4a7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 23 May 2018 12:38:02 +0300 Subject: [PATCH 02/22] x86: acpi: Adopt new version of iASL compiler The commit f9a88a4c1cd0 ("iASL: Enhance the -tc option (create AML hex file in C)") in ACPICA project changed a template of the variable that is used in the generated C-file. Now, instead of hard coded "AmlCode" the "%s_aml_code" is in use, where the prefix is a lowered case base name of the output file. In our case it will be "dsdt" producing a name as "dsdt_aml_code". The quick solution is to call sed which replaces new name by the old one to keep compatibility with old version of iASL. The long term solution would be to modify code to use the new name because it is more scalable. Cc: Robert Moore Cc: Sami Mujawar Cc: Evan Lloyd Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng [bmeng: fixed two sentences in the commit message] Signed-off-by: Bin Meng --- scripts/Makefile.lib | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ef7604c..2a7d734 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -399,6 +399,7 @@ cmd_acpi_c_asl= \ $(obj)/dsdt.c: $(src)/dsdt.asl $(call cmd,acpi_c_asl) + $(Q)sed -i -e "s,dsdt_aml_code,AmlCode," $@ # Bzip2 # --------------------------------------------------------------------------- From 341dda352dce7eeaae27db6695d05e3cc1a91dc7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 24 May 2018 03:05:59 -0700 Subject: [PATCH 03/22] x86: baytrail: Correct the comment of IACORE_VIDS bit ranges The guaranteed vid bit ranges in IACORE_VIDS MSR is actually [22:16]. This corrects the comment for it. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/baytrail/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index 29baf08..56e9813 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -80,7 +80,7 @@ static void set_max_freq(void) perf_ctl.lo = (msr.lo & 0x3f0000) >> 8; /* - * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of + * Set guaranteed vid [22:16] from IACORE_VIDS to bits [7:0] of * the PERF_CTL */ msr = msr_read(MSR_IACORE_VIDS); From 9fddf6c7dd9dca493969d4ebd5e5fc2b2e21be9c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:14 -0700 Subject: [PATCH 04/22] usb: xhci-pci: Fix compiler warning This fixes the following compiler warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/usb/host/xhci-pci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index e8fd6bf..b995aef 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -23,9 +23,8 @@ static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, hcor = (struct xhci_hcor *)((uintptr_t) hccr + HC_LENGTH(xhci_readl(&hccr->cr_capbase))); - debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (u32)hccr, (u32)hcor, - (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase))); + debug("XHCI-PCI init hccr %p and hcor %p hc_length %d\n", + hccr, hcor, (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase))); *ret_hccr = hccr; *ret_hcor = hcor; From b173b4ea3499739dec3d79489e689502b5d20300 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:15 -0700 Subject: [PATCH 05/22] x86: ivybridge: Imply USB_XHCI_HCD The Panther Point chipset connected to Ivybridge has xHC integrated, imply it. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/ivybridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig index 82d5489..eec92df 100644 --- a/arch/x86/cpu/ivybridge/Kconfig +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -18,6 +18,7 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE imply SPI_FLASH imply USB imply USB_EHCI_HCD + imply USB_XHCI_HCD imply VIDEO_VESA if NORTHBRIDGE_INTEL_IVYBRIDGE From 80abc8165e658f4538ef2ab00ceba118e097dbfd Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:16 -0700 Subject: [PATCH 06/22] x86: cougarcanyon2: Update dts for SPI lock down It turns out that like Braswell, Intel FSP for IvyBridge requires SPI controller settings to be locked down, as the U-Boot ICH SPI driver fails with the following message on Cougar Canyon 2 board: "ICH SPI: Opcode 9f not found" Update the SPI node property to indicate this fact. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/dts/cougarcanyon2.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts index ea836ee..8c71e98 100644 --- a/arch/x86/dts/cougarcanyon2.dts +++ b/arch/x86/dts/cougarcanyon2.dts @@ -70,6 +70,8 @@ #address-cells = <1>; #size-cells = <0>; compatible = "intel,ich9-spi"; + intel,spi-lock-down; + spi-flash@0 { reg = <0>; compatible = "winbond,w25q64bv", "spi-flash"; From fb05f0b02b01aed48db48f02a15e52c6de2d0dac Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:17 -0700 Subject: [PATCH 07/22] x86: cougarcanyon2: Remove CONFIG_HAVE_INTEL_ME As README.x86 already mentions, there are two SPI flashes mounted on Intel Cougar Canyon 2 board, called SPI-0 and SPI-1 respectively. SPI-0 stores the flash descriptor and the ME firmware. SPI-1 stores the actual BIOS image which is U-Boot. Building a single image with both ME firmware and U-Boot does not make sense. This also describes the exact flash location where the u-boot.rom should be programmed in the documentation. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- configs/cougarcanyon2_defconfig | 1 + doc/README.x86 | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig index 6c79b77..04ad232 100644 --- a/configs/cougarcanyon2_defconfig +++ b/configs/cougarcanyon2_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_TEXT_BASE=0xFFE00000 CONFIG_VENDOR_INTEL=y CONFIG_DEFAULT_DEVICE_TREE="cougarcanyon2" CONFIG_TARGET_COUGARCANYON2=y +# CONFIG_HAVE_INTEL_ME is not set # CONFIG_ENABLE_MRC_CACHE is not set CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" diff --git a/doc/README.x86 b/doc/README.x86 index 04f0220..78664c3 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -256,7 +256,9 @@ the board manual. The SPI-0 flash should have flash descriptor plus ME firmware and SPI-1 flash is used to store U-Boot. For convenience, the complete 8MB SPI-0 flash image is included in the FSP package (named Rom00_8M_MB_PPT.bin). Program this image to the SPI-0 flash according to the board manual just once and we are -all set. For programming U-Boot we just need to program SPI-1 flash. +all set. For programming U-Boot we just need to program SPI-1 flash. Since the +default u-boot.rom image for this board is set to 2MB, it should be programmed +to the last 2MB of the 8MB chip, address range [600000, 7FFFFF]. --- From 7d0bc172e5a5621113710d5e6e1a5413845c0863 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:18 -0700 Subject: [PATCH 08/22] x86: ivybridge: Enable 206ax cpu driver for FSP build At present this 206ax cpu driver is only built when FSP is not used. This updates the Makefile to enable the build for both cases. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/ivybridge/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 27cfb26..716134e 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -8,7 +8,6 @@ else obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += cpu.o obj-y += early_me.o obj-y += lpc.o -obj-y += model_206ax.o obj-y += northbridge.o ifndef CONFIG_SPL_BUILD obj-y += sata.o @@ -18,4 +17,5 @@ ifndef CONFIG_$(SPL_)X86_32BIT_INIT obj-y += sdram_nop.o endif endif +obj-y += model_206ax.o obj-y += bd82x6x.o From a8542ad81f544e754a7173b43b13f9db1354de0f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:19 -0700 Subject: [PATCH 09/22] x86: ivybridge: Drop CONFIG_USBDEBUG This is not used anywhere. Clean this up. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/intel_common/mrc.c | 5 ----- arch/x86/cpu/ivybridge/model_206ax.c | 15 --------------- scripts/config_whitelist.txt | 1 - 3 files changed, 21 deletions(-) diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c index a5697a6..b35102a 100644 --- a/arch/x86/cpu/intel_common/mrc.c +++ b/arch/x86/cpu/intel_common/mrc.c @@ -242,11 +242,6 @@ static int sdram_initialise(struct udevice *dev, struct udevice *me_dev, version >> 24 , (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); -#if CONFIG_USBDEBUG - /* mrc.bin reconfigures USB, so reinit it to have debug */ - early_usbdebug_init(); -#endif - return 0; } diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index c5441aa..33e5c62 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -393,10 +393,6 @@ static void configure_mca(void) msr_write(IA32_MC0_STATUS + (i * 4), msr); } -#if CONFIG_USBDEBUG -static unsigned ehci_debug_addr; -#endif - static int model_206ax_init(struct udevice *dev) { int ret; @@ -404,17 +400,6 @@ static int model_206ax_init(struct udevice *dev) /* Clear out pending MCEs */ configure_mca(); -#if CONFIG_USBDEBUG - /* Is this caution really needed? */ - if (!ehci_debug_addr) - ehci_debug_addr = get_ehci_debug(); - set_ehci_debug(0); -#endif - -#if CONFIG_USBDEBUG - set_ehci_debug(ehci_debug_addr); -#endif - /* Enable the local cpu apics */ enable_lapic_tpr(); diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index e99ba6b..1a54337 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4581,7 +4581,6 @@ CONFIG_USART1 CONFIG_USART_BASE CONFIG_USART_ID CONFIG_USBBOOTCOMMAND -CONFIG_USBDEBUG CONFIG_USBD_CONFIGURATION_STR CONFIG_USBD_CTRL_INTERFACE_STR CONFIG_USBD_DATA_INTERFACE_STR From 8407f5fcdc7335529e4edca20b7674cb75e5182b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:20 -0700 Subject: [PATCH 10/22] x86: chromebook_link: Remove dm-pre-reloc property in the cpu nodes The 206ax cpu driver does not require pre-relocation flag to work. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/dts/chromebook_link.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index fab919a..26b9f85 100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -26,14 +26,12 @@ cpus { #address-cells = <1>; #size-cells = <0>; - u-boot,dm-pre-reloc; cpu@0 { device_type = "cpu"; compatible = "intel,core-gen3"; reg = <0>; intel,apic-id = <0>; - u-boot,dm-pre-reloc; }; cpu@1 { @@ -41,7 +39,6 @@ compatible = "intel,core-gen3"; reg = <1>; intel,apic-id = <1>; - u-boot,dm-pre-reloc; }; cpu@2 { @@ -49,7 +46,6 @@ compatible = "intel,core-gen3"; reg = <2>; intel,apic-id = <2>; - u-boot,dm-pre-reloc; }; cpu@3 { @@ -57,7 +53,6 @@ compatible = "intel,core-gen3"; reg = <3>; intel,apic-id = <3>; - u-boot,dm-pre-reloc; }; }; From 0a6fb5b5773eab9d5ebd8e72c13c90b1a634cf4c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:21 -0700 Subject: [PATCH 11/22] x86: cougarcanyon2: Enable CPU driver and SMP support This enables the 206ax cpu driver on Intel Cougar Canyon 2 board, so that SMP can be supported too. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/dts/cougarcanyon2.dts | 33 +++++++++++++++++++++++++++++++++ configs/cougarcanyon2_defconfig | 3 +++ 2 files changed, 36 insertions(+) diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts index 8c71e98..946ba06 100644 --- a/arch/x86/dts/cougarcanyon2.dts +++ b/arch/x86/dts/cougarcanyon2.dts @@ -27,6 +27,39 @@ stdout-path = "/serial"; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "intel,core-gen3"; + reg = <0>; + intel,apic-id = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "intel,core-gen3"; + reg = <1>; + intel,apic-id = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "intel,core-gen3"; + reg = <2>; + intel,apic-id = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "intel,core-gen3"; + reg = <3>; + intel,apic-id = <3>; + }; + }; + microcode { update@0 { #include "microcode/m12306a2_00000008.dtsi" diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig index 04ad232..98d9aa0 100644 --- a/configs/cougarcanyon2_defconfig +++ b/configs/cougarcanyon2_defconfig @@ -5,12 +5,14 @@ CONFIG_DEFAULT_DEVICE_TREE="cougarcanyon2" CONFIG_TARGET_COUGARCANYON2=y # CONFIG_HAVE_INTEL_ME is not set # CONFIG_ENABLE_MRC_CACHE is not set +CONFIG_SMP=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CPU=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y CONFIG_CMD_PART=y @@ -32,6 +34,7 @@ CONFIG_ISO_PARTITION=y CONFIG_EFI_PARTITION=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_CPU=y CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_USB_STORAGE=y From bc728b1bc0091e5614e82a499820ee8983c7a0b3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:22 -0700 Subject: [PATCH 12/22] x86: irq: Remove chipset specific irq router drivers At present there are 3 irq router drivers. One is the common one and the other two are chipset specific for queensbay and quark. However these are really the same drivers as the core logic is the same. The two chipset specific drivers configure some registers that are outside the irq router block which should really be part of the chipset initialization. Now we remove these specific drivers and make all x86 boards use the common one. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/irq.c | 7 +---- arch/x86/cpu/quark/Makefile | 2 +- arch/x86/cpu/quark/irq.c | 48 ------------------------------- arch/x86/cpu/quark/quark.c | 26 +++++++++++++++++ arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 64 ----------------------------------------- arch/x86/cpu/queensbay/tnc.c | 39 +++++++++++++++++++++++++ arch/x86/dts/crownbay.dts | 2 +- arch/x86/dts/galileo.dts | 2 +- arch/x86/include/asm/irq.h | 7 ----- 10 files changed, 70 insertions(+), 129 deletions(-) delete mode 100644 arch/x86/cpu/quark/irq.c delete mode 100644 arch/x86/cpu/queensbay/irq.c diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 305cd3d..a1d6a84 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -237,7 +237,7 @@ static void irq_enable_sci(struct udevice *dev) } } -int irq_router_common_init(struct udevice *dev) +int irq_router_probe(struct udevice *dev) { int ret; @@ -256,11 +256,6 @@ int irq_router_common_init(struct udevice *dev) return 0; } -int irq_router_probe(struct udevice *dev) -{ - return irq_router_common_init(dev); -} - ulong write_pirq_routing_table(ulong addr) { if (!gd->arch.pirq_routing_table) diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile index 476e37c..7039f8b 100644 --- a/arch/x86/cpu/quark/Makefile +++ b/arch/x86/cpu/quark/Makefile @@ -2,6 +2,6 @@ # # Copyright (C) 2015, Bin Meng -obj-y += car.o dram.o irq.o msg_port.o quark.o +obj-y += car.o dram.o msg_port.o quark.o obj-y += mrc.o mrc_util.o hte.o smc.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o diff --git a/arch/x86/cpu/quark/irq.c b/arch/x86/cpu/quark/irq.c deleted file mode 100644 index 6928c33..0000000 --- a/arch/x86/cpu/quark/irq.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2015, Bin Meng - * Copyright (C) 2015 Google, Inc - */ - -#include -#include -#include -#include -#include - -int quark_irq_router_probe(struct udevice *dev) -{ - struct quark_rcba *rcba; - u32 base; - - qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base); - 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); - - return irq_router_common_init(dev); -} - -static const struct udevice_id quark_irq_router_ids[] = { - { .compatible = "intel,quark-irq-router" }, - { } -}; - -U_BOOT_DRIVER(quark_irq_router_drv) = { - .name = "quark_intel_irq", - .id = UCLASS_IRQ, - .of_match = quark_irq_router_ids, - .probe = quark_irq_router_probe, -}; diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 46141c4..4fd6864 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -313,12 +314,37 @@ static void quark_usb_init(void) writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS); } +static void quark_irq_init(void) +{ + struct quark_rcba *rcba; + u32 base; + + qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base); + 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_early_init_r(void) { quark_pcie_init(); quark_usb_init(); + quark_irq_init(); + return 0; } diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile index b535b2a..ac29613 100644 --- a/arch/x86/cpu/queensbay/Makefile +++ b/arch/x86/cpu/queensbay/Makefile @@ -2,5 +2,5 @@ # # Copyright (C) 2014, Bin Meng -obj-y += fsp_configs.o irq.o +obj-y += fsp_configs.o obj-y += tnc.o diff --git a/arch/x86/cpu/queensbay/irq.c b/arch/x86/cpu/queensbay/irq.c deleted file mode 100644 index 208cd61..0000000 --- a/arch/x86/cpu/queensbay/irq.c +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2014, Bin Meng - * Copyright (C) 2015 Google, Inc - */ - -#include -#include -#include -#include -#include -#include -#include - -int queensbay_irq_router_probe(struct udevice *dev) -{ - struct tnc_rcba *rcba; - u32 base; - - dm_pci_read_config32(dev->parent, LPC_RCBA, &base); - 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 have to route PCIe - * root ports' INTx to PIRQ A/B/C/D as well. For other devices - * on TunneCreek, route them to PIRQ E/F/G/H. - */ - writew(PIRQE, &rcba->d02ir); - writew(PIRQF, &rcba->d03ir); - writew(PIRQG, &rcba->d27ir); - writew(PIRQH, &rcba->d31ir); - writew(PIRQA, &rcba->d23ir); - writew(PIRQB, &rcba->d24ir); - writew(PIRQC, &rcba->d25ir); - writew(PIRQD, &rcba->d26ir); - - return irq_router_common_init(dev); -} - -static const struct udevice_id queensbay_irq_router_ids[] = { - { .compatible = "intel,queensbay-irq-router" }, - { } -}; - -U_BOOT_DRIVER(queensbay_irq_router_drv) = { - .name = "queensbay_intel_irq", - .id = UCLASS_IRQ, - .of_match = queensbay_irq_router_ids, - .probe = queensbay_irq_router_probe, -}; diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 439c14d..76556fc 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -98,6 +98,43 @@ int arch_cpu_init(void) return x86_cpu_init_f(); } +static void tnc_irq_init(void) +{ + struct tnc_rcba *rcba; + u32 base; + + pci_read_config32(TNC_LPC, LPC_RCBA, &base); + 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 have to route PCIe + * root ports' INTx to PIRQ A/B/C/D as well. For other devices + * on TunneCreek, route them to PIRQ E/F/G/H. + */ + writew(PIRQE, &rcba->d02ir); + writew(PIRQF, &rcba->d03ir); + writew(PIRQG, &rcba->d27ir); + writew(PIRQH, &rcba->d31ir); + writew(PIRQA, &rcba->d23ir); + writew(PIRQB, &rcba->d24ir); + writew(PIRQC, &rcba->d25ir); + writew(PIRQD, &rcba->d26ir); +} + int arch_early_init_r(void) { int ret = 0; @@ -106,5 +143,7 @@ int arch_early_init_r(void) ret = disable_igd(); #endif + tnc_irq_init(); + return ret; } diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 4fe076a..d8faa9d 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -151,7 +151,7 @@ #size-cells = <1>; irq-router { - compatible = "intel,queensbay-irq-router"; + compatible = "intel,irq-router"; intel,pirq-config = "pci"; intel,actl-addr = <0x58>; intel,pirq-link = <0x60 8>; diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts index d86fdc0..3454abd 100644 --- a/arch/x86/dts/galileo.dts +++ b/arch/x86/dts/galileo.dts @@ -97,7 +97,7 @@ #size-cells = <1>; irq-router { - compatible = "intel,quark-irq-router"; + compatible = "intel,irq-router"; intel,pirq-config = "pci"; intel,actl-addr = <0x58>; intel,pirq-link = <0x60 8>; diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 169b281..ad95bb4 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -58,11 +58,4 @@ struct pirq_routing { #define PIRQ_BITMAP 0xdef8 -/** - * irq_router_common_init() - Perform common x86 interrupt init - * - * This creates the PIRQ routing table and routes the IRQs - */ -int irq_router_common_init(struct udevice *dev); - #endif /* _ARCH_IRQ_H_ */ From 594d089c8a6439910b7df784e8929b65229b9e91 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 3 Jun 2018 19:04:23 -0700 Subject: [PATCH 13/22] x86: irq: Change LINK_V2N and LINK_N2V to inline functions LINK_V2N and LINK_N2V are currently defines, so they cannot handle complex logics. Change to inline functions for future extension. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/irq.c | 18 +++++++++++------- arch/x86/include/asm/irq.h | 26 +++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index a1d6a84..ec556d3 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -23,9 +23,11 @@ bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) int base = priv->link_base; if (priv->config == PIRQ_VIA_PCI) - dm_pci_read_config8(dev->parent, LINK_N2V(link, base), &pirq); + dm_pci_read_config8(dev->parent, + pirq_linkno_to_reg(link, base), &pirq); else - pirq = readb((uintptr_t)priv->ibase + LINK_N2V(link, base)); + pirq = readb((uintptr_t)priv->ibase + + pirq_linkno_to_reg(link, base)); pirq &= 0xf; @@ -40,7 +42,7 @@ int pirq_translate_link(struct udevice *dev, int link) { struct irq_router *priv = dev_get_priv(dev); - return LINK_V2N(link, priv->link_base); + return pirq_reg_to_linkno(link, priv->link_base); } void pirq_assign_irq(struct udevice *dev, int link, u8 irq) @@ -53,9 +55,11 @@ void pirq_assign_irq(struct udevice *dev, int link, u8 irq) return; if (priv->config == PIRQ_VIA_PCI) - dm_pci_write_config8(dev->parent, LINK_N2V(link, base), irq); + dm_pci_write_config8(dev->parent, + pirq_linkno_to_reg(link, base), irq); else - writeb(irq, (uintptr_t)priv->ibase + LINK_N2V(link, base)); + writeb(irq, (uintptr_t)priv->ibase + + pirq_linkno_to_reg(link, base)); } static struct irq_info *check_dup_entry(struct irq_info *slot_base, @@ -78,7 +82,7 @@ static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot, { slot->bus = bus; slot->devfn = (device << 3) | 0; - slot->irq[pin - 1].link = LINK_N2V(pirq, priv->link_base); + slot->irq[pin - 1].link = pirq_linkno_to_reg(pirq, priv->link_base); slot->irq[pin - 1].bitmap = priv->irq_mask; } @@ -199,7 +203,7 @@ static int create_pirq_routing_table(struct udevice *dev) * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != - LINK_N2V(pr.pirq, priv->link_base)) + pirq_linkno_to_reg(pr.pirq, priv->link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index ad95bb4..bfa58cf 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -52,9 +52,29 @@ struct pirq_routing { int pirq; }; -/* PIRQ link number and value conversion */ -#define LINK_V2N(link, base) (link - base) -#define LINK_N2V(link, base) (link + base) +/** + * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number + * + * @reg: PIRQ routing register offset from the base address + * @base: PIRQ routing register block base address + * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + */ +static inline int pirq_reg_to_linkno(int reg, int base) +{ + return reg - base; +} + +/** + * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset + * + * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + * @base: PIRQ routing register block base address + * @return: PIRQ routing register offset from the base address + */ +static inline int pirq_linkno_to_reg(int linkno, int base) +{ + return linkno + base; +} #define PIRQ_BITMAP 0xdef8 From fcfc8a82b10c8acb844b8f0ed6c5d2cadce1291f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 10 Jun 2018 06:25:01 -0700 Subject: [PATCH 14/22] x86: Conditionally build the pinctrl_ich6 driver The pinctrl_ich6 driver is currently unconditionally built for all x86 boards. Let's use a Kconfig option to control the build. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/Kconfig | 6 ++++++ arch/x86/cpu/baytrail/Kconfig | 1 + arch/x86/cpu/ivybridge/Kconfig | 1 + arch/x86/lib/Makefile | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5c23b2c..18c7fb2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -735,6 +735,12 @@ config I8259_PIC slave) interrupt controllers. Include this to have U-Boot set up the interrupt correctly. +config PINCTRL_ICH6 + bool + help + Intel ICH6 compatible chipset pinctrl driver. It needs to work + together with the ICH6 compatible gpio driver. + config I8254_TIMER bool default y diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig index ac58b03..022a9f2 100644 --- a/arch/x86/cpu/baytrail/Kconfig +++ b/arch/x86/cpu/baytrail/Kconfig @@ -12,6 +12,7 @@ config INTEL_BAYTRAIL imply AHCI_PCI imply ICH_SPI imply INTEL_ICH6_GPIO + imply PINCTRL_ICH6 imply MMC imply MMC_PCI imply MMC_SDHCI diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig index eec92df..5f0e608 100644 --- a/arch/x86/cpu/ivybridge/Kconfig +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -13,6 +13,7 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE imply AHCI_PCI imply ICH_SPI imply INTEL_ICH6_GPIO + imply PINCTRL_ICH6 imply SCSI imply SCSI_AHCI imply SPI_FLASH diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 5a64f6e..e80a7ce 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_ENABLE_MRC_CACHE) += mrccache.o obj-y += northbridge-uclass.o obj-$(CONFIG_I8259_PIC) += i8259.o obj-$(CONFIG_I8254_TIMER) += i8254.o -obj-y += pinctrl_ich6.o +obj-$(CONFIG_PINCTRL_ICH6) += pinctrl_ich6.o obj-y += pirq_routing.o obj-y += relocate.o obj-y += physmem.o From b8038a1cdb857c87dd4bafb43e27159118f1a3e4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 10 Jun 2018 06:25:02 -0700 Subject: [PATCH 15/22] x86: efi: app: Fix broken EFI application The EFI application does not boot currently. It's due to the call to syscon_get_by_driver_data() in cpu_init_r() maps to nowhere as CONFIG_SYSCON is not included in the configuration. EFI application is built as a shared library, so GCC won't complain during the build process if some symbols are not found. GCC will simply put these symbols into the .plt section and expect dynamic loader to fix these up. While we are here, remove some commands and drivers that are not needed at present. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- configs/efi-x86_defconfig | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index 815b51e..a2f072b 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -13,12 +13,8 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_HUSH_PARSER=y # CONFIG_CMD_BOOTM is not set -CONFIG_CMD_GPIO=y CONFIG_CMD_PART=y -CONFIG_CMD_SF=y # CONFIG_CMD_SF_TEST is not set -CONFIG_CMD_SPI=y -CONFIG_CMD_USB=y # CONFIG_CMD_NET is not set CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y @@ -30,10 +26,10 @@ CONFIG_MAC_PARTITION=y CONFIG_ISO_PARTITION=y CONFIG_EFI_PARTITION=y CONFIG_OF_EMBED=y +CONFIG_REGMAP=y +CONFIG_SYSCON=y # CONFIG_DM_ETH is not set CONFIG_DEBUG_EFI_CONSOLE=y -CONFIG_SPI=y -CONFIG_ICH_SPI=y # CONFIG_REGEX is not set CONFIG_EFI=y # CONFIG_EFI_LOADER is not set From 16dde8945ea948e675e48326e740e098dea2035e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 10 Jun 2018 06:25:03 -0700 Subject: [PATCH 16/22] x86: efi: payload: Enforce toolchain to generate 64-bit EFI payload stub codes Attempting to use a toolchain that is preconfigured to generate code for the 32-bit architecture (i386), for example, the i386-linux-gcc toolchain on kernel.org, to compile the 64-bit EFI payload does not build. This updates the makefile fragments to ensure '-m64' is passed to toolchain when building the 64-bit EFI payload stub codes. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/Makefile | 3 ++- arch/x86/lib/Makefile | 4 ++-- lib/efi/Makefile | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index d5a17d0..af9e26c 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -18,7 +18,8 @@ obj-y += cpu.o cpu_x86.o ifndef CONFIG_$(SPL_)X86_64 AFLAGS_REMOVE_call32.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) -AFLAGS_call32.o := -fpic -fshort-wchar +AFLAGS_call32.o := -fpic -fshort-wchar \ + $(if $(CONFIG_EFI_STUB_64BIT),-m64) extra-y += call32.o endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index e80a7ce..0e054da 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -58,10 +58,10 @@ CFLAGS_reloc_ia32_efi.o += -fpic -fshort-wchar # When building for 64-bit we must remove the i386-specific flags CFLAGS_REMOVE_reloc_x86_64_efi.o += -mregparm=3 -march=i386 -m32 -CFLAGS_reloc_x86_64_efi.o += -fpic -fshort-wchar +CFLAGS_reloc_x86_64_efi.o += -fpic -fshort-wchar -m64 AFLAGS_REMOVE_crt0_x86_64_efi.o += -mregparm=3 -march=i386 -m32 -AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar +AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar -m64 extra-$(CONFIG_EFI_STUB_32BIT) += crt0_ia32_efi.o reloc_ia32_efi.o extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o diff --git a/lib/efi/Makefile b/lib/efi/Makefile index 18d081a..f1a3929 100644 --- a/lib/efi/Makefile +++ b/lib/efi/Makefile @@ -7,9 +7,11 @@ obj-$(CONFIG_EFI_STUB) += efi_info.o CFLAGS_REMOVE_efi_stub.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) -CFLAGS_efi_stub.o := -fpic -fshort-wchar -DEFI_STUB +CFLAGS_efi_stub.o := -fpic -fshort-wchar -DEFI_STUB \ + $(if $(CONFIG_EFI_STUB_64BIT),-m64) CFLAGS_REMOVE_efi.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) -CFLAGS_efi.o := -fpic -fshort-wchar -DEFI_STUB +CFLAGS_efi.o := -fpic -fshort-wchar -DEFI_STUB \ + $(if $(CONFIG_EFI_STUB_64BIT),-m64) extra-$(CONFIG_EFI_STUB) += efi_stub.o efi.o From f2825f6ec0bb50e7bd9376828a32212f1961f979 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sun, 10 Jun 2018 06:25:05 -0700 Subject: [PATCH 17/22] dm: pci: Make ranges dt property optional If we use U-Boot as coreboot payload with a generic dts without any ranges specified we fail in pci pre_probe and our pci bus is not usable. So convert decode_regions(..) into a void function and do the simple error handling there. Signed-off-by: Christian Gmeiner Reviewed-by: Bin Meng [bmeng: fixed 'u-boot' in the commit message and checkpatch warning] Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/pci/pci-uclass.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 1cd1e40..de4c71b 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -810,8 +810,8 @@ error: return ret; } -static int decode_regions(struct pci_controller *hose, ofnode parent_node, - ofnode node) +static void decode_regions(struct pci_controller *hose, ofnode parent_node, + ofnode node) { int pci_addr_cells, addr_cells, size_cells; int cells_per_record; @@ -820,8 +820,11 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node, int i; prop = ofnode_get_property(node, "ranges", &len); - if (!prop) - return -EINVAL; + if (!prop) { + debug("%s: Cannot decode regions\n", __func__); + return; + } + pci_addr_cells = ofnode_read_simple_addr_cells(node); addr_cells = ofnode_read_simple_addr_cells(parent_node); size_cells = ofnode_read_simple_size_cells(node); @@ -883,7 +886,7 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node, bd_t *bd = gd->bd; if (!bd) - return 0; + return; for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { if (bd->bi_dram[i].size) { @@ -908,13 +911,12 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node, base, size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); #endif - return 0; + return; } static int pci_uclass_pre_probe(struct udevice *bus) { struct pci_controller *hose; - int ret; debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, bus->parent->name); @@ -923,12 +925,7 @@ static int pci_uclass_pre_probe(struct udevice *bus) /* For bridges, use the top-level PCI controller */ if (!device_is_on_pci_bus(bus)) { hose->ctlr = bus; - ret = decode_regions(hose, dev_ofnode(bus->parent), - dev_ofnode(bus)); - if (ret) { - debug("%s: Cannot decode regions\n", __func__); - return ret; - } + decode_regions(hose, dev_ofnode(bus->parent), dev_ofnode(bus)); } else { struct pci_controller *parent_hose; From 6f95d89c71b9735a114754fc85284cca01db1006 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sun, 10 Jun 2018 06:25:06 -0700 Subject: [PATCH 18/22] dm: pci: Use a 1:1 mapping for bus <-> phy addresses If U-Boot gets used as coreboot payload all pci resources got assigned by coreboot. If a dts without any pci ranges gets used the dm is not able to access pci device memory. To get things working make use of a 1:1 mapping for bus <-> phy addresses. This change makes it possible to get the e1000 U-Boot driver working on a sandybridge device where U-Boot is used as coreboot payload. Signed-off-by: Christian Gmeiner Reviewed-by: Bin Meng [bmeng: fixed 'u-boot' in the commit message] Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/pci/pci-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index de4c71b..46e9c71 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1182,6 +1182,11 @@ static int _dm_pci_bus_to_phys(struct udevice *ctlr, struct pci_region *res; int i; + if (hose->region_count == 0) { + *pa = bus_addr; + return 0; + } + for (i = 0; i < hose->region_count; i++) { res = &hose->regions[i]; @@ -1245,6 +1250,11 @@ int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, ctlr = pci_get_controller(dev); hose = dev_get_uclass_priv(ctlr); + if (hose->region_count == 0) { + *ba = phys_addr; + return 0; + } + for (i = 0; i < hose->region_count; i++) { res = &hose->regions[i]; From 558f3ed9c8d54c7b04db391d7585c7bdbdb3a369 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 10 Jun 2018 06:25:09 -0700 Subject: [PATCH 19/22] x86: efi: payload: Minor clean up on error message output If GetMemoryMap() fails, we really want to know EFI_BITS_PER_LONG instead of BITS_PER_LONG. A space and LF are added in places where error message is output to improve readability. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- lib/efi/efi_stub.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c index 3138739..09023a2 100644 --- a/lib/efi/efi_stub.c +++ b/lib/efi/efi_stub.c @@ -281,7 +281,8 @@ efi_status_t efi_main(efi_handle_t image, struct efi_system_table *sys_table) ret = efi_init(priv, "Payload", image, sys_table); if (ret) { - printhex2(ret); puts(" efi_init() failed\n"); + printhex2(ret); + puts(" efi_init() failed\n"); return ret; } global_priv = priv; @@ -294,7 +295,8 @@ efi_status_t efi_main(efi_handle_t image, struct efi_system_table *sys_table) size = 0; ret = boot->get_memory_map(&size, NULL, &key, &desc_size, &version); if (ret != EFI_BUFFER_TOO_SMALL) { - printhex2(BITS_PER_LONG); + printhex2(EFI_BITS_PER_LONG); + putc(' '); printhex2(ret); puts(" No memory map\n"); return ret; @@ -303,7 +305,7 @@ efi_status_t efi_main(efi_handle_t image, struct efi_system_table *sys_table) desc = efi_malloc(priv, size, &ret); if (!desc) { printhex2(ret); - puts(" No memory for memory descriptor: "); + puts(" No memory for memory descriptor\n"); return ret; } ret = setup_info_table(priv, size + 128); From dcec5d565a20e025d843828d8424851d0271677b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 12 Jun 2018 01:26:45 -0700 Subject: [PATCH 20/22] x86: irq: Parse number of PIRQ links from device tree The "intel,pirq-link" property in Intel IRQ router's dt bindings has two cells, where the second one represents the number of PIRQ links on the platform. However current driver does not parse this information from device tree. This adds the codes to do the parse and save it for future use. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/irq.c | 14 ++++++++++---- arch/x86/include/asm/irq.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index ec556d3..096c34f 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -116,10 +116,16 @@ static int create_pirq_routing_table(struct udevice *dev) return -EINVAL; } - ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); - if (ret == -1) - return ret; - priv->link_base = ret; + cell = fdt_getprop(blob, node, "intel,pirq-link", &len); + if (!cell || len != 8) + return -EINVAL; + priv->link_base = fdt_addr_to_cpu(cell[0]); + priv->link_num = fdt_addr_to_cpu(cell[1]); + if (priv->link_num > CONFIG_MAX_PIRQ_LINKS) { + debug("Limiting supported PIRQ link number from %d to %d\n", + priv->link_num, CONFIG_MAX_PIRQ_LINKS); + priv->link_num = CONFIG_MAX_PIRQ_LINKS; + } priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index bfa58cf..9ac91f2 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -29,6 +29,7 @@ enum pirq_config { * * @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE * @link_base: link value base number + * @link_num: number of PIRQ links supported * @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 @@ -39,6 +40,7 @@ enum pirq_config { struct irq_router { int config; u32 link_base; + int link_num; u16 irq_mask; u32 bdf; u32 ibase; From 51050ff0a239f2640467d4c2fe54e0e8679a4093 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 12 Jun 2018 01:26:46 -0700 Subject: [PATCH 21/22] x86: irq: Support discrete PIRQ routing registers via device tree Currently both pirq_reg_to_linkno() and pirq_linkno_to_reg() assume consecutive PIRQ routing control registers. But this is not always the case on some platforms. Introduce a new device tree property intel,pirq-regmap to describe how the PIRQ routing register offset is mapped to the link number and adjust the irq router driver to utilize the mapping. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/cpu/irq.c | 102 +++++++++++++++++++-- arch/x86/include/asm/irq.h | 32 ++----- doc/device-tree-bindings/misc/intel,irq-router.txt | 6 ++ 3 files changed, 107 insertions(+), 33 deletions(-) diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 096c34f..3adc155 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -16,18 +16,75 @@ DECLARE_GLOBAL_DATA_PTR; +/** + * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number + * + * @priv: IRQ router driver's priv data + * @reg: PIRQ routing register offset from the base address + * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + */ +static inline int pirq_reg_to_linkno(struct irq_router *priv, int reg) +{ + int linkno = 0; + + if (priv->has_regmap) { + struct pirq_regmap *map = priv->regmap; + int i; + + for (i = 0; i < priv->link_num; i++) { + if (reg - priv->link_base == map->offset) { + linkno = map->link; + break; + } + map++; + } + } else { + linkno = reg - priv->link_base; + } + + return linkno; +} + +/** + * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset + * + * @priv: IRQ router driver's priv data + * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + * @return: PIRQ routing register offset from the base address + */ +static inline int pirq_linkno_to_reg(struct irq_router *priv, int linkno) +{ + int reg = 0; + + if (priv->has_regmap) { + struct pirq_regmap *map = priv->regmap; + int i; + + for (i = 0; i < priv->link_num; i++) { + if (linkno == map->link) { + reg = map->offset + priv->link_base; + break; + } + map++; + } + } else { + reg = linkno + priv->link_base; + } + + return reg; +} + bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) { struct irq_router *priv = dev_get_priv(dev); u8 pirq; - int base = priv->link_base; if (priv->config == PIRQ_VIA_PCI) dm_pci_read_config8(dev->parent, - pirq_linkno_to_reg(link, base), &pirq); + pirq_linkno_to_reg(priv, link), &pirq); else pirq = readb((uintptr_t)priv->ibase + - pirq_linkno_to_reg(link, base)); + pirq_linkno_to_reg(priv, link)); pirq &= 0xf; @@ -42,13 +99,12 @@ int pirq_translate_link(struct udevice *dev, int link) { struct irq_router *priv = dev_get_priv(dev); - return pirq_reg_to_linkno(link, priv->link_base); + return pirq_reg_to_linkno(priv, link); } void pirq_assign_irq(struct udevice *dev, int link, u8 irq) { struct irq_router *priv = dev_get_priv(dev); - int base = priv->link_base; /* IRQ# 0/1/2/8/13 are reserved */ if (irq < 3 || irq == 8 || irq == 13) @@ -56,10 +112,10 @@ void pirq_assign_irq(struct udevice *dev, int link, u8 irq) if (priv->config == PIRQ_VIA_PCI) dm_pci_write_config8(dev->parent, - pirq_linkno_to_reg(link, base), irq); + pirq_linkno_to_reg(priv, link), irq); else writeb(irq, (uintptr_t)priv->ibase + - pirq_linkno_to_reg(link, base)); + pirq_linkno_to_reg(priv, link)); } static struct irq_info *check_dup_entry(struct irq_info *slot_base, @@ -82,7 +138,7 @@ static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot, { slot->bus = bus; slot->devfn = (device << 3) | 0; - slot->irq[pin - 1].link = pirq_linkno_to_reg(pirq, priv->link_base); + slot->irq[pin - 1].link = pirq_linkno_to_reg(priv, pirq); slot->irq[pin - 1].bitmap = priv->irq_mask; } @@ -93,6 +149,7 @@ static int create_pirq_routing_table(struct udevice *dev) int node; int len, count; const u32 *cell; + struct pirq_regmap *map; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; @@ -127,6 +184,33 @@ static int create_pirq_routing_table(struct udevice *dev) priv->link_num = CONFIG_MAX_PIRQ_LINKS; } + cell = fdt_getprop(blob, node, "intel,pirq-regmap", &len); + if (cell) { + if (len % sizeof(struct pirq_regmap)) + return -EINVAL; + + count = len / sizeof(struct pirq_regmap); + if (count < priv->link_num) { + printf("Number of pirq-regmap entires is wrong\n"); + return -EINVAL; + } + + count = priv->link_num; + priv->regmap = calloc(count, sizeof(struct pirq_regmap)); + if (!priv->regmap) + return -ENOMEM; + + priv->has_regmap = true; + map = priv->regmap; + for (i = 0; i < count; i++) { + map->link = fdt_addr_to_cpu(cell[0]); + map->offset = fdt_addr_to_cpu(cell[1]); + + cell += sizeof(struct pirq_regmap) / sizeof(u32); + map++; + } + } + priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); @@ -209,7 +293,7 @@ static int create_pirq_routing_table(struct udevice *dev) * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != - pirq_linkno_to_reg(pr.pirq, priv->link_base)) + pirq_linkno_to_reg(priv, pr.pirq)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 9ac91f2..e5c9160 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -22,6 +22,11 @@ enum pirq_config { PIRQ_VIA_IBASE }; +struct pirq_regmap { + int link; + int offset; +}; + /** * Intel interrupt router control block * @@ -30,6 +35,7 @@ enum pirq_config { * @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE * @link_base: link value base number * @link_num: number of PIRQ links supported + * @has_regmap: has mapping table between PIRQ link and routing register offset * @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 @@ -41,6 +47,8 @@ struct irq_router { int config; u32 link_base; int link_num; + bool has_regmap; + struct pirq_regmap *regmap; u16 irq_mask; u32 bdf; u32 ibase; @@ -54,30 +62,6 @@ struct pirq_routing { int pirq; }; -/** - * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number - * - * @reg: PIRQ routing register offset from the base address - * @base: PIRQ routing register block base address - * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) - */ -static inline int pirq_reg_to_linkno(int reg, int base) -{ - return reg - base; -} - -/** - * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset - * - * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) - * @base: PIRQ routing register block base address - * @return: PIRQ routing register offset from the base address - */ -static inline int pirq_linkno_to_reg(int linkno, int base) -{ - return linkno + base; -} - #define PIRQ_BITMAP 0xdef8 #endif /* _ARCH_IRQ_H_ */ diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt index 04ad346..09e97b4 100644 --- a/doc/device-tree-bindings/misc/intel,irq-router.txt +++ b/doc/device-tree-bindings/misc/intel,irq-router.txt @@ -22,6 +22,12 @@ Required properties : - intel,pirq-link : Specifies the PIRQ link information with two cells. The first cell is the register offset that controls the first PIRQ link routing. The second cell is the total number of PIRQ links the router supports. +- intel,pirq-regmap : Specifies PIRQ routing register offset of all PIRQ links, + encoded as 2 cells a group for each link. The first cell is the PIRQ link + number (0 for PIRQA, 1 for PIRQB, etc). The second cell is the PIRQ routing + register offset from the interrupt router's base address. If this property + is omitted, it indicates a consecutive register offset from the first PIRQ + link, as specified by the first cell of intel,pirq-link. - intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the 8259 PIC. Bit N is 1 means IRQ N is available to be routed. - intel,pirq-routing : Specifies all PCI devices' IRQ routing information, From bee053e248e93d82e5c352708f8c892f4a488c54 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 12 Jun 2018 01:26:47 -0700 Subject: [PATCH 22/22] x86: cougarcanyon2: Add missing chipset interrupt information Add Panther Point chipset interrupt pin/PIRQ information, and enable the generation of PIRQ routing table and MP table. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- arch/x86/dts/cougarcanyon2.dts | 46 +++++++++++++++++++++++++++++++++++++++++ configs/cougarcanyon2_defconfig | 2 ++ 2 files changed, 48 insertions(+) diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts index 946ba06..c1cda73 100644 --- a/arch/x86/dts/cougarcanyon2.dts +++ b/arch/x86/dts/cougarcanyon2.dts @@ -5,6 +5,8 @@ /dts-v1/; +#include + /include/ "skeleton.dtsi" /include/ "serial.dtsi" /include/ "keyboard.dtsi" @@ -99,6 +101,50 @@ #address-cells = <1>; #size-cells = <1>; + irq-router { + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,actl-8bit; + intel,actl-addr = <0x44>; + intel,pirq-link = <0x60 8>; + intel,pirq-regmap = < + PIRQA 0 + PIRQB 1 + PIRQC 2 + PIRQD 3 + PIRQE 8 + PIRQF 9 + PIRQG 10 + PIRQH 11 + >; + intel,pirq-mask = <0xcee0>; + intel,pirq-routing = < + /* Panther Point PCI devices */ + PCI_BDF(0, 2, 0) INTA PIRQA + PCI_BDF(0, 20, 0) INTA PIRQA + PCI_BDF(0, 22, 0) INTA PIRQA + PCI_BDF(0, 22, 1) INTB PIRQB + PCI_BDF(0, 22, 2) INTC PIRQC + PCI_BDF(0, 22, 3) INTD PIRQD + PCI_BDF(0, 25, 0) INTA PIRQA + PCI_BDF(0, 26, 0) INTA PIRQA + PCI_BDF(0, 27, 0) INTB PIRQA + PCI_BDF(0, 28, 0) INTA PIRQA + PCI_BDF(0, 28, 1) INTB PIRQB + PCI_BDF(0, 28, 2) INTC PIRQC + PCI_BDF(0, 28, 3) INTD PIRQD + PCI_BDF(0, 28, 4) INTA PIRQA + PCI_BDF(0, 28, 5) INTB PIRQB + PCI_BDF(0, 28, 6) INTC PIRQC + PCI_BDF(0, 28, 7) INTD PIRQD + PCI_BDF(0, 29, 0) INTA PIRQA + PCI_BDF(0, 31, 2) INTB PIRQB + PCI_BDF(0, 31, 3) INTC PIRQC + PCI_BDF(0, 31, 5) INTB PIRQB + PCI_BDF(0, 31, 6) INTC PIRQC + >; + }; + spi0: spi { #address-cells = <1>; #size-cells = <0>; diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig index 98d9aa0..eeee252 100644 --- a/configs/cougarcanyon2_defconfig +++ b/configs/cougarcanyon2_defconfig @@ -6,6 +6,8 @@ CONFIG_TARGET_COUGARCANYON2=y # CONFIG_HAVE_INTEL_ME is not set # CONFIG_ENABLE_MRC_CACHE is not set CONFIG_SMP=y +CONFIG_GENERATE_PIRQ_TABLE=y +CONFIG_GENERATE_MP_TABLE=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_SYS_CONSOLE_INFO_QUIET=y