x86: Add Intel Tangier support
Add Intel Tangier SoC support. Intel Tangier SoC is a core part of Intel Merrifield platform. For example, Intel Edison board is based on such platform. The patch is based on work done by the following people (in alphabetical order): Aiden Park <aiden.park@intel.com> Dukjoon Jeon <dukjoon.jeon@intel.com> eric.park <eric.park@intel.com> Fabien Chereau <fabien.chereau@intel.com> Scott D Phillips <scott.d.phillips@intel.com> Sebastien Colleur <sebastienx.colleur@intel.com> Steve Sakoman <steve.sakoman@intel.com> Vincent Tinelli <vincent.tinelli@intel.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Signed-off-by: Vincent Tinelli <vincent.tinelli@intel.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
		
							parent
							
								
									b7026b0c98
								
							
						
					
					
						commit
						e71de54a49
					
				|  | @ -114,6 +114,7 @@ source "arch/x86/cpu/ivybridge/Kconfig" | |||
| source "arch/x86/cpu/qemu/Kconfig" | ||||
| source "arch/x86/cpu/quark/Kconfig" | ||||
| source "arch/x86/cpu/queensbay/Kconfig" | ||||
| source "arch/x86/cpu/tangier/Kconfig" | ||||
| 
 | ||||
| # architecture-specific options below | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ obj-$(CONFIG_QEMU) += qemu/ | |||
| obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ | ||||
| obj-$(CONFIG_INTEL_QUARK) += quark/ | ||||
| obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ | ||||
| obj-$(CONFIG_INTEL_TANGIER) += tangier/ | ||||
| obj-y += lapic.o ioapic.o | ||||
| obj-y += irq.o | ||||
| ifndef CONFIG_$(SPL_)X86_64 | ||||
|  |  | |||
|  | @ -0,0 +1,20 @@ | |||
| # | ||||
| # Copyright (c) 2017 Intel Corporation | ||||
| # | ||||
| # SPDX-License-Identifier:	GPL-2.0+ | ||||
| # | ||||
| 
 | ||||
| config INTEL_TANGIER | ||||
| 	bool | ||||
| 	depends on INTEL_MID | ||||
| 
 | ||||
| config SYS_CAR_ADDR | ||||
| 	hex | ||||
| 	default 0x19200000 | ||||
| 
 | ||||
| config SYS_CAR_SIZE | ||||
| 	hex | ||||
| 	default 0x4000 | ||||
| 	help | ||||
| 	  Space in bytes in eSRAM used as Cache-As-RAM (CAR). | ||||
| 	  Note this size must not exceed eSRAM's total size. | ||||
|  | @ -0,0 +1,7 @@ | |||
| #
 | ||||
| # Copyright (c) 2017 Intel Corporation
 | ||||
| #
 | ||||
| # SPDX-License-Identifier:	GPL-2.0+
 | ||||
| #
 | ||||
| 
 | ||||
| obj-y += car.o tangier.o sdram.o | ||||
|  | @ -0,0 +1,13 @@ | |||
| /* | ||||
|  * Copyright (c) 2011 The Chromium OS Authors. | ||||
|  * (C) Copyright 2010-2011 | ||||
|  * Graeme Russ, <graeme.russ@gmail.com>
 | ||||
|  * | ||||
|  * SPDX-License-Identifier:	GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| .section .text | ||||
| 
 | ||||
| .globl car_init
 | ||||
| car_init: | ||||
| 	jmp	car_init_ret | ||||
|  | @ -0,0 +1,206 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2017 Intel Corporation | ||||
|  * | ||||
|  * SPDX-License-Identifier:	GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| #include <common.h> | ||||
| #include <asm/e820.h> | ||||
| #include <asm/global_data.h> | ||||
| #include <asm/sfi.h> | ||||
| 
 | ||||
| DECLARE_GLOBAL_DATA_PTR; | ||||
| 
 | ||||
| /*
 | ||||
|  * SFI tables are part of the first stage bootloader. | ||||
|  * | ||||
|  * U-Boot finds the System Table by searching 16-byte boundaries between | ||||
|  * physical address 0x000E0000 and 0x000FFFFF. U-Boot shall search this region | ||||
|  * starting at the low address and shall stop searching when the 1st valid SFI | ||||
|  * System Table is found. | ||||
|  */ | ||||
| #define SFI_BASE_ADDR		0x000E0000 | ||||
| #define SFI_LENGTH		0x00020000 | ||||
| #define SFI_TABLE_LENGTH	16 | ||||
| 
 | ||||
