From 57706e4bd67a72f76c9e34c345a19c862f79fce6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Dec 2014 13:06:37 +0800 Subject: [PATCH 01/45] x86: Remove alex.dts in arch/x86/dts No board is using alex.dts, so remove it. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/Makefile | 1 - arch/x86/dts/alex.dts | 24 ------------------------ 2 files changed, 25 deletions(-) delete mode 100644 arch/x86/dts/alex.dts diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index 3b5d6dad46..5525094539 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -1,6 +1,5 @@ dtb-y += link.dtb \ chromebook_link.dtb \ - alex.dtb \ crownbay.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/alex.dts b/arch/x86/dts/alex.dts deleted file mode 100644 index 2f13544612..0000000000 --- a/arch/x86/dts/alex.dts +++ /dev/null @@ -1,24 +0,0 @@ -/dts-v1/; - -/include/ "coreboot.dtsi" - -/ { - #address-cells = <1>; - #size-cells = <1>; - model = "Google Alex"; - compatible = "google,alex", "intel,atom-pineview"; - - config { - silent_console = <0>; - }; - - gpio: gpio {}; - - serial { - reg = <0x3f8 8>; - clock-frequency = <115200>; - }; - - chosen { }; - memory { device_type = "memory"; reg = <0 0>; }; -}; From 9ca5a0ca0e2c7d7c7029aa901db4184e9103efe1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Dec 2014 13:06:38 +0800 Subject: [PATCH 02/45] x86: Rename coreboot.dsti to serial.dtsi The name of coreboot.dtsi is misleading, as it actually describes the legacy serial port device node. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/crownbay.dts | 2 +- arch/x86/dts/link.dts | 2 +- arch/x86/dts/{coreboot.dtsi => serial.dtsi} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename arch/x86/dts/{coreboot.dtsi => serial.dtsi} (100%) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 3f43f3ca37..c3e112f717 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -6,7 +6,7 @@ /dts-v1/; -/include/ "coreboot.dtsi" +/include/ "serial.dtsi" / { #address-cells = <1>; diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index a739080a2f..c6b7d82b45 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ "coreboot.dtsi" +/include/ "serial.dtsi" / { #address-cells = <1>; diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/serial.dtsi similarity index 100% rename from arch/x86/dts/coreboot.dtsi rename to arch/x86/dts/serial.dtsi From 120c41695b8b8c7e68ef7cfdaa2bf4f965357b47 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Dec 2014 13:06:39 +0800 Subject: [PATCH 03/45] x86: Clean up the board dts files This commits cleans up the board dts files. - Correct the serial port register size to 8 - Remove the misleading status = "disabled" statement in the serial.dtsi - Move the inclusion of skeleton.dtsi from serial.dtsi to board dts files - Let the board dts file define stdout-path in the chosen node - Remove device nodes in board dts files thar are duplicated to skeleton.dtsi Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/crownbay.dts | 11 +++-------- arch/x86/dts/link.dts | 11 +++-------- arch/x86/dts/serial.dtsi | 9 +-------- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index c3e112f717..97f7a525aa 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -6,11 +6,10 @@ /dts-v1/; +/include/ "skeleton.dtsi" /include/ "serial.dtsi" / { - #address-cells = <1>; - #size-cells = <1>; model = "Intel Crown Bay"; compatible = "intel,crownbay", "intel,queensbay"; @@ -32,14 +31,10 @@ bank-name = "B"; }; - serial { - reg = <0x3f8 8>; - clock-frequency = <115200>; + chosen { + stdout-path = "/serial"; }; - chosen { }; - memory { device_type = "memory"; reg = <0 0>; }; - spi { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index c6b7d82b45..107af60004 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -1,10 +1,9 @@ /dts-v1/; +/include/ "skeleton.dtsi" /include/ "serial.dtsi" / { - #address-cells = <1>; - #size-cells = <1>; model = "Google Link"; compatible = "google,link", "intel,celeron-ivybridge"; @@ -33,14 +32,10 @@ bank-name = "C"; }; - serial { - reg = <0x3f8 8>; - clock-frequency = <115200>; + chosen { + stdout-path = "/serial"; }; - chosen { }; - memory { device_type = "memory"; reg = <0 0>; }; - spd { compatible = "memory-spd"; #address-cells = <1>; diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi index 65a93acd3d..ebdda763df 100644 --- a/arch/x86/dts/serial.dtsi +++ b/arch/x86/dts/serial.dtsi @@ -1,17 +1,10 @@ -/include/ "skeleton.dtsi" - / { - chosen { - stdout-path = "/serial"; - }; - serial { compatible = "x86-uart"; - reg = <0x3f8 0x10>; + reg = <0x3f8 8>; reg-shift = <0>; io-mapped = <1>; multiplier = <1>; baudrate = <115200>; - status = "disabled"; }; }; From 4722c035cf0f7f82633af9d5fe19d4336805e800 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 30 Dec 2014 22:53:19 +0800 Subject: [PATCH 04/45] x86: Add missing DECLARE_GLOBAL_DATA_PTR for pci.c arch/x86/cpu/pci.c has access to the U-Boot global data thus DECLARE_GLOBAL_DATA_PTR is needed. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index f3492c3851..404fbb6860 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -15,6 +15,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + static struct pci_controller x86_hose; int pci_early_init_hose(struct pci_controller **hosep) From fa5530b85dd48e58700188754ee852444466bf28 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 30 Dec 2014 22:53:20 +0800 Subject: [PATCH 05/45] x86: Support pci bus scan in the early phase On x86, some peripherals on pci buses need to be accessed in the early phase (eg: pci uart) with a valid pci memory/io address, thus scan the pci bus and do the corresponding resource allocation. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index 404fbb6860..1eee08b314 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -29,6 +29,7 @@ int pci_early_init_hose(struct pci_controller **hosep) board_pci_setup_hose(hose); pci_setup_type1(hose); + hose->last_busno = pci_hose_scan(hose); gd->arch.hose = hose; *hosep = hose; From 8f9052fd98e2e97e33b0e5ccf57f028e595abb5d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 30 Dec 2014 22:53:21 +0800 Subject: [PATCH 06/45] pci: Make pci apis usable before relocation Introduce a gd->hose to save the pci hose in the early phase so that apis in drivers/pci/pci.c can be used before relocation. Architecture codes need assign a valid gd->hose in the early phase. Some variables are declared as static so change them to be either stack variable or global data member so that they can be used before relocation, except the 'indent' used by CONFIG_PCI_SCAN_SHOW which just affects some print format. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/pci.c | 8 ++++---- arch/x86/include/asm/global_data.h | 1 - arch/x86/include/asm/pci.h | 2 +- drivers/pci/pci.c | 25 +++++++++++++++++-------- include/asm-generic/global_data.h | 6 ++++++ 5 files changed, 28 insertions(+), 14 deletions(-) diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index 1eee08b314..ab1aaaa059 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -30,7 +30,7 @@ int pci_early_init_hose(struct pci_controller **hosep) board_pci_setup_hose(hose); pci_setup_type1(hose); hose->last_busno = pci_hose_scan(hose); - gd->arch.hose = hose; + gd->hose = hose; *hosep = hose; return 0; @@ -51,7 +51,7 @@ void pci_init_board(void) struct pci_controller *hose = &x86_hose; /* Stop using the early hose */ - gd->arch.hose = NULL; + gd->hose = NULL; board_pci_setup_hose(hose); pci_setup_type1(hose); @@ -64,8 +64,8 @@ void pci_init_board(void) static struct pci_controller *get_hose(void) { - if (gd->arch.hose) - return gd->arch.hose; + if (gd->hose) + return gd->hose; return pci_bus_to_hose(0); } diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 03d491a17f..aeab3e52e3 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -43,7 +43,6 @@ struct arch_global_data { uint32_t tsc_mhz; /* TSC frequency in MHz */ void *new_fdt; /* Relocated FDT */ uint32_t bist; /* Built-in self test value */ - struct pci_controller *hose; /* PCI hose for early use */ enum pei_boot_mode_t pei_boot_mode; const struct pch_gpio_map *gpio_map; /* board GPIO map */ struct memory_info meminfo; /* Memory information */ diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index ac1a808307..c30dd4c218 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -29,7 +29,7 @@ void board_pci_setup_hose(struct pci_controller *hose); * pci_early_init_hose() - Set up PCI host before relocation * * This allocates memory for, sets up and returns the PCI hose. It can be - * called before relocation. The hose will be stored in gd->arch.hose for + * called before relocation. The hose will be stored in gd->hose for * later use, but will become invalid one DRAM is available. */ int pci_early_init_hose(struct pci_controller **hosep); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3daf73c30a..83fd9a068f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -19,6 +19,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + #define PCI_HOSE_OP(rw, size, type) \ int pci_hose_##rw##_config_##size(struct pci_controller *hose, \ pci_dev_t dev, \ @@ -123,6 +125,14 @@ void *pci_map_bar(pci_dev_t pdev, int bar, int flags) static struct pci_controller* hose_head; +struct pci_controller *pci_get_hose_head(void) +{ + if (gd->hose) + return gd->hose; + + return hose_head; +} + void pci_register_hose(struct pci_controller* hose) { struct pci_controller **phose = &hose_head; @@ -139,7 +149,7 @@ struct pci_controller *pci_bus_to_hose(int bus) { struct pci_controller *hose; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { if (bus >= hose->first_busno && bus <= hose->last_busno) return hose; } @@ -152,7 +162,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr) { struct pci_controller *hose; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { if (hose->cfg_addr == cfg_addr) return hose; } @@ -162,7 +172,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr) int pci_last_busno(void) { - struct pci_controller *hose = hose_head; + struct pci_controller *hose = pci_get_hose_head(); if (!hose) return -1; @@ -181,7 +191,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) pci_dev_t bdf; int i, bus, found_multi = 0; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { #ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE for (bus = hose->last_busno; bus >= hose->first_busno; bus--) #else @@ -233,7 +243,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) { - static struct pci_device_id ids[2] = {{}, {0, 0}}; + struct pci_device_id ids[2] = { {}, {0, 0} }; ids[0].vendor = vendor; ids[0].device = device; @@ -709,11 +719,10 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) int pci_hose_scan(struct pci_controller *hose) { #if defined(CONFIG_PCI_BOOTDELAY) - static int pcidelay_done; char *s; int i; - if (!pcidelay_done) { + if (!gd->pcidelay_done) { /* wait "pcidelay" ms (if defined)... */ s = getenv("pcidelay"); if (s) { @@ -721,7 +730,7 @@ int pci_hose_scan(struct pci_controller *hose) for (i = 0; i < val; i++) udelay(1000); } - pcidelay_done = 1; + gd->pcidelay_done = 1; } #endif /* CONFIG_PCI_BOOTDELAY */ diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 9c5a1e166f..3d14d5f117 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -90,6 +90,12 @@ typedef struct global_data { unsigned long malloc_base; /* base address of early malloc() */ unsigned long malloc_limit; /* limit address */ unsigned long malloc_ptr; /* current address */ +#endif +#ifdef CONFIG_PCI + struct pci_controller *hose; /* PCI hose for early use */ +#endif +#ifdef CONFIG_PCI_BOOTDELAY + int pcidelay_done; #endif struct udevice *cur_serial_dev; /* current serial device */ struct arch_global_data arch; /* architecture-specific data */ From 949dbc12db8ba628004ac70359ca0e0edf98432e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 30 Dec 2014 16:02:05 +0800 Subject: [PATCH 07/45] x86: Simplify the fsp hob access functions Remove the troublesome union hob_pointers so that some annoying casts are no longer needed in those hob access routines. This also improves the readability. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/fsp_support.c | 93 ++++++++++--------- arch/x86/cpu/queensbay/tnc_dram.c | 39 ++++---- .../include/asm/arch-queensbay/fsp/fsp_hob.h | 46 ++++----- .../asm/arch-queensbay/fsp/fsp_support.h | 5 +- arch/x86/lib/cmd_hob.c | 16 ++-- 5 files changed, 100 insertions(+), 99 deletions(-) diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index ef1916b2e7..4764e3c62f 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -231,26 +231,28 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) u32 fsp_get_usable_lowmem_top(const void *hob_list) { - union hob_pointers hob; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; phys_addr_t phys_start; u32 top; /* Get the HOB list for processing */ - hob.raw = (void *)hob_list; + hdr = hob_list; /* * Collect memory ranges */ top = FSP_LOWMEM_BASE; - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { - if (hob.res_desc->type == RES_SYS_MEM) { - phys_start = hob.res_desc->phys_start; + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + 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 */ if (phys_start >= FSP_LOWMEM_BASE && phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(hob.res_desc->len); + top += (u32)(res_desc->len); } } - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } return top; @@ -258,25 +260,27 @@ u32 fsp_get_usable_lowmem_top(const void *hob_list) u64 fsp_get_usable_highmem_top(const void *hob_list) { - union hob_pointers hob; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; phys_addr_t phys_start; u64 top; /* Get the HOB list for processing */ - hob.raw = (void *)hob_list; + hdr = hob_list; /* Collect memory ranges */ top = FSP_HIGHMEM_BASE; - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { - if (hob.res_desc->type == RES_SYS_MEM) { - phys_start = hob.res_desc->phys_start; + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + 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 */ if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(hob.res_desc->len); + top += (u32)(res_desc->len); } } - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } return top; @@ -285,24 +289,26 @@ u64 fsp_get_usable_highmem_top(const void *hob_list) u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, struct efi_guid *guid) { - union hob_pointers hob; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; /* Get the HOB list for processing */ - hob.raw = (void *)hob_list; + hdr = hob_list; /* Collect memory ranges */ - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { - if (hob.res_desc->type == RES_MEM_RESERVED) { - if (compare_guid(&hob.res_desc->owner, guid)) { + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_MEM_RESERVED) { + if (compare_guid(&res_desc->owner, guid)) { if (len) - *len = (u32)(hob.res_desc->len); + *len = (u32)(res_desc->len); - return (u64)(hob.res_desc->phys_start); + return (u64)(res_desc->phys_start); } } } - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } return 0; @@ -336,44 +342,45 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) return base; } -void *fsp_get_next_hob(u16 type, const void *hob_list) +const struct hob_header *fsp_get_next_hob(u16 type, const void *hob_list) { - union hob_pointers hob; + const struct hob_header *hdr; - assert(hob_list != NULL); - - hob.raw = (u8 *)hob_list; + hdr = hob_list; /* Parse the HOB list until end of list or matching type is found */ - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == type) - return hob.raw; + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == type) + return hdr; - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } return NULL; } -void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list) +const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, + const void *hob_list) { - union hob_pointers hob; + const struct hob_header *hdr; + struct hob_guid *guid_hob; - hob.raw = (u8 *)hob_list; - while ((hob.raw = fsp_get_next_hob(HOB_TYPE_GUID_EXT, - hob.raw)) != NULL) { - if (compare_guid(guid, &hob.guid->name)) + hdr = hob_list; + while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT, + hdr)) != NULL) { + guid_hob = (struct hob_guid *)hdr; + if (compare_guid(guid, &(guid_hob->name))) break; - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } - return hob.raw; + return hdr; } void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, struct efi_guid *guid) { - u8 *guid_hob; + const struct hob_header *guid_hob; guid_hob = fsp_get_next_guid_hob(guid, hob_list); if (guid_hob == NULL) { diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c index 8e97c9b82a..b669dbc98b 100644 --- a/arch/x86/cpu/queensbay/tnc_dram.c +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -14,17 +14,19 @@ DECLARE_GLOBAL_DATA_PTR; int dram_init(void) { phys_size_t ram_size = 0; - union hob_pointers hob; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; - hob.raw = gd->arch.hob_list; - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { - if (hob.res_desc->type == RES_SYS_MEM || - hob.res_desc->type == RES_MEM_RESERVED) { - ram_size += hob.res_desc->len; + hdr = gd->arch.hob_list; + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_SYS_MEM || + res_desc->type == RES_MEM_RESERVED) { + ram_size += res_desc->len; } } - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); } gd->ram_size = ram_size; @@ -55,22 +57,23 @@ ulong board_get_usable_ram_top(ulong total_size) unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) { unsigned num_entries = 0; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; - union hob_pointers hob; + hdr = gd->arch.hob_list; - hob.raw = gd->arch.hob_list; + while (!end_of_hob(hdr)) { + if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + entries[num_entries].addr = res_desc->phys_start; + entries[num_entries].size = res_desc->len; - while (!end_of_hob(hob)) { - if (get_hob_type(hob) == HOB_TYPE_RES_DESC) { - entries[num_entries].addr = hob.res_desc->phys_start; - entries[num_entries].size = hob.res_desc->len; - - if (hob.res_desc->type == RES_SYS_MEM) + if (res_desc->type == RES_SYS_MEM) entries[num_entries].type = E820_RAM; - else if (hob.res_desc->type == RES_MEM_RESERVED) + else if (res_desc->type == RES_MEM_RESERVED) entries[num_entries].type = E820_RESERVED; } - hob.raw = get_next_hob(hob); + hdr = get_next_hob(hdr); num_entries++; } diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h index 380b64efaa..51103617b0 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h @@ -182,15 +182,6 @@ struct hob_guid { /* GUID specific data goes here */ }; -/* Union of all the possible HOB Types */ -union hob_pointers { - struct hob_header *hdr; - struct hob_mem_alloc *mem_alloc; - struct hob_res_desc *res_desc; - struct hob_guid *guid; - u8 *raw; -}; - /** * get_hob_type() - return the type of a HOB * @@ -201,9 +192,9 @@ union hob_pointers { * * @return: HOB type. */ -static inline u16 get_hob_type(union hob_pointers hob) +static inline u16 get_hob_type(const struct hob_header *hdr) { - return hob.hdr->type; + return hdr->type; } /** @@ -216,9 +207,9 @@ static inline u16 get_hob_type(union hob_pointers hob) * * @return: HOB length. */ -static inline u16 get_hob_length(union hob_pointers hob) +static inline u16 get_hob_length(const struct hob_header *hdr) { - return hob.hdr->len; + return hdr->len; } /** @@ -227,13 +218,13 @@ static inline u16 get_hob_length(union hob_pointers hob) * This macro returns a pointer to HOB that follows the HOB specified by hob * in the HOB List. * - * @hob: A pointer to a HOB. + * @hdr: A pointer to a HOB. * * @return: A pointer to the next HOB in the HOB list. */ -static inline void *get_next_hob(union hob_pointers hob) +static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) { - return (void *)(*(u8 **)&(hob) + get_hob_length(hob)); + return (const struct hob_header *)((u32)hdr + get_hob_length(hdr)); } /** @@ -243,14 +234,14 @@ static inline void *get_next_hob(union hob_pointers hob) * HOB list. If hob is last HOB in the HOB list, then true is returned. * Otherwise, false is returned. * - * @hob: A pointer to a HOB. + * @hdr: A pointer to a HOB. * - * @retval true: The HOB specified by hob is the last HOB in the HOB list. - * @retval false: The HOB specified by hob is not the last HOB in the HOB list. + * @retval true: The HOB specified by hdr is the last HOB in the HOB list. + * @retval false: The HOB specified by hdr is not the last HOB in the HOB list. */ -static inline bool end_of_hob(union hob_pointers hob) +static inline bool end_of_hob(const struct hob_header *hdr) { - return get_hob_type(hob) == HOB_TYPE_EOH; + return get_hob_type(hdr) == HOB_TYPE_EOH; } /** @@ -260,13 +251,13 @@ static inline bool end_of_hob(union hob_pointers hob) * This macro returns a pointer to the data buffer in a HOB specified by hob. * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. * - * @hob: A pointer to a HOB. + * @hdr: A pointer to a HOB. * * @return: A pointer to the data buffer in a HOB. */ -static inline void *get_guid_hob_data(u8 *hob) +static inline void *get_guid_hob_data(const struct hob_header *hdr) { - return (void *)(hob + sizeof(struct hob_guid)); + return (void *)((u32)hdr + sizeof(struct hob_guid)); } /** @@ -276,14 +267,13 @@ static inline void *get_guid_hob_data(u8 *hob) * This macro returns the size, in bytes, of the data buffer in a HOB * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. * - * @hob: A pointer to a HOB. + * @hdr: A pointer to a HOB. * * @return: The size of the data buffer. */ -static inline u16 get_guid_hob_data_size(u8 *hob) +static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { - union hob_pointers hob_p = *(union hob_pointers *)hob; - return get_hob_length(hob_p) - sizeof(struct hob_guid); + return get_hob_length(hdr) - sizeof(struct hob_guid); } /* FSP specific GUID HOB definitions */ diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h index 3ae1b663b9..2a3e987ebb 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h @@ -145,7 +145,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); * * @retval: A HOB object with matching type; Otherwise NULL. */ -void *fsp_get_next_hob(u16 type, const void *hob_list); +const struct hob_header *fsp_get_next_hob(u16 type, const void *hob_list); /** * Returns the next instance of the matched GUID HOB from the starting HOB. @@ -155,7 +155,8 @@ void *fsp_get_next_hob(u16 type, const void *hob_list); * * @retval: A HOB object with matching GUID; Otherwise NULL. */ -void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list); +const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, + const void *hob_list); /** * This function retrieves a GUID HOB data buffer and size. diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c index b552fe6c1b..8d1f038527 100644 --- a/arch/x86/lib/cmd_hob.c +++ b/arch/x86/lib/cmd_hob.c @@ -28,20 +28,20 @@ static char *hob_type[] = { int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - union hob_pointers hob; + const struct hob_header *hdr; u16 type; char *desc; int i = 0; - hob.raw = (u8 *)gd->arch.hob_list; + hdr = gd->arch.hob_list; - printf("HOB list address: 0x%08x\n\n", (unsigned int)hob.raw); + printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr); printf("No. | Address | Type | Length in Bytes\n"); printf("----|----------|---------------------|----------------\n"); - while (!end_of_hob(hob)) { - printf("%-3d | %08x | ", i, (unsigned int)hob.raw); - type = get_hob_type(hob); + while (!end_of_hob(hdr)) { + printf("%-3d | %08x | ", i, (unsigned int)hdr); + type = get_hob_type(hdr); if (type == HOB_TYPE_UNUSED) desc = "*Unused*"; else if (type == HOB_TYPE_EOH) @@ -50,8 +50,8 @@ int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) desc = hob_type[type]; else desc = "*Invalid Type*"; - printf("%-19s | %-15d\n", desc, get_hob_length(hob)); - hob.raw = get_next_hob(hob); + printf("%-19s | %-15d\n", desc, get_hob_length(hdr)); + hdr = get_next_hob(hdr); i++; } From a62e84d7b1824a202dd6a9e9c7b1bc350c7b33b7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 31 Dec 2014 16:05:11 +0800 Subject: [PATCH 08/45] fdt: Add several apis to decode pci device node This commit adds several APIs to decode PCI device node according to the Open Firmware PCI bus bindings, including: - fdtdec_get_pci_addr() for encoded pci address - fdtdec_get_pci_vendev() for vendor id and device id - fdtdec_get_pci_bdf() for pci device bdf triplet - fdtdec_get_pci_bar32() for pci device register bar Signed-off-by: Bin Meng Acked-by: Simon Glass Signed-off-by: Simon Glass (Include in fdtdec.h and adjust tegra to fix build error) --- drivers/pci/pci_tegra.c | 3 +- include/fdtdec.h | 109 ++++++++++++++++++++++--- lib/fdtdec.c | 171 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 257 insertions(+), 26 deletions(-) diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index a03ad5ff1f..f9e05add19 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -458,6 +458,7 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node, unsigned int *index, unsigned int *lanes) { + struct fdt_pci_addr addr; pci_dev_t bdf; int err; @@ -469,7 +470,7 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node, *lanes = err; - err = fdtdec_pci_get_bdf(fdt, node, &bdf); + err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf); if (err < 0) { error("failed to parse \"reg\" property"); return err; diff --git a/include/fdtdec.h b/include/fdtdec.h index 5effa240af..75af750ee5 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -15,6 +15,7 @@ */ #include +#include /* * A typedef for a physical address. Note that fdt data is always big @@ -50,6 +51,49 @@ struct fdt_resource { fdt_addr_t end; }; +enum fdt_pci_space { + FDT_PCI_SPACE_CONFIG = 0, + FDT_PCI_SPACE_IO = 0x01000000, + FDT_PCI_SPACE_MEM32 = 0x02000000, + FDT_PCI_SPACE_MEM64 = 0x03000000, + FDT_PCI_SPACE_MEM32_PREF = 0x42000000, + FDT_PCI_SPACE_MEM64_PREF = 0x43000000, +}; + +#define FDT_PCI_ADDR_CELLS 3 +#define FDT_PCI_SIZE_CELLS 2 +#define FDT_PCI_REG_SIZE \ + ((FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS) * sizeof(u32)) + +/* + * The Open Firmware spec defines PCI physical address as follows: + * + * bits# 31 .... 24 23 .... 16 15 .... 08 07 .... 00 + * + * phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr + * phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh + * phys.lo cell: llllllll llllllll llllllll llllllll + * + * where: + * + * n: is 0 if the address is relocatable, 1 otherwise + * p: is 1 if addressable region is prefetchable, 0 otherwise + * t: is 1 if the address is aliased (for non-relocatable I/O) below 1MB + * (for Memory), or below 64KB (for relocatable I/O) + * ss: is the space code, denoting the address space + * bbbbbbbb: is the 8-bit Bus Number + * ddddd: is the 5-bit Device Number + * fff: is the 3-bit Function Number + * rrrrrrrr: is the 8-bit Register Number + * hhhhhhhh: is a 32-bit unsigned number + * llllllll: is a 32-bit unsigned number + */ +struct fdt_pci_addr { + u32 phys_hi; + u32 phys_mid; + u32 phys_lo; +}; + /** * Compute the size of a resource. * @@ -257,6 +301,60 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, const char *prop_name, fdt_size_t *sizep); +/** + * Look at an address property in a node and return the pci address which + * corresponds to the given type in the form of fdt_pci_addr. + * The property must hold one fdt_pci_addr with a lengh. + * + * @param blob FDT blob + * @param node node to examine + * @param type pci address type (FDT_PCI_SPACE_xxx) + * @param prop_name name of property to find + * @param addr returns pci address in the form of fdt_pci_addr + * @return 0 if ok, negative on error + */ +int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, + const char *prop_name, struct fdt_pci_addr *addr); + +/** + * Look at the compatible property of a device node that represents a PCI + * device and extract pci vendor id and device id from it. + * + * @param blob FDT blob + * @param node node to examine + * @param vendor vendor id of the pci device + * @param device device id of the pci device + * @return 0 if ok, negative on error + */ +int fdtdec_get_pci_vendev(const void *blob, int node, + u16 *vendor, u16 *device); + +/** + * Look at the pci address of a device node that represents a PCI device + * and parse the bus, device and function number from it. + * + * @param blob FDT blob + * @param node node to examine + * @param addr pci address in the form of fdt_pci_addr + * @param bdf returns bus, device, function triplet + * @return 0 if ok, negative on error + */ +int fdtdec_get_pci_bdf(const void *blob, int node, + struct fdt_pci_addr *addr, pci_dev_t *bdf); + +/** + * Look at the pci address of a device node that represents a PCI device + * and return base address of the pci device's registers. + * + * @param blob FDT blob + * @param node node to examine + * @param addr pci address in the form of fdt_pci_addr + * @param bar returns base address of the pci device's registers + * @return 0 if ok, negative on error + */ +int fdtdec_get_pci_bar32(const void *blob, int node, + struct fdt_pci_addr *addr, u32 *bar); + /** * Look up a 32-bit integer property in a node and return it. The property * must have at least 4 bytes of data. The value of the first cell is @@ -682,17 +780,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, const char *prop_names, const char *name, struct fdt_resource *res); -/** - * Look at the reg property of a device node that represents a PCI device - * and parse the bus, device and function number from it. - * - * @param fdt FDT blob - * @param node node to examine - * @param bdf returns bus, device, function triplet - * @return 0 if ok, negative on error - */ -int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf); - /** * Decode a named region within a memory bank of a given type. * diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 745b390836..487122eebc 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -126,6 +126,163 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, return fdtdec_get_addr_size(blob, node, prop_name, NULL); } +#ifdef CONFIG_PCI +int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, + const char *prop_name, struct fdt_pci_addr *addr) +{ + const u32 *cell; + int len; + int ret = -ENOENT; + + debug("%s: %s: ", __func__, prop_name); + + /* + * If we follow the pci bus bindings strictly, we should check + * the value of the node's parent node's #address-cells and + * #size-cells. They need to be 3 and 2 accordingly. However, + * for simplicity we skip the check here. + */ + cell = fdt_getprop(blob, node, prop_name, &len); + if (!cell) + goto fail; + + if ((len % FDT_PCI_REG_SIZE) == 0) { + int num = len / FDT_PCI_REG_SIZE; + int i; + + for (i = 0; i < num; i++) { + debug("pci address #%d: %08lx %08lx %08lx\n", i, + (ulong)fdt_addr_to_cpu(cell[0]), + (ulong)fdt_addr_to_cpu(cell[1]), + (ulong)fdt_addr_to_cpu(cell[2])); + if ((fdt_addr_to_cpu(*cell) & type) == type) { + addr->phys_hi = fdt_addr_to_cpu(cell[0]); + addr->phys_mid = fdt_addr_to_cpu(cell[1]); + addr->phys_lo = fdt_addr_to_cpu(cell[2]); + break; + } else { + cell += (FDT_PCI_ADDR_CELLS + + FDT_PCI_SIZE_CELLS); + } + } + + if (i == num) + goto fail; + + return 0; + } else { + ret = -EINVAL; + } + +fail: + debug("(not found)\n"); + return ret; +} + +int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device) +{ + const char *list, *end; + int len; + + list = fdt_getprop(blob, node, "compatible", &len); + if (!list) + return -ENOENT; + + end = list + len; + while (list < end) { + char *s; + + len = strlen(list); + if (len >= strlen("pciVVVV,DDDD")) { + s = strstr(list, "pci"); + + /* + * check if the string is something like pciVVVV,DDDD.RR + * or just pciVVVV,DDDD + */ + if (s && s[7] == ',' && + (s[12] == '.' || s[12] == 0)) { + s += 3; + *vendor = simple_strtol(s, NULL, 16); + + s += 5; + *device = simple_strtol(s, NULL, 16); + + return 0; + } + } else { + list += (len + 1); + } + } + + return -ENOENT; +} + +int fdtdec_get_pci_bdf(const void *blob, int node, + struct fdt_pci_addr *addr, pci_dev_t *bdf) +{ + u16 dt_vendor, dt_device, vendor, device; + int ret; + + /* get vendor id & device id from the compatible string */ + ret = fdtdec_get_pci_vendev(blob, node, &dt_vendor, &dt_device); + if (ret) + return ret; + + /* extract the bdf from fdt_pci_addr */ + *bdf = addr->phys_hi & 0xffff00; + + /* read vendor id & device id based on bdf */ + pci_read_config_word(*bdf, PCI_VENDOR_ID, &vendor); + pci_read_config_word(*bdf, PCI_DEVICE_ID, &device); + + /* + * Note there are two places in the device tree to fully describe + * a pci device: one is via compatible string with a format of + * "pciVVVV,DDDD" and the other one is the bdf numbers encoded in + * the device node's reg address property. We read the vendor id + * and device id based on bdf and compare the values with the + * "VVVV,DDDD". If they are the same, then we are good to use bdf + * to read device's bar. But if they are different, we have to rely + * on the vendor id and device id extracted from the compatible + * string and locate the real bdf by pci_find_device(). This is + * because normally we may only know device's device number and + * function number when writing device tree. The bus number is + * dynamically assigned during the pci enumeration process. + */ + if ((dt_vendor != vendor) || (dt_device != device)) { + *bdf = pci_find_device(dt_vendor, dt_device, 0); + if (*bdf == -1) + return -ENODEV; + } + + return 0; +} + +int fdtdec_get_pci_bar32(const void *blob, int node, + struct fdt_pci_addr *addr, u32 *bar) +{ + pci_dev_t bdf; + int barnum; + int ret; + + /* get pci devices's bdf */ + ret = fdtdec_get_pci_bdf(blob, node, addr, &bdf); + if (ret) + return ret; + + /* extract the bar number from fdt_pci_addr */ + barnum = addr->phys_hi & 0xff; + if ((barnum < PCI_BASE_ADDRESS_0) || (barnum > PCI_CARDBUS_CIS)) + return -EINVAL; + + barnum = (barnum - PCI_BASE_ADDRESS_0) / 4; + *bar = pci_read_bar32(pci_bus_to_hose(PCI_BUS(bdf)), bdf, barnum); + + return 0; +} +#endif + uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name, uint64_t default_val) { @@ -795,20 +952,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, return fdt_get_resource(fdt, node, property, index, res); } -int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf) -{ - const fdt32_t *prop; - int len; - - prop = fdt_getprop(fdt, node, "reg", &len); - if (!prop) - return len; - - *bdf = fdt32_to_cpu(*prop) & 0xffffff; - - return 0; -} - int fdtdec_decode_memory_region(const void *blob, int config_node, const char *mem_type, const char *suffix, fdt_addr_t *basep, fdt_size_t *sizep) From 3db886a5bf38700b51a1d7a7b00ec8b64c9c2089 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 31 Dec 2014 16:05:12 +0800 Subject: [PATCH 09/45] serial: ns16550: Support ns16550 compatible pci uart devices There are many pci uart devices which are ns16550 compatible. We can describe them in the board dts file and use it as the U-Boot serial console as specified in the chosen node 'stdout-path' property. Those pci uart devices can have their register be memory-mapped, or i/o-mapped. The driver will try to use the memory-mapped register if the reg property in the node has an entry to describe the memory-mapped register, otherwise i/o-mapped register will be used. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/serial/ns16550.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index af5beba39f..70c946249f 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -289,7 +289,38 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) struct ns16550_platdata *plat = dev->platdata; fdt_addr_t addr; + /* try Processor Local Bus device first */ addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); +#ifdef CONFIG_PCI + if (addr == FDT_ADDR_T_NONE) { + /* then try pci device */ + struct fdt_pci_addr pci_addr; + u32 bar; + int ret; + + /* we prefer to use a memory-mapped register */ + ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, + FDT_PCI_SPACE_MEM32, "reg", + &pci_addr); + if (ret) { + /* try if there is any i/o-mapped register */ + ret = fdtdec_get_pci_addr(gd->fdt_blob, + dev->of_offset, + FDT_PCI_SPACE_IO, + "reg", &pci_addr); + if (ret) + return ret; + } + + ret = fdtdec_get_pci_bar32(gd->fdt_blob, dev->of_offset, + &pci_addr, &bar); + if (ret) + return ret; + + addr = bar; + } +#endif + if (addr == FDT_ADDR_T_NONE) return -EINVAL; From 1eb47efc49f1db8384f62c12f82b27d2bfbbae2e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 31 Dec 2014 16:05:13 +0800 Subject: [PATCH 10/45] x86: Use ePAPR defined properties for x86-uart Use ePAPR defined properties for x86-uart: clock-frequency and current-speed. Assign the value of clock-frequency in device tree to plat->clock of x86-uart instead of using hardcoded number. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/serial.dtsi | 5 ++--- drivers/serial/serial_x86.c | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi index ebdda763df..9b097f4f9b 100644 --- a/arch/x86/dts/serial.dtsi +++ b/arch/x86/dts/serial.dtsi @@ -3,8 +3,7 @@ compatible = "x86-uart"; reg = <0x3f8 8>; reg-shift = <0>; - io-mapped = <1>; - multiplier = <1>; - baudrate = <115200>; + clock-frequency = <1843200>; + current-speed = <115200>; }; }; diff --git a/drivers/serial/serial_x86.c b/drivers/serial/serial_x86.c index e81e035ec2..4bf6062c64 100644 --- a/drivers/serial/serial_x86.c +++ b/drivers/serial/serial_x86.c @@ -6,9 +6,12 @@ #include #include +#include #include #include +DECLARE_GLOBAL_DATA_PTR; + static const struct udevice_id x86_serial_ids[] = { { .compatible = "x86-uart" }, { } @@ -22,10 +25,13 @@ static int x86_serial_ofdata_to_platdata(struct udevice *dev) ret = ns16550_serial_ofdata_to_platdata(dev); if (ret) return ret; - plat->clock = 1843200; + + plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "clock-frequency", 1843200); return 0; } + U_BOOT_DRIVER(serial_ns16550) = { .name = "serial_x86", .id = UCLASS_SERIAL, From b21b208184721eed198bdf59204b452716986377 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 31 Dec 2014 16:05:14 +0800 Subject: [PATCH 11/45] x86: crownbay: Add pci devices in the dts file The Topcliff PCH has 4 UART devices integrated (Device 10, Funciton 1/2/3/4). Add the corresponding device nodes in the crownbay.dts per Open Firmware PCI bus bindings. Also a comment block is added for the 'stdout-path' property in the chosen node, mentioning that by default the legacy superio serial port (io addr 0x3f8) is still used on Crown Bay as the console port. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/crownbay.dts | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 97f7a525aa..e81054ebc5 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -32,6 +32,14 @@ }; chosen { + /* + * By default the legacy superio serial port is used as the + * U-Boot serial console. If we want to use UART from Topcliff + * PCH as the console, change this property to &pciuart#. + * + * For example, stdout-path = &pciuart0 will use the first + * UART on Topcliff PCH. + */ stdout-path = "/serial"; }; @@ -52,4 +60,77 @@ }; }; + pci { + #address-cells = <3>; + #size-cells = <2>; + compatible = "intel,pci"; + device_type = "pci"; + + pcie@17,0 { + #address-cells = <3>; + #size-cells = <2>; + compatible = "intel,pci"; + device_type = "pci"; + + topcliff@0,0 { + #address-cells = <3>; + #size-cells = <2>; + compatible = "intel,pci"; + device_type = "pci"; + + pciuart0: uart@a,1 { + compatible = "pci8086,8811.00", + "pci8086,8811", + "pciclass,070002", + "pciclass,0700", + "x86-uart"; + reg = <0x00025100 0x0 0x0 0x0 0x0 + 0x01025110 0x0 0x0 0x0 0x0>; + reg-shift = <0>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; + + pciuart1: uart@a,2 { + compatible = "pci8086,8812.00", + "pci8086,8812", + "pciclass,070002", + "pciclass,0700", + "x86-uart"; + reg = <0x00025200 0x0 0x0 0x0 0x0 + 0x01025210 0x0 0x0 0x0 0x0>; + reg-shift = <0>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; + + pciuart2: uart@a,3 { + compatible = "pci8086,8813.00", + "pci8086,8813", + "pciclass,070002", + "pciclass,0700", + "x86-uart"; + reg = <0x00025300 0x0 0x0 0x0 0x0 + 0x01025310 0x0 0x0 0x0 0x0>; + reg-shift = <0>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; + + pciuart3: uart@a,4 { + compatible = "pci8086,8814.00", + "pci8086,8814", + "pciclass,070002", + "pciclass,0700", + "x86-uart"; + reg = <0x00025400 0x0 0x0 0x0 0x0 + 0x01025410 0x0 0x0 0x0 0x0>; + reg-shift = <0>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; + }; + }; + }; + }; From bbd43d659c55c3fedddae1eba2a520bc8a93d3fd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:17:54 -0700 Subject: [PATCH 12/45] x86: Correct XIP_ROM_SIZE This should default to the size of the ROM for faster execution before relocation. Signed-off-by: Simon Glass --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ebf72b3ee0..7d007bb60a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -53,7 +53,7 @@ config RAMTOP config XIP_ROM_SIZE hex - default 0x10000 + default ROM_SIZE config CPU_ADDR_BITS int From 6c911c4322a295e0e5ab07c12c793d1f00670028 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:17:55 -0700 Subject: [PATCH 13/45] x86: Drop RAMTOP Kconfig We don't need this in U-Boot since we calculate it based on available memory. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/Kconfig | 4 ---- arch/x86/include/asm/mtrr.h | 8 -------- 2 files changed, 12 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7d007bb60a..e992e647cc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -47,10 +47,6 @@ config RAMBASE hex default 0x100000 -config RAMTOP - hex - default 0x200000 - config XIP_ROM_SIZE hex default ROM_SIZE diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 5f05a4848f..dcc995dbb6 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -100,10 +100,6 @@ static inline long x86_mtrr_rom_cache_var_index(void) { return -1; } #endif -#if !defined(CONFIG_RAMTOP) -# error "CONFIG_RAMTOP not defined" -#endif - #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) # error "CONFIG_XIP_ROM_SIZE is not a power of 2" #endif @@ -114,8 +110,4 @@ static inline long x86_mtrr_rom_cache_var_index(void) { return -1; } #define CACHE_ROM_BASE (((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12) -#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0 -# error "CONFIG_RAMTOP must be a power of 2" -#endif - #endif From 8a388085c70d0da306cbd0dc644606cf8be24486 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:17:56 -0700 Subject: [PATCH 14/45] x86: Correct ifdtool microcode calculation This currently assumes that U-Boot resides at the start of ROM. Update it to remove this assumption. Signed-off-by: Simon Glass Tested-by: Bin Meng --- tools/ifdtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ifdtool.c b/tools/ifdtool.c index fe8366ba4f..590ccc914b 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -788,9 +788,9 @@ static int write_uboot(char *image, int size, struct input_file *uboot, fdt_strerror(data_size)); return -ENOENT; } - offset = ucode_ptr - uboot->addr; + offset = (uint32_t)(ucode_ptr + size); ptr = (void *)image + offset; - ptr[0] = uboot->addr + (data - image); + ptr[0] = (data - image) - size; ptr[1] = data_size; debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", ucode_ptr, ptr[0], ptr[1]); From 6dcc8159849a88610205d5d2e67107a76ac2189d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:17:59 -0700 Subject: [PATCH 15/45] x86: video: Add a debug() to display the frame buffer address Provide a way to display this address when booting. Signed-off-by: Simon Glass --- drivers/video/x86_fb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c index 8743a8c319..6641033a5d 100644 --- a/drivers/video/x86_fb.c +++ b/drivers/video/x86_fb.c @@ -32,6 +32,7 @@ void *video_hw_init(void) sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY, bits_per_pixel); printf("%s\n", gdev->modeIdent); + debug("Frame buffer at %x\n", gdev->frameAdrs); return (void *)gdev; } From 23609c71dc0c4a433b7189308cda25d1b9e70c43 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:00 -0700 Subject: [PATCH 16/45] x86: pci: Don't return a vesa mode when there is not video If the video has not been set up, we should not return a success code. This can be detected by seeing if any of the variables are non-zero. Signed-off-by: Simon Glass --- drivers/pci/pci_rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index af6a3ae00c..9808bb385e 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -205,7 +205,7 @@ int vbe_get_video_info(struct graphic_device *gdev) gdev->vprBase = vesa->phys_base_ptr; gdev->cprBase = vesa->phys_base_ptr; - return 0; + return gdev->winSizeX ? 0 : -ENOSYS; #else return -ENOSYS; #endif From fba7eac1c84aa674696fea55ac3a37f1e7156181 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:01 -0700 Subject: [PATCH 17/45] x86: video: Add debug option to time the BIOS copy This can be very slow - typically 80ms even on a fast machine since it uses the SPI flash to read the data. Add an option to display the time taken. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 9808bb385e..5ba315b2ad 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -156,6 +156,8 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header, target = (void *)PCI_VGA_RAM_IMAGE_START; if (target != rom_header) { + ulong start = get_timer(0); + debug("Copying VGA ROM Image from %p to %p, 0x%x bytes\n", rom_header, target, rom_size); memcpy(target, rom_header, rom_size); @@ -163,6 +165,7 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header, printf("VGA ROM copy failed\n"); return -EFAULT; } + debug("Copy took %lums\n", get_timer(start)); } *ram_headerp = target; From d19ee5c27ec0c144bae294b4317e03738616a593 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:02 -0700 Subject: [PATCH 18/45] x86: ivybridge: Only run the Video BIOS when video is enabled This takes about about 700ms on link when running natively and 900ms when running using the emulator. It is a waste of time if video is not enabled, so don't bother running the video BIOS in that case. We could add a command to run the video BIOS later when needed, but this is not considered at present. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/gma.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index 3d7f740273..cf4f87c4e3 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -15,6 +15,7 @@ #include #include #include +#include struct gt_powermeter { u16 reg; @@ -730,6 +731,9 @@ static int int15_handler(void) int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, const void *blob, int node) { +#ifdef CONFIG_VIDEO + ulong start; +#endif void *gtt_bar; u32 reg32; int ret; @@ -745,8 +749,11 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, if (ret) return ret; +#ifdef CONFIG_VIDEO + start = get_timer(0); ret = pci_run_vga_bios(dev, int15_handler, false); - + debug("BIOS ran in %lums\n", get_timer(start)); +#endif /* Post VBIOS init */ ret = gma_pm_init_post_vbios(gtt_bar, blob, node); if (ret) From 818f602112f5e789704096dbc4a7eb9f63fe5718 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:03 -0700 Subject: [PATCH 19/45] x86: Use cache, don't clear the display in video BIOS There is no need to run with the cache disabled, and there is no point in clearing the display frame buffer since U-Boot does it later. Signed-off-by: Simon Glass --- arch/x86/lib/bios.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index d1f8933e12..42853489fb 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -210,8 +210,8 @@ static u8 vbe_set_mode(struct vbe_mode_info *mi) debug("VBE: Setting VESA mode %#04x\n", mi->video_mode); /* request linear framebuffer mode */ mi->video_mode |= (1 << 14); - /* request clearing of framebuffer */ - mi->video_mode &= ~(1 << 15); + /* don't clear the framebuffer, we do that later */ + mi->video_mode |= (1 << 15); realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode, 0x0000, 0x0000, 0x0000, 0x0000); @@ -262,7 +262,6 @@ void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode, /* Make sure the code is placed. */ setup_realmode_code(); - disable_caches(); debug("Calling Option ROM at %lx, pci device %#x...", addr, num_dev); /* Option ROM entry point is at OPROM start + 3 */ From f4a6f0aed0be1f941aa786924c2fff0c01fbf91b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:04 -0700 Subject: [PATCH 20/45] x86: Tidy up VESA mode numbers There are some bits which should be ignored when displaying the mode number. Make sure that they are not included in the mode that is displayed. Signed-off-by: Simon Glass --- arch/x86/lib/bios.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 42853489fb..1d75cfc263 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -207,12 +207,14 @@ static u8 vbe_get_mode_info(struct vbe_mode_info *mi) static u8 vbe_set_mode(struct vbe_mode_info *mi) { - debug("VBE: Setting VESA mode %#04x\n", mi->video_mode); + int video_mode = mi->video_mode; + + debug("VBE: Setting VESA mode %#04x\n", video_mode); /* request linear framebuffer mode */ - mi->video_mode |= (1 << 14); + video_mode |= (1 << 14); /* don't clear the framebuffer, we do that later */ - mi->video_mode |= (1 << 15); - realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode, + video_mode |= (1 << 15); + realmode_interrupt(0x10, VESA_SET_MODE, video_mode, 0x0000, 0x0000, 0x0000, 0x0000); return 0; @@ -236,6 +238,7 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info) return; } + mode_info->video_mode &= 0x3ff; vbe_set_mode(mode_info); } From 9a99caf3f3e220d744525d492f7e72a5c8756374 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:05 -0700 Subject: [PATCH 21/45] x86: pci: Display vesa modes in hex The hex value is more commonly understood, so use that instead of decimal. Add a 0x prefix to avoid confusion. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 5ba315b2ad..7d25cc9f2f 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -247,7 +247,7 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) defined(CONFIG_FRAMEBUFFER_VESA_MODE) vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE; #endif - debug("Selected vesa mode %d\b", vesa_mode); + debug("Selected vesa mode %#x\n", vesa_mode); if (emulate) { #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; @@ -275,7 +275,7 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) return -ENOSYS; #endif } - debug("Final vesa mode %d\n", mode_info.video_mode); + debug("Final vesa mode %#x\n", mode_info.video_mode); return 0; } From 3a5659f7cfc0fd99b57fe2ed9e4a9ebde7cf8491 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:06 -0700 Subject: [PATCH 22/45] x86: ivybridge: Drop support for ROM caching This is set up along with CAR (Cache-as-RAM) anyway. When we relocate we don't really need ROM caching (we read the VGA BIOS from ROM but that is about it) Drop it. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/cpu.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 969b07b059..0543e06aef 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -49,27 +49,6 @@ static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev) pci_hose_write_config_byte(hose, dev, 0xdc, reg8); } -static void set_var_mtrr( - unsigned reg, unsigned base, unsigned size, unsigned type) - -{ - /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ - /* FIXME: It only support 4G less range */ - wrmsr(MTRRphysBase_MSR(reg), base | type, 0); - wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid, - (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1); -} - -static void enable_rom_caching(void) -{ - disable_caches(); - set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT); - enable_caches(); - - /* Enable Variable MTRRs */ - wrmsr(MTRRdefType_MSR, 0x800, 0); -} - static int set_flex_ratio_to_tdp_nominal(void) { msr_t flex_ratio, msr; @@ -165,10 +144,6 @@ int arch_cpu_init(void) /* This is already done in start.S, but let's do it in C */ enable_port80_on_lpc(hose, PCH_LPC_DEV); - /* already done in car.S */ - if (false) - enable_rom_caching(); - set_spi_speed(); /* From aff2523f6998dca1f667aa0d26cc8f351c5628dc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:07 -0700 Subject: [PATCH 23/45] x86: Add support for MTRRs Memory Type Range Registers are used to tell the CPU whether memory is cacheable and if so the cache write mode to use. Clean up the existing header file to follow style, and remove the unneeded code. These can speed up booting so should be supported. Add these to global_data so they can be requested while booting. We will apply the changes during relocation (in a later commit). Signed-off-by: Simon Glass --- arch/x86/cpu/Makefile | 1 + arch/x86/cpu/coreboot/coreboot.c | 22 ++--- arch/x86/cpu/ivybridge/car.S | 12 +-- arch/x86/cpu/mtrr.c | 81 ++++++++++++++++ arch/x86/include/asm/global_data.h | 15 +++ arch/x86/include/asm/mtrr.h | 145 ++++++++++++++--------------- 6 files changed, 181 insertions(+), 95 deletions(-) create mode 100644 arch/x86/cpu/mtrr.c diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 5033d2b757..62e43c04e5 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -17,5 +17,6 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ obj-y += lapic.o +obj-y += mtrr.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index cfacc05875..6d06d5af19 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -64,11 +65,6 @@ int board_eth_init(bd_t *bis) return pci_eth_init(bis); } -#define MTRR_TYPE_WP 5 -#define MTRRcap_MSR 0xfe -#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) -#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) - void board_final_cleanup(void) { /* Un-cache the ROM so the kernel has one @@ -77,15 +73,17 @@ void board_final_cleanup(void) * Coreboot should have assigned this to the * top available variable MTRR. */ - u8 top_mtrr = (native_read_msr(MTRRcap_MSR) & 0xff) - 1; - u8 top_type = native_read_msr(MTRRphysBase_MSR(top_mtrr)) & 0xff; + u8 top_mtrr = (native_read_msr(MTRR_CAP_MSR) & 0xff) - 1; + u8 top_type = native_read_msr(MTRR_PHYS_BASE_MSR(top_mtrr)) & 0xff; /* Make sure this MTRR is the correct Write-Protected type */ - if (top_type == MTRR_TYPE_WP) { - disable_caches(); - wrmsrl(MTRRphysBase_MSR(top_mtrr), 0); - wrmsrl(MTRRphysMask_MSR(top_mtrr), 0); - enable_caches(); + if (top_type == MTRR_TYPE_WRPROT) { + struct mtrr_state state; + + mtrr_open(&state); + wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0); + wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0); + mtrr_close(&state); } /* Issue SMI to Coreboot to lock down ME and registers */ diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index dca68e4144..72b22ea9e4 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -61,7 +61,7 @@ clear_mtrrs: post_code(POST_CAR_MTRR) /* Configure the default memory type to uncacheable */ - movl $MTRRdefType_MSR, %ecx + movl $MTRR_DEF_TYPE_MSR, %ecx rdmsr andl $(~0x00000cff), %eax wrmsr @@ -76,16 +76,16 @@ clear_mtrrs: post_code(POST_CAR_BASE_ADDRESS) /* Set Cache-as-RAM mask */ movl $(MTRR_PHYS_MASK_MSR(0)), %ecx - movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax movl $CPU_PHYSMASK_HI, %edx wrmsr post_code(POST_CAR_MASK) /* Enable MTRR */ - movl $MTRRdefType_MSR, %ecx + movl $MTRR_DEF_TYPE_MSR, %ecx rdmsr - orl $MTRRdefTypeEn, %eax + orl $MTRR_DEF_TYPE_EN, %eax wrmsr /* Enable cache (CR0.CD = 0, CR0.NW = 0) */ @@ -130,7 +130,7 @@ clear_mtrrs: movl $MTRR_PHYS_MASK_MSR(1), %ecx movl $CPU_PHYSMASK_HI, %edx - movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax wrmsr post_code(POST_CAR_ROM_CACHE) @@ -141,7 +141,7 @@ clear_mtrrs: xorl %edx, %edx wrmsr movl $MTRR_PHYS_MASK_MSR(2), %ecx - movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax + movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax movl $CPU_PHYSMASK_HI, %edx wrmsr #endif diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c new file mode 100644 index 0000000000..d5a825d181 --- /dev/null +++ b/arch/x86/cpu/mtrr.c @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Memory Type Range Regsters - these are used to tell the CPU whether + * memory is cacheable and if so the cache write mode to use. + * + * These can speed up booting. See the mtrr command. + * + * Reference: Intel Architecture Software Developer's Manual, Volume 3: + * System Programming + */ + +#include +#include +#include +#include + +/* Prepare to adjust MTRRs */ +void mtrr_open(struct mtrr_state *state) +{ + state->enable_cache = dcache_status(); + + if (state->enable_cache) + disable_caches(); + state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); + wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); +} + +/* Clean up after adjusting MTRRs, and enable them */ +void mtrr_close(struct mtrr_state *state) +{ + wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); + if (state->enable_cache) + enable_caches(); +} + +int mtrr_commit(bool do_caches) +{ + struct mtrr_request *req = gd->arch.mtrr_req; + struct mtrr_state state; + uint64_t mask; + int i; + + mtrr_open(&state); + for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { + mask = ~(req->size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type); + wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID); + } + + /* Clear the ones that are unused */ + for (; i < MTRR_COUNT; i++) + wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); + mtrr_close(&state); + + return 0; +} + +int mtrr_add_request(int type, uint64_t start, uint64_t size) +{ + struct mtrr_request *req; + uint64_t mask; + + if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS) + return -ENOSPC; + req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++]; + req->type = type; + req->start = start; + req->size = size; + debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1, + req->type, req->start, req->size); + mask = ~(req->size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + mask |= MTRR_PHYS_MASK_VALID; + debug(" %016llx %016llx\n", req->start | req->type, mask); + + return 0; +} diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index aeab3e52e3..24e305239b 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -29,6 +29,19 @@ struct memory_info { struct memory_area area[CONFIG_NR_DRAM_BANKS]; }; +#define MAX_MTRR_REQUESTS 8 + +/** + * A request for a memory region to be set up in a particular way. These + * requests are processed before board_init_r() is called. They are generally + * optional and can be ignored with some performance impact. + */ +struct mtrr_request { + int type; /* MTRR_TYPE_... */ + uint64_t start; + uint64_t size; +}; + /* Architecture-specific global data */ struct arch_global_data { struct global_data *gd_addr; /* Location of Global Data */ @@ -49,6 +62,8 @@ struct arch_global_data { #ifdef CONFIG_HAVE_FSP void *hob_list; /* FSP HOB list */ #endif + struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS]; + int mtrr_req_count; }; #endif diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index dcc995dbb6..3c1174043c 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -9,94 +9,85 @@ #ifndef _ASM_MTRR_H #define _ASM_MTRR_H -/* These are the region types */ -#define MTRR_TYPE_UNCACHEABLE 0 -#define MTRR_TYPE_WRCOMB 1 -/*#define MTRR_TYPE_ 2*/ -/*#define MTRR_TYPE_ 3*/ -#define MTRR_TYPE_WRTHROUGH 4 -#define MTRR_TYPE_WRPROT 5 -#define MTRR_TYPE_WRBACK 6 -#define MTRR_NUM_TYPES 7 +/* MTRR region types */ +#define MTRR_TYPE_UNCACHEABLE 0 +#define MTRR_TYPE_WRCOMB 1 +#define MTRR_TYPE_WRTHROUGH 4 +#define MTRR_TYPE_WRPROT 5 +#define MTRR_TYPE_WRBACK 6 -#define MTRRcap_MSR 0x0fe -#define MTRRdefType_MSR 0x2ff +#define MTRR_TYPE_COUNT 7 -#define MTRRdefTypeEn (1 << 11) -#define MTRRdefTypeFixEn (1 << 10) +#define MTRR_CAP_MSR 0x0fe +#define MTRR_DEF_TYPE_MSR 0x2ff -#define SMRRphysBase_MSR 0x1f2 -#define SMRRphysMask_MSR 0x1f3 +#define MTRR_DEF_TYPE_EN (1 << 11) +#define MTRR_DEF_TYPE_FIX_EN (1 << 10) -#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) -#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) +#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) +#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) -#define MTRRphysMaskValid (1 << 11) +#define MTRR_PHYS_MASK_VALID (1 << 11) -#define NUM_FIXED_RANGES 88 -#define RANGES_PER_FIXED_MTRR 8 -#define MTRRfix64K_00000_MSR 0x250 -#define MTRRfix16K_80000_MSR 0x258 -#define MTRRfix16K_A0000_MSR 0x259 -#define MTRRfix4K_C0000_MSR 0x268 -#define MTRRfix4K_C8000_MSR 0x269 -#define MTRRfix4K_D0000_MSR 0x26a -#define MTRRfix4K_D8000_MSR 0x26b -#define MTRRfix4K_E0000_MSR 0x26c -#define MTRRfix4K_E8000_MSR 0x26d -#define MTRRfix4K_F0000_MSR 0x26e -#define MTRRfix4K_F8000_MSR 0x26f +#define MTRR_BASE_TYPE_MASK 0x7 + +/* Number of MTRRs supported */ +#define MTRR_COUNT 8 #if !defined(__ASSEMBLER__) -/* - * The MTRR code has some side effects that the callers should be aware for. - * 1. The call sequence matters. x86_setup_mtrrs() calls - * x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent - * of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers - * want to call the components of x86_setup_mtrrs() because of other - * rquirements the ordering should still preserved. - * 2. enable_fixed_mtrr() will enable both variable and fixed MTRRs because - * of the nature of the global MTRR enable flag. Therefore, all direct - * or indirect callers of enable_fixed_mtrr() should ensure that the - * variable MTRR MSRs do not contain bad ranges. - * 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling - * the caching of the ROM. However, it is set to uncacheable (UC). It - * is the responsiblity of the caller to enable it by calling - * x86_mtrr_enable_rom_caching(). +/** + * Information about the previous MTRR state, set up by mtrr_open() + * + * @deftype: Previous value of MTRR_DEF_TYPE_MSR + * @enable_cache: true if cache was enabled */ -void x86_setup_mtrrs(void); -/* - * x86_setup_var_mtrrs() parameters: - * address_bits - number of physical address bits supported by cpu - * above4gb - 2 means dynamically detect number of variable MTRRs available. - * non-zero means handle memory ranges above 4GiB. - * 0 means ignore memory ranges above 4GiB +struct mtrr_state { + uint64_t deftype; + bool enable_cache; +}; + +/** + * mtrr_open() - Prepare to adjust MTRRs + * + * Use mtrr_open() passing in a structure - this function will init it. Then + * when done, pass the same structure to mtrr_close() to re-enable MTRRs and + * possibly the cache. + * + * @state: Empty structure to pass in to hold settings */ -void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb); -void enable_fixed_mtrr(void); -void x86_setup_fixed_mtrrs(void); -/* Set up fixed MTRRs but do not enable them. */ -void x86_setup_fixed_mtrrs_no_enable(void); -int x86_mtrr_check(void); -/* ROM caching can be used after variable MTRRs are set up. Beware that - * enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on - * one's IO hole size and WRCOMB resources. Be sure to check the console - * log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that - * on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the - * rom caching will be disabled if all threads run the MTRR code. Therefore, - * one needs to call x86_mtrr_enable_rom_caching() after all threads of the - * same core have run the MTRR code. */ -#if CONFIG_CACHE_ROM -void x86_mtrr_enable_rom_caching(void); -void x86_mtrr_disable_rom_caching(void); -/* Return the variable range MTRR index of the ROM cache. */ -long x86_mtrr_rom_cache_var_index(void); -#else -static inline void x86_mtrr_enable_rom_caching(void) {} -static inline void x86_mtrr_disable_rom_caching(void) {} -static inline long x86_mtrr_rom_cache_var_index(void) { return -1; } -#endif /* CONFIG_CACHE_ROM */ +void mtrr_open(struct mtrr_state *state); + +/** + * mtrr_open() - Clean up after adjusting MTRRs, and enable them + * + * This uses the structure containing information returned from mtrr_open(). + * + * @state: Structure from mtrr_open() + */ +/* */ +void mtrr_close(struct mtrr_state *state); + +/** + * mtrr_add_request() - Add a new MTRR request + * + * This adds a request for a memory region to be set up in a particular way. + * + * @type: Requested type (MTRR_TYPE_) + * @start: Start address + * @size: Size + */ +int mtrr_add_request(int type, uint64_t start, uint64_t size); + +/** + * mtrr_commit() - set up the MTRR registers based on current requests + * + * This sets up MTRRs for the available DRAM and the requests received so far. + * It must be called with caches disabled. + * + * @do_caches: true if caches are currently on + */ +int mtrr_commit(bool do_caches); #endif From 9818a00eead58a36fe39735dae5dbdc393f53463 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:08 -0700 Subject: [PATCH 24/45] x86: ivybridge: Set up an MTRR for the video frame buffer Set the frame buffer to write-combining. This makes it faster, although for scrolling write-through is even faster for U-Boot. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/gma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index cf4f87c4e3..6cf9654e02 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -735,6 +736,7 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, ulong start; #endif void *gtt_bar; + ulong base; u32 reg32; int ret; @@ -743,6 +745,11 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; pci_write_config32(dev, PCI_COMMAND, reg32); + /* Use write-combining for the graphics memory, 256MB */ + base = pci_read_bar32(hose, dev, 2); + mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); + mtrr_commit(true); + gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0); debug("GT bar %p\n", gtt_bar); ret = gma_pm_init_pre_vbios(gtt_bar); From 313aef37a12703b32a75dfc15b50491ecc43d97a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:09 -0700 Subject: [PATCH 25/45] x86: board_f: Adjust x86 boot order for performance For bare platforms we turn off ROM-caching before calling board_init_f_r() It is then very slow to copy U-Boot from ROM to RAM. So adjust the order so that the copying happens before we turn off ROM-caching. Signed-off-by: Simon Glass --- common/board_f.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/board_f.c b/common/board_f.c index cfd77f8653..3a4b32c29d 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -985,6 +985,11 @@ static init_fnc_t init_sequence_f[] = { INIT_FUNC_WATCHDOG_RESET reloc_fdt, setup_reloc, +#ifdef CONFIG_X86 + copy_uboot_to_ram, + clear_bss, + do_elf_reloc_fixups, +#endif #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) jump_to_copy, #endif @@ -1044,9 +1049,6 @@ void board_init_f(ulong boot_flags) */ static init_fnc_t init_sequence_f_r[] = { init_cache_f_r, - copy_uboot_to_ram, - clear_bss, - do_elf_reloc_fixups, NULL, }; From aaafcd6c3f472f81d2c87b96571fba2e0f55b368 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:10 -0700 Subject: [PATCH 26/45] x86: ivybridge: Request MTRRs for DRAM regions We should use MTRRs to speed up execution. Add a list of MTRR requests which will dealt with when we relocate and run from RAM. We set RAM as cacheable (with write-back) and registers as non-cacheable. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/sdram.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index b95e781bbf..95047359ff 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -430,6 +431,15 @@ static int sdram_find(pci_dev_t dev) add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); add_memory_area(info, 1ULL << 32, touud); + + /* Add MTRRs for memory */ + mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); + mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20); + mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20); + mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20); + mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20), + 32 << 20); + /* * If >= 4GB installed then memory from TOLUD to 4GB * is remapped above TOM, TOUUD will account for both From db55bd7dad9a2c30c8da884bf20273945e240430 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:11 -0700 Subject: [PATCH 27/45] x86: Commit the current MTRRs before relocation Once we stop running from ROM we should set up the MTTRs to speed up execution. This is only needed for platforms that don't have an FSP. Also in the Coreboot case, the MTRRs are set up for us. Signed-off-by: Simon Glass --- arch/x86/lib/init_helpers.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index be4eb12c53..fc211d9d5c 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -7,6 +7,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -66,6 +67,13 @@ int calculate_relocation_address(void) int init_cache_f_r(void) { +#if defined(CONFIG_X86_RESET_VECTOR) & !defined(CONFIG_HAVE_FSP) + int ret; + + ret = mtrr_commit(false); + if (ret) + return ret; +#endif /* Initialise the CPU cache(s) */ return init_cache(); } From 7b00896ade7ee93504b5e5782bebe680705de1f6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:12 -0700 Subject: [PATCH 28/45] x86: ivybridge: Add a way to turn off the CAR Cache-as-RAM should be turned off when we relocate since we want to run from RAM. Add a function to perform this task. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/car.S | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index 72b22ea9e4..d5f1acfe3d 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -163,6 +163,52 @@ wait_for_sipi: /* return */ jmp car_init_ret +.globl car_uninit +car_uninit: + /* Disable cache */ + movl %cr0, %eax + orl $X86_CR0_CD, %eax + movl %eax, %cr0 + + /* Disable MTRRs */ + movl $MTRR_DEF_TYPE_MSR, %ecx + rdmsr + andl $(~MTRR_DEF_TYPE_EN), %eax + wrmsr + + /* Disable the no-eviction run state */ + movl NOEVICTMOD_MSR, %ecx + rdmsr + andl $~2, %eax + wrmsr + + invd + + /* Disable the no-eviction mode */ + rdmsr + andl $~1, %eax + wrmsr + +#ifdef CONFIG_CACHE_MRC_BIN + /* Clear the MTRR that was used to cache MRC */ + xorl %eax, %eax + xorl %edx, %edx + movl $MTRR_PHYS_BASE_MSR(2), %ecx + wrmsr + movl $MTRR_PHYS_MASK_MSR(2), %ecx + wrmsr +#endif + + /* Enable MTRRs */ + movl $MTRR_DEF_TYPE_MSR, %ecx + rdmsr + orl $MTRR_DEF_TYPE_EN, %eax + wrmsr + + invd + + ret + mtrr_table: /* Fixed MTRRs */ .word 0x250, 0x258, 0x259 From 801d70ce026be4595e595fb6790621a6a898cee9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:13 -0700 Subject: [PATCH 29/45] x86: Disable CAR before relocation on platforms that need it For platforms with CAR we should disable it before relocation. Check if this function is available and call it if so. Signed-off-by: Simon Glass --- arch/x86/cpu/start.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 125782cf27..f51f1121d0 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -205,6 +205,14 @@ board_init_f_r_trampoline: /* Setup global descriptor table so gd->xyz works */ call setup_gdt + /* Set if we need to disable CAR */ +.weak car_uninit + movl $car_uninit, %eax + cmpl $0, %eax + jz 1f + + call car_uninit +1: /* Re-enter U-Boot by calling board_init_f_r */ call board_init_f_r From c72f74e2780350f16795dc4d69145b9c87cb3e97 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:14 -0700 Subject: [PATCH 30/45] x86: ivybridge: Update microcode early in boot At present the normal update (which happens much later) does not work. This seems to have something to do with the 'no eviction' mode in the CAR, or at least moving the microcode update after that causes it not to work. For now, do an update early on so that it definitely works. Also refuse to continue unless the microcode update check (later in boot) is successful. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/car.S | 16 ++++++++++++ arch/x86/cpu/ivybridge/cpu.c | 2 +- arch/x86/cpu/ivybridge/microcode_intel.c | 26 ++++++++++++------- arch/x86/dts/link.dts | 3 --- .../include/asm/arch-ivybridge/microcode.h | 6 +++++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index d5f1acfe3d..9441666f5a 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,11 @@ */ #include +#include #include #include #include +#include #define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) #define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) @@ -45,6 +47,14 @@ car_init: movl $0xFEE00300, %esi movl %eax, (%esi) + /* TODO: Load microcode later - the 'no eviction' mode breaks this */ + movl $MSR_IA32_UCODE_WRITE, %ecx + xorl %edx, %edx + movl $_dt_ucode_base_size, %eax + movl (%eax), %eax + addl $UCODE_HEADER_LEN, %eax + wrmsr + post_code(POST_CAR_SIPI) /* Zero out all fixed range and variable range MTRRs */ movl $mtrr_table, %esi @@ -222,3 +232,9 @@ mtrr_table: .word 0x20C, 0x20D, 0x20E, 0x20F .word 0x210, 0x211, 0x212, 0x213 mtrr_table_end: + + .align 4 +_dt_ucode_base_size: + /* These next two fields are filled in by ifdtool */ + .long 0 /* microcode base */ + .long 0 /* microcode size */ diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 0543e06aef..e9253100f6 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -263,7 +263,7 @@ int print_cpuinfo(void) enable_lapic(); ret = microcode_update_intel(); - if (ret && ret != -ENOENT && ret != -EEXIST) + if (ret) return ret; /* Enable upper 128bytes of CMOS */ diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c index 08177510ab..2440a97c48 100644 --- a/arch/x86/cpu/ivybridge/microcode_intel.c +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include /** * struct microcode_update - standard microcode header from Intel @@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node, update->data = fdt_getprop(blob, node, "data", &update->size); if (!update->data) return -EINVAL; - update->data += 48; - update->size -= 48; + update->data += UCODE_HEADER_LEN; + update->size -= UCODE_HEADER_LEN; update->header_version = fdtdec_get_int(blob, node, "intel,header-version", 0); @@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void) asm volatile ( "xorl %%eax, %%eax\n" "xorl %%edx, %%edx\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "wrmsr\n" "movl $0x01, %%eax\n" "cpuid\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "rdmsr\n" : /* outputs */ "=a" (low), "=d" (high) : /* inputs */ + "i" (MSR_IA32_UCODE_REV) : /* clobbers */ "ebx", "ecx" ); @@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu) struct cpuid_result result; uint32_t low, high; - wrmsr(0x8b, 0, 0); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); result = cpuid(1); - rdmsr(0x8b, low, cpu->update_revision); + rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision); x86_model = (result.eax >> 4) & 0x0f; x86_family = (result.eax >> 8) & 0x0f; cpu->processor_signature = result.eax; @@ -120,6 +123,7 @@ int microcode_update_intel(void) int count; int node; int ret; + int rev; microcode_read_cpu(&cpu); node = 0; @@ -147,12 +151,16 @@ int microcode_update_intel(void) skipped++; continue; } - ret = microcode_read_rev(); - wrmsr(0x79, (ulong)update.data, 0); + wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0); + rev = microcode_read_rev(); debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", - microcode_read_rev(), update.date_code & 0xffff, + rev, update.date_code & 0xffff, (update.date_code >> 24) & 0xff, (update.date_code >> 16) & 0xff); + if (update.update_revision != rev) { + printf("Microcode update failed\n"); + return -EFAULT; + } count++; } while (1); } diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 107af60004..9490b169fb 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -209,9 +209,6 @@ microcode { update@0 { -#include "microcode/m12206a7_00000029.dtsi" - }; - update@1 { #include "microcode/m12306a9_0000001b.dtsi" }; }; diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h index bc9b87c44c..b868283761 100644 --- a/arch/x86/include/asm/arch-ivybridge/microcode.h +++ b/arch/x86/include/asm/arch-ivybridge/microcode.h @@ -7,6 +7,11 @@ #ifndef __ASM_ARCH_MICROCODE_H #define __ASM_ARCH_MICROCODE_H +/* Length of the public header on Intel microcode blobs */ +#define UCODE_HEADER_LEN 0x30 + +#ifndef __ASSEMBLY__ + /** * microcode_update_intel() - Apply microcode updates * @@ -16,5 +21,6 @@ * not updates were found, -EINVAL if an update was invalid */ int microcode_update_intel(void); +#endif /* __ASSEMBLY__ */ #endif From cb3b2e62caa7b87ed727d690c5a8bd1e003ab601 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jan 2015 16:18:15 -0700 Subject: [PATCH 31/45] x86: Add an 'mtrr' command to list and adjust MTRRs It is useful to be able to see the MTRR setup in U-Boot. Add a command to list the state of the variable MTRR registers and allow them to be changed. Update the documentation to list some of the available commands. This does not support fixed MTRRs as yet. Signed-off-by: Simon Glass Tested-by: Bin Meng --- arch/x86/lib/Makefile | 1 + arch/x86/lib/cmd_mtrr.c | 138 ++++++++++++++++++++++++++++++++++++++++ doc/README.x86 | 18 +++++- 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 arch/x86/lib/cmd_mtrr.c diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 73262d7263..32d7b98fa6 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_HAVE_FSP) += cmd_hob.o obj-y += gcc.o obj-y += init_helpers.o obj-y += interrupts.o +obj-y += cmd_mtrr.o obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o obj-$(CONFIG_PCI) += pci_type1.o diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c new file mode 100644 index 0000000000..7e0506b75d --- /dev/null +++ b/arch/x86/lib/cmd_mtrr.c @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { + "Uncacheable", + "Combine", + "2", + "3", + "Through", + "Protect", + "Back", +}; + +static int do_mtrr_list(void) +{ + int i; + + printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", + "Mask ||", "Size ||"); + for (i = 0; i < MTRR_COUNT; i++) { + const char *type = "Invalid"; + uint64_t base, mask, size; + bool valid; + + base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); + mask = native_read_msr(MTRR_PHYS_MASK_MSR(i)); + size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); + size |= (1 << 12) - 1; + size += 1; + valid = mask & MTRR_PHYS_MASK_VALID; + type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; + printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, + valid ? "Y" : "N", type, base, mask, size); + } + + return 0; +} + +static int do_mtrr_set(uint reg, int argc, char * const argv[]) +{ + const char *typename = argv[0]; + struct mtrr_state state; + uint32_t start, size; + uint64_t base, mask; + int i, type = -1; + bool valid; + + if (argc < 3) + return CMD_RET_USAGE; + for (i = 0; i < MTRR_TYPE_COUNT; i++) { + if (*typename == *mtrr_type_name[i]) + type = i; + } + if (type == -1) { + printf("Invalid type name %s\n", typename); + return CMD_RET_USAGE; + } + start = simple_strtoul(argv[1], NULL, 16); + size = simple_strtoul(argv[2], NULL, 16); + + base = start | type; + valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID; + mask = ~((uint64_t)size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + if (valid) + mask |= MTRR_PHYS_MASK_VALID; + + printf("base=%llx, mask=%llx\n", base, mask); + mtrr_open(&state); + wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); + wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); + mtrr_close(&state); + + return 0; +} + +static int mtrr_set_valid(int reg, bool valid) +{ + struct mtrr_state state; + uint64_t mask; + + mtrr_open(&state); + mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); + if (valid) + mask |= MTRR_PHYS_MASK_VALID; + else + mask &= ~MTRR_PHYS_MASK_VALID; + wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); + mtrr_close(&state); + + return 0; +} + +static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *cmd; + uint reg; + + cmd = argv[1]; + if (argc < 2 || *cmd == 'l') + return do_mtrr_list(); + argc -= 2; + argv += 2; + if (argc <= 0) + return CMD_RET_USAGE; + reg = simple_strtoul(argv[0], NULL, 16); + if (reg >= MTRR_COUNT) { + printf("Invalid register number\n"); + return CMD_RET_USAGE; + } + if (*cmd == 'e') + return mtrr_set_valid(reg, true); + else if (*cmd == 'd') + return mtrr_set_valid(reg, false); + else if (*cmd == 's') + return do_mtrr_set(reg, argc - 1, argv + 1); + else + return CMD_RET_USAGE; + + return 0; +} + +U_BOOT_CMD( + mtrr, 6, 1, do_mtrr, + "Use x86 memory type range registers (32-bit only)", + "[list] - list current registers\n" + "set - set a register\n" + "\t is Uncacheable, Combine, Through, Protect, Back\n" + "disable - disable a register\n" + "ensable - enable a register" +); diff --git a/doc/README.x86 b/doc/README.x86 index 5fab04491f..b474161e12 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -110,9 +110,25 @@ be turned on. Not every device on the board is configured via devie tree, but more and more devices will be added as time goes by. Check out the directory arch/x86/dts/ for these device tree source files. +Useful Commands +--------------- + +In keeping with the U-Boot philosophy of providing functions to check and +adjust internal settings, there are several x86-specific commands that may be +useful: + +hob - Display information about Firmware Support Package (FSP) Hand-off + Block. This is only available on platforms which use FSP, mostly + Atom. +iod - Display I/O memory +iow - Write I/O memory +mtrr - List and set the Memory Type Range Registers (MTRR). These are used to + tell the CPU whether memory is cacheable and if so the cache write + mode to use. U-Boot sets up some reasonable values but you can + adjust then with this command. + TODO List --------- -- MTRR support (for performance) - Audio - Chrome OS verified boot - SMI and ACPI support, to provide platform info and facilities to Linux From b2439aecd3091e754d3dc3f8be422fee74180295 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 14:04:36 +0800 Subject: [PATCH 32/45] x86: fsp: Drop get_hob_type() and get_hob_length() These two are not worth having separate inline functions as they are really simple, so drop them. Also changed 'type' parameter of fsp_get_next_hob() from u16 to uint. Suggested-by: Simon Glass Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/fsp_support.c | 10 +++--- arch/x86/cpu/queensbay/tnc_dram.c | 4 +-- .../include/asm/arch-queensbay/fsp/fsp_hob.h | 36 ++----------------- .../asm/arch-queensbay/fsp/fsp_support.h | 2 +- arch/x86/lib/cmd_hob.c | 6 ++-- 5 files changed, 14 insertions(+), 44 deletions(-) diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index 4764e3c62f..aed3e2b300 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -242,7 +242,7 @@ u32 fsp_get_usable_lowmem_top(const void *hob_list) /* * Collect memory ranges */ top = FSP_LOWMEM_BASE; while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_SYS_MEM) { phys_start = res_desc->phys_start; @@ -271,7 +271,7 @@ u64 fsp_get_usable_highmem_top(const void *hob_list) /* Collect memory ranges */ top = FSP_HIGHMEM_BASE; while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_SYS_MEM) { phys_start = res_desc->phys_start; @@ -297,7 +297,7 @@ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, /* Collect memory ranges */ while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_MEM_RESERVED) { if (compare_guid(&res_desc->owner, guid)) { @@ -342,7 +342,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) return base; } -const struct hob_header *fsp_get_next_hob(u16 type, const void *hob_list) +const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list) { const struct hob_header *hdr; @@ -350,7 +350,7 @@ const struct hob_header *fsp_get_next_hob(u16 type, const void *hob_list) /* Parse the HOB list until end of list or matching type is found */ while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == type) + if (hdr->type == type) return hdr; hdr = get_next_hob(hdr); diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c index b669dbc98b..df79a39dd8 100644 --- a/arch/x86/cpu/queensbay/tnc_dram.c +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -19,7 +19,7 @@ int dram_init(void) hdr = gd->arch.hob_list; while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_SYS_MEM || res_desc->type == RES_MEM_RESERVED) { @@ -63,7 +63,7 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) hdr = gd->arch.hob_list; while (!end_of_hob(hdr)) { - if (get_hob_type(hdr) == HOB_TYPE_RES_DESC) { + if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; entries[num_entries].addr = res_desc->phys_start; entries[num_entries].size = res_desc->len; diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h index 51103617b0..6cca7f5654 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h @@ -182,36 +182,6 @@ struct hob_guid { /* GUID specific data goes here */ }; -/** - * get_hob_type() - return the type of a HOB - * - * This macro returns the type field from the HOB header for the - * HOB specified by hob. - * - * @hob: A pointer to a HOB. - * - * @return: HOB type. - */ -static inline u16 get_hob_type(const struct hob_header *hdr) -{ - return hdr->type; -} - -/** - * get_hob_length() - return the length, in bytes, of a HOB - * - * This macro returns the len field from the HOB header for the - * HOB specified by hob. - * - * @hob: A pointer to a HOB. - * - * @return: HOB length. - */ -static inline u16 get_hob_length(const struct hob_header *hdr) -{ - return hdr->len; -} - /** * get_next_hob() - return a pointer to the next HOB in the HOB list * @@ -224,7 +194,7 @@ static inline u16 get_hob_length(const struct hob_header *hdr) */ static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) { - return (const struct hob_header *)((u32)hdr + get_hob_length(hdr)); + return (const struct hob_header *)((u32)hdr + hdr->len); } /** @@ -241,7 +211,7 @@ static inline const struct hob_header *get_next_hob(const struct hob_header *hdr */ static inline bool end_of_hob(const struct hob_header *hdr) { - return get_hob_type(hdr) == HOB_TYPE_EOH; + return hdr->type == HOB_TYPE_EOH; } /** @@ -273,7 +243,7 @@ static inline void *get_guid_hob_data(const struct hob_header *hdr) */ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { - return get_hob_length(hdr) - sizeof(struct hob_guid); + return hdr->len - sizeof(struct hob_guid); } /* FSP specific GUID HOB definitions */ diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h index 2a3e987ebb..ebdbd03435 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h @@ -145,7 +145,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); * * @retval: A HOB object with matching type; Otherwise NULL. */ -const struct hob_header *fsp_get_next_hob(u16 type, const void *hob_list); +const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list); /** * Returns the next instance of the matched GUID HOB from the starting HOB. diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c index 8d1f038527..a0ef037da1 100644 --- a/arch/x86/lib/cmd_hob.c +++ b/arch/x86/lib/cmd_hob.c @@ -29,7 +29,7 @@ static char *hob_type[] = { int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const struct hob_header *hdr; - u16 type; + uint type; char *desc; int i = 0; @@ -41,7 +41,7 @@ int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("----|----------|---------------------|----------------\n"); while (!end_of_hob(hdr)) { printf("%-3d | %08x | ", i, (unsigned int)hdr); - type = get_hob_type(hdr); + type = hdr->type; if (type == HOB_TYPE_UNUSED) desc = "*Unused*"; else if (type == HOB_TYPE_EOH) @@ -50,7 +50,7 @@ int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) desc = hob_type[type]; else desc = "*Invalid Type*"; - printf("%-19s | %-15d\n", desc, get_hob_length(hdr)); + printf("%-19s | %-15d\n", desc, hdr->len); hdr = get_next_hob(hdr); i++; } From 5c564b0d2fd108ebc5fd6bb0081b981ee32ddf0b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:13 +0800 Subject: [PATCH 33/45] x86: coreboot: Set up timer base correctly If coreboot is built with CONFIG_COLLECT_TIMESTAMPS, use the value of base_time in coreboot's timestamp table as our timer base, otherwise TSC counter value will be used. Sometimes even coreboot is built with CONFIG_COLLECT_TIMESTAMPS, the value of base_time in the timestamp table is still zero, so we must exclude this case too (this is currently seen on booting coreboot in qemu). Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/coreboot/timestamp.c | 33 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index bd3558a021..0edee6bd2c 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -3,18 +3,7 @@ * * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -38,9 +27,27 @@ static struct timestamp_table *ts_table __attribute__((section(".data"))); void timestamp_init(void) { +#ifdef CONFIG_SYS_X86_TSC_TIMER + uint64_t base_time; +#endif + ts_table = lib_sysinfo.tstamp_table; #ifdef CONFIG_SYS_X86_TSC_TIMER - timer_set_base(ts_table->base_time); + /* + * If coreboot is built with CONFIG_COLLECT_TIMESTAMPS, use the value + * of base_time in coreboot's timestamp table as our timer base, + * otherwise TSC counter value will be used. + * + * Sometimes even coreboot is built with CONFIG_COLLECT_TIMESTAMPS, + * the value of base_time in the timestamp table is still zero, so + * we must exclude this case too (this is currently seen on booting + * coreboot in qemu) + */ + if (ts_table && ts_table->base_time) + base_time = ts_table->base_time; + else + base_time = rdtsc(); + timer_set_base(base_time); #endif timestamp_add_now(TS_U_BOOT_INITTED); } From 3ba6a0f4f6a2381ad32930df6277930a3de577bc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:14 +0800 Subject: [PATCH 34/45] x86: Allow a hardcoded TSC frequency provided by Kconfig By default U-Boot automatically calibrates TSC running frequency via MSR and PIT. The calibration may not work on every x86 processor, so a new Kconfig option CONFIG_TSC_CALIBRATION_BYPASS is introduced to allow bypassing the calibration and assign a hardcoded TSC frequency CONFIG_TSC_FREQ_IN_MHZ. Normally the bypass should be turned on in a simulation environment like qemu. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/Kconfig | 20 ++++++++++++++++++++ arch/x86/lib/tsc_timer.c | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e992e647cc..ffcb4cb665 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -313,6 +313,26 @@ config FRAMEBUFFER_VESA_MODE endmenu +config TSC_CALIBRATION_BYPASS + bool "Bypass Time-Stamp Counter (TSC) calibration" + default n + help + By default U-Boot automatically calibrates Time-Stamp Counter (TSC) + running frequency via Model-Specific Register (MSR) and Programmable + Interval Timer (PIT). If the calibration does not work on your board, + select this option and provide a hardcoded TSC running frequency with + CONFIG_TSC_FREQ_IN_MHZ below. + + Normally this option should be turned on in a simulation environment + like qemu. + +config TSC_FREQ_IN_MHZ + int "Time-Stamp Counter (TSC) running frequency in MHz" + depends on TSC_CALIBRATION_BYPASS + default 1000 + help + The running frequency in MHz of Time-Stamp Counter (TSC). + source "arch/x86/cpu/ivybridge/Kconfig" source "arch/x86/cpu/queensbay/Kconfig" diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index fb9afed18f..7f5ba2ca6f 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -78,7 +78,7 @@ static int match_cpu(u8 family, u8 model) * * Returns the calibration value or 0 if MSR calibration failed. */ -static unsigned long try_msr_calibrate_tsc(void) +static unsigned long __maybe_unused try_msr_calibrate_tsc(void) { u32 lo, hi, ratio, freq_id, freq; unsigned long res; @@ -199,7 +199,7 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp, #define MAX_QUICK_PIT_MS 50 #define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) -static unsigned long quick_pit_calibrate(void) +static unsigned long __maybe_unused quick_pit_calibrate(void) { int i; u64 tsc, delta; @@ -306,6 +306,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) if (gd->arch.tsc_mhz) return gd->arch.tsc_mhz; +#ifdef CONFIG_TSC_CALIBRATION_BYPASS + fast_calibrate = CONFIG_TSC_FREQ_IN_MHZ; +#else fast_calibrate = try_msr_calibrate_tsc(); if (!fast_calibrate) { @@ -313,6 +316,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) if (!fast_calibrate) panic("TSC frequency is ZERO"); } +#endif gd->arch.tsc_mhz = fast_calibrate; return fast_calibrate; From 8cb20ccc34cda9fdcbae962744bf8ecee90dd5d2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:15 +0800 Subject: [PATCH 35/45] x86: Move CONFIG_X86_RESET_VECTOR and CONFIG_SYS_X86_START16 to Kconfig Convert CONFIG_X86_RESET_VECTOR and CONFIG_SYS_X86_START16 to Kconfig options so that we can remove them from board configuration file. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/Kconfig | 9 +++++++++ board/google/chromebook_link/Kconfig | 1 + board/intel/crownbay/Kconfig | 1 + include/configs/chromebook_link.h | 2 -- include/configs/crownbay.h | 2 -- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ffcb4cb665..ba0c1aace0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -66,6 +66,15 @@ config SMM_TSEG config SMM_TSEG_SIZE hex +config X86_RESET_VECTOR + bool + default n + +config SYS_X86_START16 + hex + depends on X86_RESET_VECTOR + default 0xfffff800 + config BOARD_ROMSIZE_KB_512 bool config BOARD_ROMSIZE_KB_1024 diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 7f79fd206f..a9a55e8d83 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -14,6 +14,7 @@ config SYS_CONFIG_NAME config BOARD_SPECIFIC_OPTIONS # dummy def_bool y + select X86_RESET_VECTOR select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 diff --git a/board/intel/crownbay/Kconfig b/board/intel/crownbay/Kconfig index 4709f9b55d..762663a001 100644 --- a/board/intel/crownbay/Kconfig +++ b/board/intel/crownbay/Kconfig @@ -14,6 +14,7 @@ config SYS_CONFIG_NAME config BOARD_SPECIFIC_OPTIONS # dummy def_bool y + select X86_RESET_VECTOR select INTEL_QUEENSBAY select BOARD_ROMSIZE_KB_1024 diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 8930210908..449f0c2ce3 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -19,11 +19,9 @@ #define CONFIG_SYS_CAR_SIZE (128 * 1024) #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 -#define CONFIG_SYS_X86_START16 0xfffff800 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_DISPLAY_CPUINFO -#define CONFIG_X86_RESET_VECTOR #define CONFIG_NR_DRAM_BANKS 8 #define CONFIG_X86_MRC_ADDR 0xfffa0000 #define CONFIG_CACHE_MRC_SIZE_KB 512 diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h index eadb339a0f..b927b1c9f5 100644 --- a/include/configs/crownbay.h +++ b/include/configs/crownbay.h @@ -14,10 +14,8 @@ #include #define CONFIG_SYS_MONITOR_LEN (1 << 20) -#define CONFIG_SYS_X86_START16 0xfffff800 #define CONFIG_BOARD_EARLY_INIT_F -#define CONFIG_X86_RESET_VECTOR #define CONFIG_NR_DRAM_BANKS 1 #define CONFIG_X86_SERIAL From 7698d36a107734d363a512d3eeb81d6c9acc0a29 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:16 +0800 Subject: [PATCH 36/45] x86: Hide ROM chip size when CONFIG_X86_RESET_VECTOR is not selected When CONFIG_X86_RESET_VECTOR is not selected, specifying the ROM chip size is meaningless, hence hide it. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ba0c1aace0..512b6f6e1f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -49,6 +49,7 @@ config RAMBASE config XIP_ROM_SIZE hex + depends on X86_RESET_VECTOR default ROM_SIZE config CPU_ADDR_BITS @@ -90,6 +91,7 @@ config BOARD_ROMSIZE_KB_16384 choice prompt "ROM chip size" + depends on X86_RESET_VECTOR default UBOOT_ROMSIZE_KB_512 if BOARD_ROMSIZE_KB_512 default UBOOT_ROMSIZE_KB_1024 if BOARD_ROMSIZE_KB_1024 default UBOOT_ROMSIZE_KB_2048 if BOARD_ROMSIZE_KB_2048 From c57522f6564a68a0e0a82544afdb2f95737c1ccd Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:17 +0800 Subject: [PATCH 37/45] x86: coreboot: Make SYS_CONFIG_NAME and DEFAULT_DEVICE_TREE configurable In theory U-Boot built for coreboot is supposed to run as a payload to be loaded by coreboot on every board that coreboot supports. The U-Boot build process uses SYS_CONFIG_NAME and DEFAULT_DEVICE_TREE which are hardcoded in board defconfig and Kconfig files. For better support of coreboot, we want to make these two options configurable so that we can easily change them during 'make menuconfig' so that the generated U-Boot image for coreboot is board configuration aware. Signed-off-by: Bin Meng Acked-by: Simon Glass --- board/coreboot/coreboot/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig index 6ca6cedf0d..e5ccf5848f 100644 --- a/board/coreboot/coreboot/Kconfig +++ b/board/coreboot/coreboot/Kconfig @@ -9,7 +9,20 @@ config SYS_VENDOR config SYS_SOC default "coreboot" +comment "coreboot-specific options" + config SYS_CONFIG_NAME + string "Board configuration file" default "coreboot" + help + This option selects the board configuration file in include/configs/ + directory to be used to build U-Boot for coreboot. + +config DEFAULT_DEVICE_TREE + string "Board Device Tree Source (dts) file" + default "link" + help + This option selects the board Device Tree Source (dts) file in + arch/x86/dts/ directory to be used to build U-Boot for coreboot. endif From 9d74f03460a788e004fb1fb4cb53003d26f57298 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:18 +0800 Subject: [PATCH 38/45] x86: coreboot: Move coreboot-specific defines from coreboot.h to Kconfig There are many places in the U-Boot source tree which refer to CONFIG_SYS_COREBOOT, CONFIG_CBMEM_CONSOLE and CONFIG_VIDEO_COREBOOT that is currently defined in coreboot.h. Move them to arch/x86/cpu/coreboot/Kconfig so that we can switch to board configuration file to build U-Boot later. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/Kconfig | 2 ++ arch/x86/cpu/coreboot/Kconfig | 15 +++++++++++++++ include/configs/coreboot.h | 5 ----- 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 arch/x86/cpu/coreboot/Kconfig diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 512b6f6e1f..90e828a26e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -344,6 +344,8 @@ config TSC_FREQ_IN_MHZ help The running frequency in MHz of Time-Stamp Counter (TSC). +source "arch/x86/cpu/coreboot/Kconfig" + source "arch/x86/cpu/ivybridge/Kconfig" source "arch/x86/cpu/queensbay/Kconfig" diff --git a/arch/x86/cpu/coreboot/Kconfig b/arch/x86/cpu/coreboot/Kconfig new file mode 100644 index 0000000000..e0e3c64506 --- /dev/null +++ b/arch/x86/cpu/coreboot/Kconfig @@ -0,0 +1,15 @@ +if TARGET_COREBOOT + +config SYS_COREBOOT + bool + default y + +config CBMEM_CONSOLE + bool + default y + +config VIDEO_COREBOOT + bool + default y + +endif diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index 990a2d186e..a0d99522b7 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -19,7 +19,6 @@ * High Level Configuration Options * (easy to change) */ -#define CONFIG_SYS_COREBOOT #define CONFIG_LAST_STAGE_INIT #define CONFIG_SYS_EARLY_PCI_INIT @@ -55,10 +54,6 @@ "stdout=vga,serial,cbmem\0" \ "stderr=vga,serial,cbmem\0" -#define CONFIG_CBMEM_CONSOLE - -#define CONFIG_VIDEO_COREBOOT - #define CONFIG_NR_DRAM_BANKS 4 #define CONFIG_TRACE From 24ef04280cc9730679d390acb41bb02487527303 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:19 +0800 Subject: [PATCH 39/45] x86: Move CONFIG_SYS_CAR_xxx to Kconfig Move CONFIG_SYS_CAR_ADDR and CONFIG_SYS_CAR_SIZE to Kconfig so that we don't need them in the board configuration file thus the same board configuratoin file can be used to build both coreboot version and bare version. Signed-off-by: Bin Meng Acked-by: Simon Glass --- board/coreboot/coreboot/Kconfig | 12 ++++++++++++ board/google/chromebook_link/Kconfig | 8 ++++++++ include/configs/chromebook_link.h | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig index e5ccf5848f..f2cd75409e 100644 --- a/board/coreboot/coreboot/Kconfig +++ b/board/coreboot/coreboot/Kconfig @@ -25,4 +25,16 @@ config DEFAULT_DEVICE_TREE This option selects the board Device Tree Source (dts) file in arch/x86/dts/ directory to be used to build U-Boot for coreboot. +config SYS_CAR_ADDR + hex "Board specific Cache-As-RAM (CAR) address" + default 0x19200000 + help + This option specifies the board specific Cache-As-RAM (CAR) address. + +config SYS_CAR_SIZE + hex "Board specific Cache-As-RAM (CAR) size" + default 0x4000 + help + This option specifies the board specific Cache-As-RAM (CAR) size. + endif diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index a9a55e8d83..33a31f311f 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -30,4 +30,12 @@ config EARLY_POST_CROS_EC bool "Enable early post to Chrome OS EC" default y +config SYS_CAR_ADDR + hex + default 0xff7e0000 + +config SYS_CAR_SIZE + hex + default 0x20000 + endif diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 449f0c2ce3..318f1a8fe7 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -15,9 +15,9 @@ #include -#define CONFIG_SYS_CAR_ADDR 0xff7e0000 -#define CONFIG_SYS_CAR_SIZE (128 * 1024) + #define CONFIG_SYS_MONITOR_LEN (1 << 20) + #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_DISPLAY_CPUINFO From fa48e51013280396f02e668a5d9f1d606d69be35 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:20 +0800 Subject: [PATCH 40/45] x86: Remove include/configs/coreboot.h Since we already swtiched to use the new mechanism for building U-Boot for coreboot, coreboot.h is no longer needed so remove it. Signed-off-by: Bin Meng Acked-by: Simon Glass --- board/coreboot/coreboot/MAINTAINERS | 2 +- include/configs/coreboot.h | 70 ----------------------------- 2 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 include/configs/coreboot.h diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS index 6ce66f551f..2736aa0282 100644 --- a/board/coreboot/coreboot/MAINTAINERS +++ b/board/coreboot/coreboot/MAINTAINERS @@ -2,5 +2,5 @@ COREBOOT BOARD M: Simon Glass S: Maintained F: board/coreboot/coreboot/ -F: include/configs/coreboot.h +F: include/configs/chromebook_link.h F: configs/coreboot-x86_defconfig diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h deleted file mode 100644 index a0d99522b7..0000000000 --- a/include/configs/coreboot.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2008 - * Graeme Russ, graeme.russ@gmail.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * board/config.h - configuration options, board specific - */ - -#ifndef __CONFIG_H -#define __CONFIG_H - -#include - -/* - * High Level Configuration Options - * (easy to change) - */ -#define CONFIG_LAST_STAGE_INIT -#define CONFIG_SYS_EARLY_PCI_INIT - -#define CONFIG_SYS_CAR_ADDR 0x19200000 -#define CONFIG_SYS_CAR_SIZE (16 * 1024) -#define CONFIG_SYS_MONITOR_LEN (256 * 1024) - -#define CONFIG_TRACE_EARLY_SIZE (8 << 20) -#define CONFIG_TRACE_EARLY -#define CONFIG_TRACE_EARLY_ADDR 0x01400000 - -#define CONFIG_BOOTSTAGE -#define CONFIG_BOOTSTAGE_REPORT -#define CONFIG_BOOTSTAGE_FDT -#define CONFIG_CMD_BOOTSTAGE -/* Place to stash bootstage data from first-stage U-Boot */ -#define CONFIG_BOOTSTAGE_STASH 0x0110f000 -#define CONFIG_BOOTSTAGE_STASH_SIZE 0x7fc -#define CONFIG_BOOTSTAGE_USER_COUNT 60 - -#define CONFIG_SCSI_DEV_LIST {PCI_VENDOR_ID_INTEL, \ - PCI_DEVICE_ID_INTEL_NM10_AHCI}, \ - {PCI_VENDOR_ID_INTEL, \ - PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \ - {PCI_VENDOR_ID_INTEL, \ - PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_SERIES6}, \ - {PCI_VENDOR_ID_INTEL, \ - PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE} - -#define CONFIG_X86_SERIAL - -#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \ - "stdout=vga,serial,cbmem\0" \ - "stderr=vga,serial,cbmem\0" - -#define CONFIG_NR_DRAM_BANKS 4 - -#define CONFIG_TRACE -#define CONFIG_CMD_TRACE -#define CONFIG_TRACE_BUFFER_SIZE (16 << 20) - -#define CONFIG_BOOTDELAY 2 - -#define CONFIG_CROS_EC -#define CONFIG_CROS_EC_LPC -#define CONFIG_CMD_CROS_EC -#define CONFIG_ARCH_EARLY_INIT_R - -#endif /* __CONFIG_H */ From ade8127a7929c6394908e7debe89e297202b7efa Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:21 +0800 Subject: [PATCH 41/45] x86: Make chromebook_link the default board for coreboot Change SYS_CONFIG_NAME and DEFAULT_DEVICE_TREE to chromebook_link which is currently the only real board officially supported to run U-Boot loaded by coreboot. Note the symbolic link file chromebook_link.dts is deleted and link.dts is renamed to chromebook_link.dts. To avoid multiple definition of video_hw_init, the CONFIG_VIDEO_X86 define needs to be moved to arch/x86/cpu/ivybridge/Kconfig. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/Makefile | 3 +- arch/x86/dts/chromebook_link.dts | 217 +++++++++++++++++++++++++++++- arch/x86/dts/link.dts | 216 ----------------------------- board/coreboot/coreboot/Kconfig | 4 +- configs/chromebook_link_defconfig | 1 + configs/coreboot-x86_defconfig | 1 - drivers/video/Kconfig | 8 ++ include/configs/chromebook_link.h | 1 - 8 files changed, 228 insertions(+), 223 deletions(-) mode change 120000 => 100644 arch/x86/dts/chromebook_link.dts delete mode 100644 arch/x86/dts/link.dts diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index 5525094539..97ed884288 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -1,5 +1,4 @@ -dtb-y += link.dtb \ - chromebook_link.dtb \ +dtb-y += chromebook_link.dtb \ crownbay.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts deleted file mode 120000 index 6f8c5cdba7..0000000000 --- a/arch/x86/dts/chromebook_link.dts +++ /dev/null @@ -1 +0,0 @@ -link.dts \ No newline at end of file diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts new file mode 100644 index 0000000000..9490b169fb --- /dev/null +++ b/arch/x86/dts/chromebook_link.dts @@ -0,0 +1,216 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" +/include/ "serial.dtsi" + +/ { + model = "Google Link"; + compatible = "google,link", "intel,celeron-ivybridge"; + + config { + silent_console = <0>; + }; + + gpioa { + compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; + reg = <0 0x10>; + bank-name = "A"; + }; + + gpiob { + compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; + reg = <0x30 0x10>; + bank-name = "B"; + }; + + gpioc { + compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; + reg = <0x40 0x10>; + bank-name = "C"; + }; + + chosen { + stdout-path = "/serial"; + }; + + spd { + compatible = "memory-spd"; + #address-cells = <1>; + #size-cells = <0>; + elpida_4Gb_1600_x16 { + reg = <0>; + data = [92 10 0b 03 04 19 02 02 + 03 52 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + 20 08 3c 3c 01 40 83 81 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 11 42 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 02 fe 00 + 11 52 00 00 00 07 7f 37 + 45 42 4a 32 30 55 47 36 + 45 42 55 30 2d 47 4e 2d + 46 20 30 20 02 fe 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00]; + }; + samsung_4Gb_1600_1.35v_x16 { + reg = <1>; + data = [92 11 0b 03 04 19 02 02 + 03 11 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + f0 0a 3c 3c 01 40 83 01 + 00 80 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 11 02 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 80 ce 01 + 00 00 00 00 00 00 6a 04 + 4d 34 37 31 42 35 36 37 + 34 42 48 30 2d 59 4b 30 + 20 20 00 00 80 ce 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00]; + }; + micron_4Gb_1600_1.35v_x16 { + reg = <2>; + data = [92 11 0b 03 04 19 02 02 + 03 11 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + 20 08 3c 3c 01 40 83 05 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 01 02 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 80 2c 00 + 00 00 00 00 00 00 ad 75 + 34 4b 54 46 32 35 36 36 + 34 48 5a 2d 31 47 36 45 + 31 20 45 31 80 2c 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff]; + }; + }; + + spi { + #address-cells = <1>; + #size-cells = <0>; + compatible = "intel,ich9"; + spi-flash@0 { + reg = <0>; + compatible = "winbond,w25q64", "spi-flash"; + memory-map = <0xff800000 0x00800000>; + }; + }; + + pci { + sata { + compatible = "intel,pantherpoint-ahci"; + intel,sata-mode = "ahci"; + intel,sata-port-map = <1>; + intel,sata-port0-gen3-tx = <0x00880a7f>; + }; + + gma { + compatible = "intel,gma"; + intel,dp_hotplug = <0 0 0x06>; + intel,panel-port-select = <1>; + intel,panel-power-cycle-delay = <6>; + intel,panel-power-up-delay = <2000>; + intel,panel-power-down-delay = <500>; + intel,panel-power-backlight-on-delay = <2000>; + intel,panel-power-backlight-off-delay = <2000>; + intel,cpu-backlight = <0x00000200>; + intel,pch-backlight = <0x04000000>; + }; + + lpc { + compatible = "intel,lpc"; + #address-cells = <1>; + #size-cells = <1>; + gen-dec = <0x800 0xfc 0x900 0xfc>; + intel,gen-dec = <0x800 0xfc 0x900 0xfc>; + intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b + 0x80 0x80 0x80 0x80>; + intel,gpi-routing = <0 0 0 0 0 0 0 2 + 1 0 0 0 0 0 0 0>; + /* Enable EC SMI source */ + intel,alt-gp-smi-enable = <0x0100>; + + cros-ec@200 { + compatible = "google,cros-ec"; + reg = <0x204 1 0x200 1 0x880 0x80>; + + /* Describes the flash memory within the EC */ + #address-cells = <1>; + #size-cells = <1>; + flash@8000000 { + reg = <0x08000000 0x20000>; + erase-value = <0xff>; + }; + }; + }; + }; + + microcode { + update@0 { +#include "microcode/m12306a9_0000001b.dtsi" + }; + }; + +}; diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts deleted file mode 100644 index 9490b169fb..0000000000 --- a/arch/x86/dts/link.dts +++ /dev/null @@ -1,216 +0,0 @@ -/dts-v1/; - -/include/ "skeleton.dtsi" -/include/ "serial.dtsi" - -/ { - model = "Google Link"; - compatible = "google,link", "intel,celeron-ivybridge"; - - config { - silent_console = <0>; - }; - - gpioa { - compatible = "intel,ich6-gpio"; - u-boot,dm-pre-reloc; - reg = <0 0x10>; - bank-name = "A"; - }; - - gpiob { - compatible = "intel,ich6-gpio"; - u-boot,dm-pre-reloc; - reg = <0x30 0x10>; - bank-name = "B"; - }; - - gpioc { - compatible = "intel,ich6-gpio"; - u-boot,dm-pre-reloc; - reg = <0x40 0x10>; - bank-name = "C"; - }; - - chosen { - stdout-path = "/serial"; - }; - - spd { - compatible = "memory-spd"; - #address-cells = <1>; - #size-cells = <0>; - elpida_4Gb_1600_x16 { - reg = <0>; - data = [92 10 0b 03 04 19 02 02 - 03 52 01 08 0a 00 fe 00 - 69 78 69 3c 69 11 18 81 - 20 08 3c 3c 01 40 83 81 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 0f 11 42 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 02 fe 00 - 11 52 00 00 00 07 7f 37 - 45 42 4a 32 30 55 47 36 - 45 42 55 30 2d 47 4e 2d - 46 20 30 20 02 fe 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00]; - }; - samsung_4Gb_1600_1.35v_x16 { - reg = <1>; - data = [92 11 0b 03 04 19 02 02 - 03 11 01 08 0a 00 fe 00 - 69 78 69 3c 69 11 18 81 - f0 0a 3c 3c 01 40 83 01 - 00 80 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 0f 11 02 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 80 ce 01 - 00 00 00 00 00 00 6a 04 - 4d 34 37 31 42 35 36 37 - 34 42 48 30 2d 59 4b 30 - 20 20 00 00 80 ce 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00]; - }; - micron_4Gb_1600_1.35v_x16 { - reg = <2>; - data = [92 11 0b 03 04 19 02 02 - 03 11 01 08 0a 00 fe 00 - 69 78 69 3c 69 11 18 81 - 20 08 3c 3c 01 40 83 05 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 0f 01 02 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 80 2c 00 - 00 00 00 00 00 00 ad 75 - 34 4b 54 46 32 35 36 36 - 34 48 5a 2d 31 47 36 45 - 31 20 45 31 80 2c 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff - ff ff ff ff ff ff ff ff]; - }; - }; - - spi { - #address-cells = <1>; - #size-cells = <0>; - compatible = "intel,ich9"; - spi-flash@0 { - reg = <0>; - compatible = "winbond,w25q64", "spi-flash"; - memory-map = <0xff800000 0x00800000>; - }; - }; - - pci { - sata { - compatible = "intel,pantherpoint-ahci"; - intel,sata-mode = "ahci"; - intel,sata-port-map = <1>; - intel,sata-port0-gen3-tx = <0x00880a7f>; - }; - - gma { - compatible = "intel,gma"; - intel,dp_hotplug = <0 0 0x06>; - intel,panel-port-select = <1>; - intel,panel-power-cycle-delay = <6>; - intel,panel-power-up-delay = <2000>; - intel,panel-power-down-delay = <500>; - intel,panel-power-backlight-on-delay = <2000>; - intel,panel-power-backlight-off-delay = <2000>; - intel,cpu-backlight = <0x00000200>; - intel,pch-backlight = <0x04000000>; - }; - - lpc { - compatible = "intel,lpc"; - #address-cells = <1>; - #size-cells = <1>; - gen-dec = <0x800 0xfc 0x900 0xfc>; - intel,gen-dec = <0x800 0xfc 0x900 0xfc>; - intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b - 0x80 0x80 0x80 0x80>; - intel,gpi-routing = <0 0 0 0 0 0 0 2 - 1 0 0 0 0 0 0 0>; - /* Enable EC SMI source */ - intel,alt-gp-smi-enable = <0x0100>; - - cros-ec@200 { - compatible = "google,cros-ec"; - reg = <0x204 1 0x200 1 0x880 0x80>; - - /* Describes the flash memory within the EC */ - #address-cells = <1>; - #size-cells = <1>; - flash@8000000 { - reg = <0x08000000 0x20000>; - erase-value = <0xff>; - }; - }; - }; - }; - - microcode { - update@0 { -#include "microcode/m12306a9_0000001b.dtsi" - }; - }; - -}; diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig index f2cd75409e..981de1f071 100644 --- a/board/coreboot/coreboot/Kconfig +++ b/board/coreboot/coreboot/Kconfig @@ -13,14 +13,14 @@ comment "coreboot-specific options" config SYS_CONFIG_NAME string "Board configuration file" - default "coreboot" + default "chromebook_link" help This option selects the board configuration file in include/configs/ directory to be used to build U-Boot for coreboot. config DEFAULT_DEVICE_TREE string "Board Device Tree Source (dts) file" - default "link" + default "chromebook_link" help This option selects the board Device Tree Source (dts) file in arch/x86/dts/ directory to be used to build U-Boot for coreboot. diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b83803e1d2..e956835dc6 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -6,5 +6,6 @@ CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="chromebook_link" CONFIG_HAVE_MRC=y CONFIG_SMM_TSEG_SIZE=0x800000 +CONFIG_VIDEO_X86=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index 6249db7cb0..3cc034a98b 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -2,4 +2,3 @@ CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0x01110000" CONFIG_X86=y CONFIG_TARGET_COREBOOT=y CONFIG_OF_CONTROL=y -CONFIG_DEFAULT_DEVICE_TREE="link" diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e69de29bb2..fdbf3f64f2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -0,0 +1,8 @@ +config VIDEO_X86 + bool "Enable x86 video driver support" + depends on X86 + default n + help + Turn on this option to enable a very simple driver which uses vesa + to discover the video mode and then provides a frame buffer for use + by U-Boot. diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 318f1a8fe7..e0bf3096f6 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -39,7 +39,6 @@ #define CONFIG_X86_OPTION_ROM_FILE pci8086,0166.bin #define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000 -#define CONFIG_VIDEO_X86 #define CONFIG_PCI_MEM_BUS 0xe0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS From 48a223e4ba0a7fec5940cccf7950b656e4f7cbed Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:22 +0800 Subject: [PATCH 42/45] x86: coreboot: Wrap cros_ec initialization cros_ec_board_init() should be called only when CONFIG_CROS_EC is enabled. Signed-off-by: Bin Meng Acked-by: Simon Glass --- board/coreboot/coreboot/coreboot.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c index 154faf6239..e076ea69cf 100644 --- a/board/coreboot/coreboot/coreboot.c +++ b/board/coreboot/coreboot/coreboot.c @@ -10,8 +10,10 @@ int arch_early_init_r(void) { +#ifdef CONFIG_CROS_EC if (cros_ec_board_init()) return -1; +#endif return 0; } From cdcc17d73dcbc40ccc74af98d914fbd61df4b85e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:23 +0800 Subject: [PATCH 43/45] x86: coreboot: Configure pci memory regions Configure coreboot pci memory regions so that pci device drivers could work correctly. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/coreboot/pci.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c index 6a3dd93914..c9983f1588 100644 --- a/arch/x86/cpu/coreboot/pci.c +++ b/arch/x86/cpu/coreboot/pci.c @@ -13,6 +13,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev, struct pci_config_table *table) { @@ -35,7 +37,31 @@ void board_pci_setup_hose(struct pci_controller *hose) hose->first_busno = 0; hose->last_busno = 0; - pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff, + /* PCI memory space */ + pci_set_region(hose->regions + 0, + CONFIG_PCI_MEM_BUS, + CONFIG_PCI_MEM_PHYS, + CONFIG_PCI_MEM_SIZE, PCI_REGION_MEM); - hose->region_count = 1; + + /* 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; } From 617b867fd775d9809b75e9fde57df952f3c3595d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 22:14:24 +0800 Subject: [PATCH 44/45] x86: Update README.x86 for coreboot support Update README.x86 to include new build instructions for U-Boot as the coreboot payload and testing considerations with coreboot. Signed-off-by: Bin Meng Acked-by: Simon Glass --- doc/README.x86 | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/doc/README.x86 b/doc/README.x86 index b474161e12..7df8cc516a 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,6 +32,21 @@ on other architectures, like below: $ make coreboot-x86_defconfig $ make all +Note this default configuration will build a U-Boot payload for the Link board. +To build a coreboot payload against another board, you can change the build +configuration during the 'make menuconfig' process. + +x86 architecture ---> + ... + (chromebook_link) Board configuration file + (chromebook_link) Board Device Tree Source (dts) file + (0x19200000) Board specific Cache-As-RAM (CAR) address + (0x4000) Board specific Cache-As-RAM (CAR) size + +Change the 'Board configuration file' and 'Board Device Tree Source (dts) file' +to point to a new board. You can also change the Cache-As-RAM (CAR) related +settings here if the default values do not fit your new board. + Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a little bit tricky, as generally it requires several binary blobs which are not shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is @@ -88,11 +103,31 @@ in this FSP package too. Rename the first one to fsp.bin and second one to cmc.bin and put them in the board directory. -Now you can build U-Boot and obtaim u-boot.rom +Now you can build U-Boot and obtain u-boot.rom $ make crownbay_defconfig $ make all +Test with coreboot +------------------ +For testing U-Boot as the coreboot payload, there are things that need be paid +attention to. coreboot supports loading an ELF executable and a 32-bit plain +binary, as well as other supported payloads. With the default configuration, +U-Boot is set up to use a separate Device Tree Blob (dtb). As of today, the +generated u-boot-dtb.bin needs to be packaged by the cbfstool utility (a tool +provided by coreboot) manually as coreboot's 'make menuconfig' does not provide +this capability yet. The command is as follows: + +# in the coreboot root directory +$ ./build/util/cbfstool/cbfstool build/coreboot.rom add-flat-binary \ + -f u-boot-dtb.bin -n fallback/payload -c lzma -l 0x1110000 -e 0x1110015 + +Make sure 0x1110000 matches CONFIG_SYS_TEXT_BASE and 0x1110015 matches the +symbol address of _start (in arch/x86/cpu/start.S). + +If you want to use ELF as the coreboot payload, change U-Boot configuration to +use CONFIG_OF_EMBED. + CPU Microcode ------------- Modern CPU usually requires a special bit stream called microcode [5] to be @@ -106,7 +141,7 @@ x86 has been converted to use driver model for serial and GPIO. Device Tree ----------- x86 uses device tree to configure the board thus requires CONFIG_OF_CONTROL to -be turned on. Not every device on the board is configured via devie tree, but +be turned on. Not every device on the board is configured via device tree, but more and more devices will be added as time goes by. Check out the directory arch/x86/dts/ for these device tree source files. From 657e384af630463e3c8c4ffbacd16c5e46aeb0e0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 6 Jan 2015 14:35:38 +0800 Subject: [PATCH 45/45] x86: Remove CONFIG_DISPLAY_CPUINFO in chromebook_link.h CONFIG_DISPLAY_CPUINFO is already defined in x86-common.h, so remove it to avoid duplication. Signed-off-by: Bin Meng Acked-by: Simon Glass --- include/configs/chromebook_link.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index e0bf3096f6..7e6d239d13 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -20,7 +20,6 @@ #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_BOARD_EARLY_INIT_F -#define CONFIG_DISPLAY_CPUINFO #define CONFIG_NR_DRAM_BANKS 8 #define CONFIG_X86_MRC_ADDR 0xfffa0000