From b2e02d28653edac48d6def9791f2fa0ebc491498 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Dec 2014 15:50:36 +0800 Subject: x86: Add basic support to queensbay platform and crownbay board Implement minimum required functions for the basic support to queensbay platform and crownbay board. Currently the implementation is to call fsp_init() in the car_init(). We may move that call to cpu_init_f() in the future. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Makefile | 9 +++ arch/x86/cpu/queensbay/tnc.c | 48 ++++++++++++++ arch/x86/cpu/queensbay/tnc_car.S | 127 ++++++++++++++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc_dram.c | 78 +++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc_pci.c | 61 ++++++++++++++++++ arch/x86/include/asm/ibmpc.h | 3 + board/intel/crownbay/MAINTAINERS | 6 ++ board/intel/crownbay/Makefile | 7 +++ board/intel/crownbay/crownbay.c | 21 +++++++ board/intel/crownbay/start.S | 9 +++ 10 files changed, 369 insertions(+) create mode 100644 arch/x86/cpu/queensbay/Makefile create mode 100644 arch/x86/cpu/queensbay/tnc.c create mode 100644 arch/x86/cpu/queensbay/tnc_car.S create mode 100644 arch/x86/cpu/queensbay/tnc_dram.c create mode 100644 arch/x86/cpu/queensbay/tnc_pci.c create mode 100644 board/intel/crownbay/MAINTAINERS create mode 100644 board/intel/crownbay/Makefile create mode 100644 board/intel/crownbay/crownbay.c create mode 100644 board/intel/crownbay/start.S diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile new file mode 100644 index 0000000000..ace04ca4d0 --- /dev/null +++ b/arch/x86/cpu/queensbay/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2014, Bin Meng +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += tnc_car.o tnc_dram.o tnc.o +obj-y += fsp_configs.o fsp_support.o +obj-$(CONFIG_PCI) += tnc_pci.o diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c new file mode 100644 index 0000000000..8b9815fa00 --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int arch_cpu_init(void) +{ + post_code(POST_CPU_INIT); +#ifdef CONFIG_SYS_X86_TSC_TIMER + timer_set_base(rdtsc()); +#endif + + return x86_cpu_init_f(); +} + +int print_cpuinfo(void) +{ + post_code(POST_CPU_INFO); + return default_print_cpuinfo(); +} + +void reset_cpu(ulong addr) +{ + /* cold reset */ + outb(0x06, PORT_RESET); +} + +void board_final_cleanup(void) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_BOOT): "); + status = fsp_notify(NULL, INIT_PHASE_BOOT); + if (status != FSP_SUCCESS) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return; +} diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/cpu/queensbay/tnc_car.S new file mode 100644 index 0000000000..6834a6413d --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_car.S @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +.globl car_init +car_init: + /* + * Note: ebp holds the BIST value (built-in self test) so far, but ebp + * will be destroyed through the FSP call, thus we have to test the + * BIST value here before we call into FSP. + */ + test %ebp, %ebp + jz car_init_start + post_code(POST_BIST_FAILURE) + jmp die + +car_init_start: + post_code(POST_CAR_START) + lea find_fsp_header_romstack, %esp + jmp find_fsp_header + +find_fsp_header_ret: + /* EAX points to FSP_INFO_HEADER */ + mov %eax, %ebp + + /* sanity test */ + cmp $CONFIG_FSP_LOCATION, %eax + jb die + + /* calculate TempRamInitEntry address */ + mov 0x30(%ebp), %eax + add 0x1c(%ebp), %eax + + /* call FSP TempRamInitEntry to setup temporary stack */ + lea temp_ram_init_romstack, %esp + jmp *%eax + +temp_ram_init_ret: + addl $4, %esp + cmp $0, %eax + jnz car_init_fail + + post_code(POST_CAR_CPU_CACHE) + + /* + * The FSP TempRamInit initializes the ecx and edx registers to + * point to a temporary but writable memory range (Cache-As-RAM). + * ecx: the start of this temporary memory range, + * edx: the end of this range. + */ + + /* stack grows down from top of CAR */ + movl %edx, %esp + + /* + * TODO: + * + * According to FSP architecture spec, the fsp_init() will not return + * to its caller, instead it requires the bootloader to provide a + * so-called continuation function to pass into the FSP as a parameter + * of fsp_init, and fsp_init() will call that continuation function + * directly. + * + * The call to fsp_init() may need to be moved out of the car_init() + * to cpu_init_f() with the help of some inline assembly codes. + * Note there is another issue that fsp_init() will setup another stack + * using the fsp_init parameter stack_top after DRAM is initialized, + * which means any data on the previous stack (on the CAR) gets lost + * (ie: U-Boot global_data). FSP is supposed to support such scenario, + * however it does not work. This should be revisited in the future. + */ + movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax + xorl %edx, %edx + xorl %ecx, %ecx + call fsp_init + +.global fsp_init_done +fsp_init_done: + /* + * We come here from FspInit with eax pointing to the HOB list. + * Save eax to esi temporarily. + */ + movl %eax, %esi + /* + * Re-initialize the ebp (BIST) to zero, as we already reach here + * which means we passed BIST testing before. + */ + xorl %ebp, %ebp + jmp car_init_ret + +car_init_fail: + post_code(POST_CAR_FAILURE) + +die: + hlt + jmp die + hlt + + /* + * The function call before CAR initialization is tricky. It cannot + * be called using the 'call' instruction but only the 'jmp' with + * the help of a handcrafted stack in the ROM. The stack needs to + * contain the function return address as well as the parameters. + */ + .balign 4 +find_fsp_header_romstack: + .long find_fsp_header_ret + + .balign 4 +temp_ram_init_romstack: + .long temp_ram_init_ret + .long temp_ram_init_params +temp_ram_init_params: + .long ucode_start /* microcode base */ + .long ucode_size /* microcode size */ + .long CONFIG_SYS_MONITOR_BASE /* code region base */ + .long CONFIG_SYS_MONITOR_LEN /* code region size */ + + .balign 4 +ucode_start: + .include "arch/x86/cpu/queensbay/M0220661105.inc" +ucode_size = ( . - ucode_start) diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c new file mode 100644 index 0000000000..dbc17102da --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + phys_size_t ram_size = 0; + union hob_pointers_t hob; + + hob.raw = gd->arch.hob_list; + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == 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; + } + } + hob.raw = GET_NEXT_HOB(hob); + } + + gd->ram_size = ram_size; + post_code(POST_DRAM); + + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; +} + +/* + * This function looks for the highest region of memory lower than 4GB which + * has enough space for U-Boot where U-Boot is aligned on a page boundary. + * It overrides the default implementation found elsewhere which simply + * picks the end of ram, wherever that may be. The location of the stack, + * the relocation address, and how far U-Boot is moved by relocation are + * set in the global data structure. + */ +ulong board_get_usable_ram_top(ulong total_size) +{ + return get_usable_lowmem_top(gd->arch.hob_list); +} + +unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) +{ + unsigned num_entries = 0; + + union hob_pointers_t hob; + + hob.raw = gd->arch.hob_list; + + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == 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) + entries[num_entries].type = E820_RAM; + else if (hob.res_desc->type == RES_MEM_RESERVED) + entries[num_entries].type = E820_RESERVED; + } + hob.raw = GET_NEXT_HOB(hob); + num_entries++; + } + + return num_entries; +} diff --git a/arch/x86/cpu/queensbay/tnc_pci.c b/arch/x86/cpu/queensbay/tnc_pci.c new file mode 100644 index 0000000000..39bff49c8d --- /dev/null +++ b/arch/x86/cpu/queensbay/tnc_pci.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +void board_pci_setup_hose(struct pci_controller *hose) +{ + hose->first_busno = 0; + hose->last_busno = 0; + + /* PCI memory space */ + pci_set_region(hose->regions + 0, + CONFIG_PCI_MEM_BUS, + CONFIG_PCI_MEM_PHYS, + CONFIG_PCI_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 1, + CONFIG_PCI_IO_BUS, + CONFIG_PCI_IO_PHYS, + CONFIG_PCI_IO_SIZE, + PCI_REGION_IO); + + pci_set_region(hose->regions + 2, + CONFIG_PCI_PREF_BUS, + CONFIG_PCI_PREF_PHYS, + CONFIG_PCI_PREF_SIZE, + PCI_REGION_PREFETCH); + + pci_set_region(hose->regions + 3, + 0, + 0, + gd->ram_size, + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); + + hose->region_count = 4; +} + +int board_pci_post_scan(struct pci_controller *hose) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); + status = fsp_notify(NULL, INIT_PHASE_PCI); + if (status != FSP_SUCCESS) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return 0; +} diff --git a/arch/x86/include/asm/ibmpc.h b/arch/x86/include/asm/ibmpc.h index e6d183b479..c3b5187c22 100644 --- a/arch/x86/include/asm/ibmpc.h +++ b/arch/x86/include/asm/ibmpc.h @@ -18,4 +18,7 @@ #define SYSCTLA 0x92 #define SLAVE_PIC 0xa0 +#define UART0_BASE 0x3f8 +#define UART1_BASE 0x2f8 + #endif diff --git a/board/intel/crownbay/MAINTAINERS b/board/intel/crownbay/MAINTAINERS new file mode 100644 index 0000000000..1eb68693df --- /dev/null +++ b/board/intel/crownbay/MAINTAINERS @@ -0,0 +1,6 @@ +INTEL CROWNBAY BOARD +M: Bin Meng +S: Maintained +F: board/intel/crownbay/ +F: include/configs/crownbay.h +F: configs/crownbay_defconfig diff --git a/board/intel/crownbay/Makefile b/board/intel/crownbay/Makefile new file mode 100644 index 0000000000..aeb219b4e5 --- /dev/null +++ b/board/intel/crownbay/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2014, Bin Meng +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += crownbay.o start.o diff --git a/board/intel/crownbay/crownbay.c b/board/intel/crownbay/crownbay.c new file mode 100644 index 0000000000..8c6df98bf7 --- /dev/null +++ b/board/intel/crownbay/crownbay.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#define SERIAL_DEV PNP_DEV(0x2e, 4) + +DECLARE_GLOBAL_DATA_PTR; + +int board_early_init_f(void) +{ + lpc47m_enable_serial(SERIAL_DEV, UART0_BASE); + + return 0; +} diff --git a/board/intel/crownbay/start.S b/board/intel/crownbay/start.S new file mode 100644 index 0000000000..cf92b4c0b3 --- /dev/null +++ b/board/intel/crownbay/start.S @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.globl early_board_init +early_board_init: + jmp early_board_init_ret -- cgit v1.2.3