| static int sfi_table_check(struct sfi_table_header *sbh) | ||||
| { | ||||
| 	char chksum = 0; | ||||
| 	char *pos = (char *)sbh; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	if (sbh->len < SFI_TABLE_LENGTH) | ||||
| 		return -ENXIO; | ||||
| 
 | ||||
| 	if (sbh->len > SFI_LENGTH) | ||||
| 		return -ENXIO; | ||||
| 
 | ||||
| 	for (i = 0; i < sbh->len; i++) | ||||
| 		chksum += *pos++; | ||||
| 
 | ||||
| 	if (chksum) | ||||
| 		error("sfi: Invalid checksum\n"); | ||||
| 
 | ||||
| 	/* Checksum is OK if zero */ | ||||
| 	return chksum ? -EILSEQ : 0; | ||||
| } | ||||
| 
 | ||||
| static int sfi_table_is_type(struct sfi_table_header *sbh, const char *signature) | ||||
| { | ||||
| 	return !strncmp(sbh->sig, signature, SFI_SIGNATURE_SIZE) && | ||||
| 	       !sfi_table_check(sbh); | ||||
| } | ||||
| 
 | ||||
| static struct sfi_table_simple *sfi_get_table_by_sig(unsigned long addr, | ||||
| 						     const char *signature) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	for (i = 0; i < SFI_LENGTH; i += SFI_TABLE_LENGTH) { | ||||
| 		sb = (struct sfi_table_simple *)(addr + i); | ||||
| 		if (sfi_table_is_type(&sb->header, signature)) | ||||
| 			return sb; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static struct sfi_table_simple *sfi_search_mmap(void) | ||||
| { | ||||
| 	struct sfi_table_header *sbh; | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	u32 sys_entry_cnt; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	/* Find SYST table */ | ||||
| 	sb = sfi_get_table_by_sig(SFI_BASE_ADDR, SFI_SIG_SYST); | ||||
| 	if (!sb) { | ||||
| 		error("sfi: failed to locate SYST table\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	sys_entry_cnt = (sb->header.len - sizeof(*sbh)) / 8; | ||||
| 
 | ||||
| 	/* Search through each SYST entry for MMAP table */ | ||||
| 	for (i = 0; i < sys_entry_cnt; i++) { | ||||
| 		sbh = (struct sfi_table_header *)(unsigned long)sb->pentry[i]; | ||||
| 
 | ||||
| 		if (sfi_table_is_type(sbh, SFI_SIG_MMAP)) | ||||
| 			return (struct sfi_table_simple *)sbh; | ||||
| 	} | ||||
| 
 | ||||
| 	error("sfi: failed to locate SFI MMAP table\n"); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| #define sfi_for_each_mentry(i, sb, mentry)				\ | ||||
| 	for (i = 0, mentry = (struct sfi_mem_entry *)sb->pentry;	\ | ||||
| 	     i < SFI_GET_NUM_ENTRIES(sb, struct sfi_mem_entry);		\ | ||||
| 	     i++, mentry++)						\ | ||||
| 
 | ||||
| static unsigned sfi_setup_e820(unsigned max_entries, struct e820entry *entries) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	struct sfi_mem_entry *mentry; | ||||
| 	unsigned long long start, end, size; | ||||
| 	int type, total = 0; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	sb = sfi_search_mmap(); | ||||
| 	if (!sb) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	sfi_for_each_mentry(i, sb, mentry) { | ||||
| 		start = mentry->phys_start; | ||||
| 		size = mentry->pages << 12; | ||||
| 		end = start + size; | ||||
| 
 | ||||
| 		if (start > end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* translate SFI mmap type to E820 map type */ | ||||
| 		switch (mentry->type) { | ||||
| 		case SFI_MEM_CONV: | ||||
| 			type = E820_RAM; | ||||
| 			break; | ||||
| 		case SFI_MEM_UNUSABLE: | ||||
| 		case SFI_RUNTIME_SERVICE_DATA: | ||||
| 			continue; | ||||
| 		default: | ||||
| 			type = E820_RESERVED; | ||||
| 		} | ||||
| 
 | ||||
| 		if (total == E820MAX) | ||||
| 			break; | ||||
| 		entries[total].addr = start; | ||||
| 		entries[total].size = size; | ||||
| 		entries[total].type = type; | ||||
| 
 | ||||
| 		total++; | ||||
| 	} | ||||
| 
 | ||||
| 	return total; | ||||
| } | ||||
| 
 | ||||
| static int sfi_get_bank_size(void) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	struct sfi_mem_entry *mentry; | ||||
| 	int bank = 0; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	sb = sfi_search_mmap(); | ||||
| 	if (!sb) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	sfi_for_each_mentry(i, sb, mentry) { | ||||
| 		if (mentry->type != SFI_MEM_CONV) | ||||
| 			continue; | ||||
| 
 | ||||
| 		gd->bd->bi_dram[bank].start = mentry->phys_start; | ||||
| 		gd->bd->bi_dram[bank].size = mentry->pages << 12; | ||||
| 		bank++; | ||||
| 	} | ||||
| 
 | ||||
| 	return bank; | ||||
| } | ||||
| 
 | ||||
| static phys_size_t sfi_get_ram_size(void) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	struct sfi_mem_entry *mentry; | ||||
| 	phys_size_t ram = 0; | ||||
| 	u32 i; | ||||
| 
 | ||||
| 	sb = sfi_search_mmap(); | ||||
| 	if (!sb) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	sfi_for_each_mentry(i, sb, mentry) { | ||||
| 		if (mentry->type != SFI_MEM_CONV) | ||||
| 			continue; | ||||
| 
 | ||||
| 		ram += mentry->pages << 12; | ||||
| 	} | ||||
| 
 | ||||
| 	debug("sfi: RAM size %llu\n", ram); | ||||
| 	return ram; | ||||
| } | ||||
| 
 | ||||
| unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) | ||||
| { | ||||
| 	return sfi_setup_e820(max_entries, entries); | ||||
| } | ||||
| 
 | ||||
| int dram_init_banksize(void) | ||||
| { | ||||
| 	sfi_get_bank_size(); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int dram_init(void) | ||||
| { | ||||
| 	gd->ram_size = sfi_get_ram_size(); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2017 Intel Corporation | ||||
|  * | ||||
|  * SPDX-License-Identifier:	GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| #include <common.h> | ||||
| #include <asm/scu.h> | ||||
| #include <asm/u-boot-x86.h> | ||||
| 
 | ||||
| DECLARE_GLOBAL_DATA_PTR; | ||||
| 
 | ||||
| /*
 | ||||
|  * Miscellaneous platform dependent initializations | ||||
|  */ | ||||
| int arch_cpu_init(void) | ||||
| { | ||||
| 	return x86_cpu_init_f(); | ||||
| } | ||||
| 
 | ||||
| int checkcpu(void) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int print_cpuinfo(void) | ||||
| { | ||||
| 	return default_print_cpuinfo(); | ||||
| } | ||||
| 
 | ||||
| void reset_cpu(ulong addr) | ||||
| { | ||||
| 	scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); | ||||
| } | ||||
|  | @ -60,6 +60,25 @@ struct __packed sfi_mem_entry { | |||
| 	u64	attrib; | ||||
| }; | ||||
| 
 | ||||
| /* Memory type definitions */ | ||||
| enum sfi_mem_type { | ||||
| 	SFI_MEM_RESERVED, | ||||
| 	SFI_LOADER_CODE, | ||||
| 	SFI_LOADER_DATA, | ||||
| 	SFI_BOOT_SERVICE_CODE, | ||||
| 	SFI_BOOT_SERVICE_DATA, | ||||
| 	SFI_RUNTIME_SERVICE_CODE, | ||||
| 	SFI_RUNTIME_SERVICE_DATA, | ||||
| 	SFI_MEM_CONV, | ||||
| 	SFI_MEM_UNUSABLE, | ||||
| 	SFI_ACPI_RECLAIM, | ||||
| 	SFI_ACPI_NVS, | ||||
| 	SFI_MEM_MMIO, | ||||
| 	SFI_MEM_IOPORT, | ||||
| 	SFI_PAL_CODE, | ||||
| 	SFI_MEM_TYPEMAX, | ||||
| }; | ||||
| 
 | ||||
| struct __packed sfi_cpu_table_entry { | ||||
| 	u32	apic_id; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue